class MomoAfternoonBreakoutDailyTrigger(DailyTrigger): def __init__(self, settings): DailyTrigger.__init__(self, settings) self.minprice = settings.getfloat("Strategy", "minprice") self.minvolume = settings.getint("Strategy", "minvolume") self.minmove = settings.getfloat("Strategy", "minmove") smatrend = settings.get("Strategy", "dailysmatrendfilter") if smatrend == "None": self.dailysmatrendfilter = None else: self.dailysmatrendfilter = int(smatrend) self.volume = Volume() self.avgvol = SimpleMovingAverage(self.volume, 21) self.close = Close() if self.dailysmatrendfilter is not None: self.ma = SimpleMovingAverage(period=self.dailysmatrendfilter) else: self.ma = None def ready(self): return (self.ma is None or self.ma.ready()) and self.avgvol.ready() and self.close.ready() def check(self): if self.ready() and self.lastpd is not None: # todo would be a lot faster if I could implement a peek at today to check the move is big enough if self.close.value() >= self.minprice \ and (self.ma is None or self.close.value() > self.ma.value()) \ and self.avgvol.value() >= self.minvolume \ and ((self.peekpd.high - self.peekpd.open) / self.peekpd.open) >= self.minmove: return True return False def handle(self, perioddata): if self.ma is not None: self.ma.handle(perioddata) self.volume.handle(perioddata) self.avgvol.handle(perioddata) self.close.handle(perioddata) self.lastpd = perioddata def recommendedPreload(self): mapreload = 0 if self.ma is not None: mapreload = self.ma.recommendedPreload() return max(mapreload, self.avgvol.recommendedPreload())
class MomoPullbackEntryManager(EntryManager): """ Enter at a moving average after a minimum move. Stop is set at a percentage between the moving average and the low of day. """ def __init__(self, settings, name=None): EntryManager.__init__(self, settings, name) self.minhour = settings.getint("Strategy", "minhour") self.maxhour = settings.getint("Strategy", "maxhour") self.target = self._getintsetting("Strategy", "target") self.minmove = settings.getfloat("Strategy", "minmove") self.maxprice = self._getfloatsetting("Strategy", "maxprice") self.maperiod = self._getintsetting("Strategy", "ma") self.stopPercentToLow = self._getfloatsetting("Strategy", "stopPercentToLow") self.hod = None self.open = None self.hoddate = None self.low = None self.close = Close() self.ma = ExponentialMovingAverage(metric=self.close, period=self.maperiod) self.mademove = False self.lastpd = None def handle(self, perioddata): self.close.handle(perioddata) self.ma.handle(perioddata) if self.lastpd is not None and self.lastpd.date.day != perioddata.date.day: self.low = None self.hod = None self.hoddate = None self.mademove = False if self.open is None: self.open = perioddata.open if self.lastpd is not None and (self.low is None or self.lastpd.low < self.low): self.low = self.lastpd.low if self.periodData is not None: # quick, use previous value to update hod if self.hod is None or self.periodData.high >= self.hod: self.hod = self.periodData.high self.hoddate = self.periodData.date if not self.mademove and self.low is not None and self.hod is not None and self.open is not None and ( self.hod - self.open) / self.open >= self.minmove: logger.debug("saw minimum desired move in MomoPullbackManager, waiting for pullback") self.mademove = True EntryManager.handle(self, perioddata) self.lastpd = perioddata def checkTrade(self, trade): if trade is not None: # no scale ins return trade if self.mademove \ and self.periodData.date.hour >= self.minhour \ and (self.periodData.date.hour < self.maxhour or (self.periodData.date.hour == self.maxhour and self.periodData.date.minute == 0)) \ and self.periodData.low <= self.ma.value(): # we have an entry entry = min(self.periodData.open, self.ma.value()) if self.maxprice is None or entry <= self.maxprice: stop = self.low - 0.01 if self.stopPercentToLow is not None: stop = entry - (self.stopPercentToLow * (entry - self.low)) # at least 10c if stop >= entry - 0.1: stop = entry - 0.1 trade = Trade(self.periodData.stock, self.periodData.date, entry, stop) if self.target is not None: target = entry + ((entry - stop) * self.target) trade.target = target if self.periodData.low < stop: trade.exit = self.periodData.date trade.exitPrice = stop return trade return None
def findsetups(self, fromdt, todt): stocks = self._getTickers(fromdt, datastore) for stock in stocks: close = Close() sma = None if self.dailysmatrendfilter != None: sma = SimpleMovingAverage(close, period=self.dailysmatrendfilter) # padded extra to make sure 50 day sma has enough trading days to work with before our window dailydata = datastore.getDailyData(stock, fromdt - timedelta(days=100), todt) prevpd = None for pd in dailydata: if prevpd != None and pd.date >= fromdt: trade = None if pd.open == prevpd.close or prevpd.close == 0: gapsize=0 else: gapsize = (prevpd.close - pd.open)/prevpd.close if gapsize >= self.mingap and (sma == None or (sma.ready() and pd.open < sma.value())) and pd.open >= self.minprice: intrafromdt = pd.date intratodt = pd.date + timedelta(hours=24) intradaydata = iter(datastore.getIntradayData(stock, 300, intrafromdt, intratodt)) try: intradaypd = intradaydata.next() entry = None lod = intradaypd.low prevpd = intradaypd high = High() highesthigh = Highest(metric=high, period=self.donchianstop) high.handle(intradaypd) highesthigh.handle(intradaypd) for intradaypd in intradaydata: if trade == None \ and highesthigh.ready() \ and intradaypd.date.hour >= self.minhour \ and (intradaypd.date.hour < self.maxhour \ or (intradaypd.date.hour == self.maxhour and intradaypd.date.minute==0)) \ and intradaypd.low < lod: entry = lod - 0.01 trade = Trade(stock, intradaypd.date, min(entry, intradaypd.open), highesthigh.value()+0.01) if self.target != None: trade.target = trade.entryPrice + (self.target * (trade.entryPrice-trade.stop)) if trade != None and trade.exit == None: if intradaypd.high >= trade.trailingstop: trade.exit = intradaypd.date trade.exitPrice = max(trade.stop, intradaypd.open) if trade.exit == None and trade.target != None and intradaypd.low <= trade.target: trade.exit = intradaypd.date trade.exitPrice = min(intradaypd.open, trade.target) if intradaypd.low < lod: lod = intradaypd.low high.handle(intradaypd) highesthigh.handle(intradaypd) except StopIteration: pass # eod, close it if it is still open if trade != None and trade.exit == None: trade.exit = intradaypd.date trade.exitPrice = intradaypd.close if trade != None: self.tradeManager.addTrade(trade) # now we can update the indicators - since we finished trading the day close.handle(pd) if sma != None: sma.handle(pd) prevpd = pd return self.tradeManager.getStats()
def findsetups(self, fromdt, todt): numstopouts = 0 stocks = self._getTickers(fromdt, datastore) for stock in stocks: # padded extra to make sure 200 day sma has enough trading days to work with before our window dailydata = datastore.getDailyData(stock, fromdt - timedelta(days=(self.slowma*2)), todt) close = Close() fastma = SimpleMovingAverage(period=self.fastma) slowma = SimpleMovingAverage(period=self.slowma) lastfastma = HistoricMetric(metric=fastma, period=1) lastslowma = HistoricMetric(metric=slowma, period=1) atr = ATR(period=14) lastdd = None trade = None for pd in dailydata: close.handle(pd) fastma.handle(pd) slowma.handle(pd) lastfastma.handle(pd) lastslowma.handle(pd) atr.handle(pd) # check for long stopout if trade != None and pd.low < trade.trailingstop: trade.exit = pd.date trade.exitPrice = min(pd.open, trade.trailingstop) self.tradeManager.addTrade(trade) numstopouts = numstopouts + 1 trade = None # check for long exit if trade != None and fastma.value() < slowma.value(): trade.exit = pd.date trade.exitPrice = pd.close self.tradeManager.addTrade(trade) trade = None if fastma.ready() and slowma.ready() and lastfastma.ready() and lastslowma.ready() and atr.ready(): pass # check for new long if trade == None and fastma.ready() and slowma.ready() \ and lastfastma.ready() and lastslowma.ready() \ and (self.atrStop == None or atr.ready()) \ and pd.date >= fromdt \ and fastma.value() > slowma.value() \ and lastfastma.value() <= lastslowma.value() \ and pd.close >= self.minprice: stop = 0 if self.atrStop != None: stop = max(0,pd.close - (float(self.atrStop) * atr.value())) if self.percentStop != None: stop = max(0, pd.close * (1.0 - self.percentStop)) trade = Trade(stock=stock, entry=pd.date, entryPrice=pd.close, stop=stop) if trade != None and trade.entry == None: trade.exit = lastdd.date trade.exitPrice = lastdd.close self.tradeManager.addTrade(trade) trade = None print "num stopouts was %d" % numstopouts return self.tradeManager.getStats()