def __init__(self, settings): PriceVolumeDailyTrigger.__init__(self, settings) self.minatrmultiple = settings.getfloat("MomoDailyTrigger", "minatrmultiple") self.closepercent = settings.get("MomoDailyTrigger", "closepercent") self.openpercent = settings.get("MomoDailyTrigger", "openpercent") self.takeLongs = settings.getboolean("MomoDailyTrigger", "takeLongs") self.takeShorts = settings.getboolean("MomoDailyTrigger", "takeShorts") minaprstr = settings.get("MomoDailyTrigger", "minapr") self.minapr = None if minaprstr != "None": self.minapr = float(minaprstr) dfilter = settings.get("MomoDailyTrigger", "donchianfilter") self.high = High() self.low = Low() self.atr = ATR(14) self.lastatr = HistoricMetric(self.atr, 1) if dfilter == "None": self.lasthighesthigh = None self.lastlowestlow = None else: self.highesthigh = Highest(self.high, int(dfilter)) self.lasthighesthigh = HistoricMetric(self.highesthigh, 1) self.lowestlow = Lowest(self.low, int(dfilter)) self.lastlowestlow = HistoricMetric(self.lowestlow, 1)
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()
def findsetups(self, fromdt, todt): datastore = datastorefactory.get_datastore() # stocks = datastore.filterStocksByAvgVolume(fromdt, minvolume) stocks = self._getTickers(fromdt, datastore) for stock in stocks: dailydata = list() volume = Volume() avgvolume = SimpleMovingAverage(metric=volume, period=21) dailyatr = ATR(20) atrfromdt = fromdt - timedelta(days=max(self.duration, 40)) # 40 to give the atr time to normalize dailydataiter = iter(datastore.getDailyData(stock, atrfromdt, todt)) dailydataday = None try: while dailydataday == None or dailydataday.date < fromdt: dailydataday = dailydataiter.next() # have to fix it to a real object for the atr dailyatr.handle(dailydataday) dailydata.append(dailydataday) except StopIteration: pass if len(dailydata) > self.duration: dailydata = dailydata[len(dailydata) - self.duration :] # ok, we find the highest high and lowest low first high = 0 low = None for ddhighfinder in dailydata: if high < ddhighfinder.high: high = ddhighfinder.high if low == None or ddhighfinder.low < low: low = ddhighfinder.low # great, now we find how many lower highs are within the mush factor atrmush = 0 if dailyatr.value() != None: atrmush = dailyatr.value() * self.mushinessatr taps = 0 shorttaps = 0 for ddtapfinder in dailydata: delta = high - ddtapfinder.high if delta <= atrmush or delta <= self.mushinessfixed: taps = taps + 1 shortdelta = ddtapfinder.low - low if shortdelta <= atrmush or delta <= self.mushinessfixed: shorttaps = shorttaps + 1 # ok, now we can add the next dd - we go ahead and prep some things for the next loop pass # since we are no longer using them now for dailydataday in dailydataiter: saveatr = dailyatr.value() volume.handle(dailydataday) avgvolume.handle(dailydataday) dailyatr.handle(dailydataday) dailydata.append(dailydataday) dailydata = dailydata[1:] trade = None # as a hack, now we can check our peek ahead and see for free if we # ever broke the high today. If not, we are done if ( self.doLongs and taps >= self.numtaps and dailydataday.high > high and high >= self.minprice and (self.maxprice == None or high <= self.maxprice) and avgvolume.ready() and avgvolume.value() >= self.minavgvolume and ( self.minAPR == None or (dailyatr.ready() and dailyatr.value() / dailydataday.adjustedClose) >= self.minAPR ) ): # ok, we need to scan the day low = None donchlow = None if self.donchianstop != None: low = Low() donchlow = Lowest(low, self.donchianstop) intrafromdt = dailydataday.date intratodt = intrafromdt + timedelta(hours=24) intradaydata = datastore.getIntradayData(stock, self.period, intrafromdt, intratodt) if intradaydata != None and len(intradaydata) > 1: intradaybar = intradaydata[0] intralow = intradaybar.low intrahigh = intradaybar.high taps = 1 for i in range(1, len(intradaydata)): intradaybar = intradaydata[i] if trade == None and ( self.maxintradayrangeatr == None or (saveatr != None and (intrahigh - intralow) < (saveatr * self.maxintradayrangeatr)) ): intralow = min(intralow, intradaybar.low) if ( intradaybar.high <= intrahigh and (intrahigh - intradaybar.high) <= self.mushinessfixed2m ): taps = taps + 1 if intradaybar.high > intrahigh: if ( taps >= self.taps2m and intrahigh >= high and ( self.maxhour == None or intradaybar.date.hour < self.maxhour or (intradaybar.date.hour == self.maxhour and intradaybar.date.minute == 0) ) and (self.minhour == None or intradaybar.date.hour >= self.minhour) ): # trade entry if donchlow != None and donchlow.ready(): stop = donchlow.value() - 0.01 else: stop = intralow - 0.01 entryPrice = min(intradaybar.open, intrahigh + 0.01) if entryPrice > stop: trade = Trade( stock=stock, entry=intradaybar.date, entryPrice=min(intradaybar.open, intrahigh + 0.01), stop=stop, ) if self.target: trade.target = trade.entryPrice + ( self.target * (trade.entryPrice - trade.stop) ) else: # need to recalculate taps off this new high as we had no signal yet intrahigh = intradaybar.high taps = 1 for j in range(0, i - 1): if (intrahigh - intradaydata[j].high) < self.mushinessfixed2m: taps = taps + 1 if trade and trade.exit == None: if intradaybar.low < trade.trailingstop: # taken out trade.exit = intradaybar.date trade.exitPrice = min(intradaybar.open, trade.trailingstop) if trade.target != None and intradaybar.high > trade.target: trade.exit = intradaybar.date trade.exitPrice = max(intradaybar.open, trade.target) if low != None: low.handle(intradaybar) if donchlow != None: donchlow.handle(intradaybar) if trade != None and trade.exit == None: trade.exit = intradaybar.date trade.exitPrice = intradaybar.close if trade: self.tradeManager.addTrade(trade) trade = None trade = None # SHORTS # as a hack, now we can check our peek ahead and see for free if we # ever broke the low today. If not, we are done if ( self.doShorts and shorttaps >= self.numtaps and dailydataday.low < low and low >= self.minprice and avgvolume.ready() and avgvolume.value() >= self.minavgvolume and ( self.minAPR == None or (dailyatr.ready() and dailyatr.value() / dailydataday.adjustedClose) >= self.minAPR ) ): # ok, we need to scan the day high = None donchhigh = None if self.donchianstop != None: high = High() donchhigh = Highest(high, self.donchianstop) intrafromdt = dailydataday.date intratodt = intrafromdt + timedelta(hours=24) intradaydata = datastore.getIntradayData(stock, 300, intrafromdt, intratodt) if intradaydata != None and len(intradaydata) > 1: intradaybar = intradaydata[0] intralow = intradaybar.low intrahigh = intradaybar.high taps = 1 for i in range(1, len(intradaydata)): intradaybar = intradaydata[i] if trade == None and ( self.maxintradayrangeatr == None or (saveatr != None and (intrahigh - intralow) < (saveatr * self.maxintradayrangeatr)) ): intrahigh = max(intrahigh, intradaybar.high) if ( intradaybar.low >= intralow and (intradaybar.low - intralow) <= self.mushinessfixed2m ): taps = taps + 1 if intradaybar.low < intralow: if ( taps >= self.taps2m and intralow <= low and ( self.maxhour == None or intradaybar.date.hour < self.maxhour or (intradaybar.date.hour == self.maxhour and intradaybar.date.minute == 0) ) and (self.minhour == None or intradaybar.date.hour >= self.minhour) ): # trade entry if donchhigh != None and donchhigh.ready(): stop = donchhigh.value() + 0.01 else: stop = intrahigh + 0.01 entryPrice = min(intradaybar.open, intralow - 0.01) if entryPrice < stop: trade = Trade( stock=stock, entry=intradaybar.date, entryPrice=entryPrice, stop=stop ) if self.target: trade.target = trade.entryPrice - ( self.target * (trade.stop - trade.entryPrice) ) else: # need to recalculate taps off this new high as we had no signal yet intralow = intradaybar.low taps = 1 for j in range(0, i - 1): if (intralow - intradaydata[j].low) < self.mushinessfixed2m: taps = taps + 1 if trade and trade.exit == None: if intradaybar.high >= trade.trailingstop: # taken out trade.exit = intradaybar.date trade.exitPrice = max(intradaybar.open, trade.trailingstop) if trade.target != None and intradaybar.low < trade.target: trade.exit = intradaybar.date trade.exitPrice = min(intradaybar.open, trade.target) if high != None: high.handle(intradaybar) if donchhigh != None: donchhigh.handle(intradaybar) if trade != None and trade.exit == None: trade.exit = intradaybar.date trade.exitPrice = intradaybar.close if trade: self.tradeManager.addTrade(trade) trade = None trade = None # redo daily setup for the next day, already loaded in above the intraday loop # ok, we find the highest high first high = 0 low = None for ddhighfinder in dailydata: if high < ddhighfinder.high: high = ddhighfinder.high if low == None or ddhighfinder.low < low: low = ddhighfinder.low # great, now we find how many lower highs are within the mush factor atrmush = 0 if dailyatr.value() != None: atrmush = dailyatr.value() * self.mushinessatr taps = 0 shorttaps = 0 for ddtapfinder in dailydata: delta = high - ddtapfinder.high shortdelta = ddtapfinder.low - low if delta <= atrmush or delta <= self.mushinessfixed: taps = taps + 1 if shortdelta <= atrmush or shortdelta <= self.mushinessfixed: shorttaps = shorttaps + 1 return self.tradeManager.getStats()
class MomoDailyTrigger(PriceVolumeDailyTrigger): def __init__(self, settings): PriceVolumeDailyTrigger.__init__(self, settings) self.minatrmultiple = settings.getfloat("MomoDailyTrigger", "minatrmultiple") self.closepercent = settings.get("MomoDailyTrigger", "closepercent") self.openpercent = settings.get("MomoDailyTrigger", "openpercent") self.takeLongs = settings.getboolean("MomoDailyTrigger", "takeLongs") self.takeShorts = settings.getboolean("MomoDailyTrigger", "takeShorts") minaprstr = settings.get("MomoDailyTrigger", "minapr") self.minapr = None if minaprstr != "None": self.minapr = float(minaprstr) dfilter = settings.get("MomoDailyTrigger", "donchianfilter") self.high = High() self.low = Low() self.atr = ATR(14) self.lastatr = HistoricMetric(self.atr, 1) if dfilter == "None": self.lasthighesthigh = None self.lastlowestlow = None else: self.highesthigh = Highest(self.high, int(dfilter)) self.lasthighesthigh = HistoricMetric(self.highesthigh, 1) self.lowestlow = Lowest(self.low, int(dfilter)) self.lastlowestlow = HistoricMetric(self.lowestlow, 1) def ready(self): if PriceVolumeDailyTrigger.ready(self) and self.perioddata is not None and self.lastperioddata is not None: return True def check(self): if self.lastperioddata.close <= 0: return False if self.minapr is None or (self.lastatr.value() / self.lastperioddata.close) < self.minapr: return False if (self.lastperioddata.close - self.lastperioddata.open) < (self.lastatr.value() * self.minatrmultiple): return False if self.lastperioddata.close > self.lastperioddata.open and self.takeLongs: if ((self.lastperioddata.high - self.lastperioddata.close) / ( self.lastperioddata.high - self.lastperioddata.low)) > self.closepercent: return False if ((self.lastperioddata.open - self.lastperioddata.low) / ( self.lastperioddata.high - self.lastperioddata.low)) > self.openpercent: return False return True if self.lastperioddata.close < self.lastperioddata.open and self.takeShorts: if ((self.lastperioddata.close - self.lastperioddata.low) / ( self.lastperioddata.high - self.lastperioddata.low)) > self.closepercent: return False if ((self.lastperioddata.high - self.lastperioddata.open) / ( self.lastperioddata.high - self.lastperioddata.low)) > self.openpercent: return False return True def handle(self, perioddata): # store previous perioddata before we call superclass self.lastperioddata = self.perioddata self.high.handle(perioddata) self.low.handle(perioddata) self.atr.handle(perioddata) self.lastatr.handle(perioddata) if self.lasthighesthigh is not None: self.highesthigh.handle(perioddata) self.lasthighesthigh.handle(perioddata) self.lowestlow.handle(perioddata) self.lastlowestlow.handle(perioddata) PriceVolumeDailyTrigger.handle(self, perioddata) def getLongPrice(self): if self.lastperioddata.close > self.lastperioddata.open: return self.lastperioddata.close return None def getShortPrice(self): if self.lastperioddata.open > self.lastperioddata.close: return self.lastperioddata.close return None