package dailyBot.model; import java.util.LinkedList; import java.util.List; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantReadWriteLock; import dailyBot.control.DailyLog; import dailyBot.control.DailyUtils; import dailyBot.control.connection.SqlConnection; import dailyBot.control.connection.XMLPersistentObject; import dailyBot.model.SignalProvider.SignalProviderId; public class Strategy extends XMLPersistentObject { public enum StrategyId { BREAKOUT1, BREAKOUT2, RANGE1, RANGE2, MOMENTUM1, MOMENTUM2; volatile transient Strategy thisStategy = null; public Strategy strategy() { if(thisStategy == null) DailyLog.logError("Estrategia " + this + " fue llamada antes de ser registrada."); return thisStategy; } public void startStrategy() { thisStategy = Strategy.readPersistency(this); if(thisStategy == null) thisStategy = new Strategy(this); for(StrategySignal signal : thisStategy.signals) signal.getPair().addSignal(signal); } } protected StrategyId id; protected List <StrategySignal> signals = new LinkedList <StrategySignal>(); protected final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock(true); protected final Lock read = readWriteLock.readLock(); protected final Lock write = DailyUtils.getSafeWriteLock(readWriteLock); public Strategy() { } public Strategy(StrategyId id) { this.id = id; } public void processSignalChange(Pair pair, boolean hit, boolean buy, int lotNumber, double entryPrice, StrategySignal affected) { if(hit) { affected.setLotNumber(affected.getLotNumber() - lotNumber); if(affected.getLotNumber() <= 0) { SqlConnection.addRecord(id, affected); for(SignalProviderId signalProviderId : SignalProviderId.values()) signalProviderId.signalProvider().processSignal(affected, hit); write.lock(); try { signals.remove(affected); } finally { write.unlock(); } affected.getPair().deleteSignal(affected); } } else { StrategySignal newSignal = new StrategySignal(id, buy, pair, lotNumber, entryPrice, 0, true); if(hasPair(pair) != null) { DailyLog.logError("Error, par: " + pair + ", ya existe en esta estrategia " + id.toString()); return; } write.lock(); try { signals.add(newSignal); } finally { write.unlock(); } newSignal.getPair().addSignal(newSignal); for(SignalProviderId signalProviderId : SignalProviderId.values()) signalProviderId.signalProvider().processSignal(newSignal, hit); } } public StrategySignal hasPair(Pair par) { read.lock(); try { for(StrategySignal signal : signals) if(signal.getPair().equals(par)) return signal; } finally { read.unlock(); } return null; } public boolean checkConsistency() { read.lock(); try { return signals == null || id == null; } finally { read.unlock(); } } public void writePersistency() { read.lock(); try { writeObject(); } catch(Exception e) { DailyLog.logError("Error en la escritura en la base de datos: " + id.name() + " " + e.getMessage()); } finally { read.unlock(); } } public static Strategy readPersistency(StrategyId id) { try { return XMLPersistentObject.readObject(Strategy.class, id.ordinal()); } catch(Exception e) { DailyLog.logError("Error de lectura de base de datos: " + id.name()); DailyLog.tryInmediateReboot(); return null; } } public List <StrategySignal> duplicateSignals() { read.lock(); try { if(signals == null) return null; else return new LinkedList <StrategySignal>(signals); } finally { read.unlock(); } } public List <StrategySignal> getSignals() { read.lock(); try { return signals; } finally { read.unlock(); } } public void setSignals(List <StrategySignal> signals) { write.lock(); try { if(signals != null) this.signals = new LinkedList <StrategySignal>(signals); else this.signals = null; } finally { write.unlock(); } for(StrategySignal signal : signals) signal.getPair().addSignal(signal); } public StrategyId getId() { read.lock(); try { return id; } finally { read.unlock(); } } public void setId(StrategyId id) { write.lock(); try { this.id = id; } finally { write.unlock(); } } @Override protected int objectId() { return id.ordinal(); } }