class NewHighDailyTrigger(Check): def __init__(self, settings): self.highperiod = settings.getfloat("NewHighDailyTrigger", "highperiod") self.minprice = settings.getfloat("NewHighDailyTrigger", "minprice") self.maxprice = settings.getfloat("NewHighDailyTrigger", "maxprice") self.high = High() self.highesthigh = Highest(metric=self.high, period=self.highperiod) self.lasthighesthigh = HistoricMetric(metric=self.highesthigh,period=1) def ready(self): if self.lasthighesthigh.ready(): return True return False def check(self): if self.ready() and self.lastpd != None: if self.high.value() > self.lasthighesthigh.value() \ and self.lasthighesthigh.value() >= self.minprice \ and self.lasthighesthigh.value() <= self.maxprice: return True return False def handle(self, perioddata): self.high.handle(perioddata) self.highesthigh.handle(perioddata) self.lasthighesthigh.handle(perioddata) self.lastpd = perioddata def getLongPrice(self): return self.lasthighesthigh.value() def getShortPrice(self): return None
class GapDailyTrigger(PriceVolumeDailyTrigger): def __init__(self, settings): PriceVolumeDailyTrigger.__init__(self, settings) self.mingap = settings.getfloat("GapDailyTrigger", "mingap") dfilter = settings.get("GapDailyTrigger", "donchianfilter") if dfilter == "None": self.lasthighesthigh = None self.lastlowestlow = None else: self.high = High() self.highesthigh = Highest(self.high, int(dfilter)) self.lasthighesthigh = HistoricMetric(self.highesthigh, 1) self.low = Low() 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.mingap >= 0.0: if PriceVolumeDailyTrigger.check(self) and self.perioddata is not None and \ (( self.perioddata.open - self.lastperioddata.close) / self.lastperioddata.close) >= self.mingap \ and (self.lasthighesthigh is None or ( self.lasthighesthigh.ready() and self.perioddata.open >= self.lasthighesthigh.value())): return True else: if PriceVolumeDailyTrigger.check(self) and self.perioddata is not None and \ (( self.perioddata.open - self.lastperioddata.close) / self.lastperioddata.close) <= self.mingap \ and (self.lastlowestlow is None or ( self.lastlowestlow.ready() and self.perioddata.open <= self.lastlowestlow.value())): return True return False def handle(self, perioddata): # store previous perioddata before we call superclass self.lastperioddata = self.perioddata if self.lasthighesthigh is not None: self.high.handle(perioddata) self.highesthigh.handle(perioddata) self.lasthighesthigh.handle(perioddata) self.low.handle(perioddata) self.lowestlow.handle(perioddata) self.lastlowestlow.handle(perioddata) PriceVolumeDailyTrigger.handle(self, perioddata)
def __init__(self, settings): self.highperiod = settings.getfloat("NewHighDailyTrigger", "highperiod") self.minprice = settings.getfloat("NewHighDailyTrigger", "minprice") self.maxprice = settings.getfloat("NewHighDailyTrigger", "maxprice") self.high = High() self.highesthigh = Highest(metric=self.high, period=self.highperiod) self.lasthighesthigh = HistoricMetric(metric=self.highesthigh,period=1)
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 __init__(self, settings): BasicStopManager.__init__(self, settings) channelPeriod = settings.getint("DonchianChannelStopManager", "channelPeriod") self.low = Low() self.high = High() self.lowestLow = Lowest(self.low, channelPeriod) self.highestHigh = Highest(self.high, channelPeriod) self.lastLowestLow = HistoricMetric(self.lowestLow, 1) self.lastHighestHigh = HistoricMetric(self.highestHigh, 1)
class DonchianChannelStopManager(BasicStopManager): def __init__(self, settings): BasicStopManager.__init__(self, settings) channelPeriod = settings.getint("DonchianChannelStopManager", "channelPeriod") self.low = Low() self.high = High() self.lowestLow = Lowest(self.low, channelPeriod) self.highestHigh = Highest(self.high, channelPeriod) self.lastLowestLow = HistoricMetric(self.lowestLow, 1) self.lastHighestHigh = HistoricMetric(self.highestHigh, 1) def handle(self, perioddata): BasicStopManager.handle(self, perioddata) self.low.handle(perioddata) self.high.handle(perioddata) self.lowestLow.handle(perioddata) self.highestHigh.handle(perioddata) self.lastLowestLow.handle(perioddata) self.lastHighestHigh.handle(perioddata) def checkTrade(self, trade): if trade != None and trade.entryPrice > trade.stop: trade.trailingstop = max(trade.stop, self.lastLowestLow.value()-0.01) if trade != None and trade.entryPrice < trade.stop: trade.trailingstop = min(trade.stop, self.lastHighestHigh.value() + 0.01) if trade != None and trade.exit == None \ and trade.entryPrice > trade.stop and self.perioddata.low <= trade.trailingstop: trade.exit = self.perioddata.date trade.exitPrice = min(self.perioddata.open, trade.trailingstop) if trade != None and trade.exit == None \ and trade.entryPrice < trade.stop and self.perioddata.high >= trade.trailingstop: trade.exit = self.perioddata.date trade.exitPrice = max(self.perioddata.open, trade.trailingstop) return trade def recommendedPreload(self): return self.lastHighestHigh.recommendedPreload()
def __init__(self, settings): PriceVolumeDailyTrigger.__init__(self, settings) self.mingap = settings.getfloat("GapDailyTrigger", "mingap") dfilter = settings.get("GapDailyTrigger", "donchianfilter") if dfilter == "None": self.lasthighesthigh = None self.lastlowestlow = None else: self.high = High() self.highesthigh = Highest(self.high, int(dfilter)) self.lasthighesthigh = HistoricMetric(self.highesthigh, 1) self.low = Low() self.lowestlow = Lowest(self.low, int(dfilter)) self.lastlowestlow = HistoricMetric(self.lowestlow, 1)
def __init__(self, settings, name=None): EntryManager.__init__(self, settings, name) self.mindip = settings.getfloat("R2GEntryManager", "mindip") self.target = self._getfloatsetting(settings, "R2GEntryManager", "target") self.setupLong = False self.setupShort = False self.low = Low() self.lod = Lowest(self.low, -1) self.high = High() self.hod = Highest(self.high, -1) # TODO replace trigger logic with some kind of context/info from DailyDataTrigger self.triggerLongPrice = None self.triggerShortPrice = None self.currentDate = None self.currentDayOpen = None
class R2GEntryManager(EntryManager): """ Enter after an open below and minimum move below the previous close, once it retakes the previous close and goes higher. Opposite requirements for shorts. """ def __init__(self, settings, name=None): EntryManager.__init__(self, settings, name) self.mindip = settings.getfloat("R2GEntryManager", "mindip") self.target = self._getfloatsetting(settings, "R2GEntryManager", "target") self.setupLong = False self.setupShort = False self.low = Low() self.lod = Lowest(self.low, -1) self.high = High() self.hod = Highest(self.high, -1) # TODO replace trigger logic with some kind of context/info from DailyDataTrigger self.triggerLongPrice = None self.triggerShortPrice = None self.currentDate = None self.currentDayOpen = None def handle(self, perioddata): EntryManager.handle(self, perioddata) current_date = perioddata.date.date if current_date > self.currentDate: self.currentDayOpen = perioddata.adjustedOpen self.low.handle(perioddata) self.lod.handle(perioddata) self.high.handle(perioddata) self.hod.handle(perioddata) # TODO need to rewrite this in terms of some new hinting # facility from the daily trigger now that I removed # trigger price arguments if self.triggerLongPrice is not None: if perioddata.low <= (self.triggerLongPrice - self.mindip): self.setupLong = True if self.triggerShortPrice is not None: if perioddata.high >= (self.triggerShortPrice + self.mindip): self.setupShort = True def checkTrade(self): if self.setupLong and self.periodData.high >= (self.triggerLongPrice + 0.01) \ and self.currentDayOpen is not None and self.currentDayOpen < self.triggerLongPrice: entry_price = max(self.periodData.open, self.triggerLongPrice + 0.01) stop = self.lod.value() - 0.01 trade = Trade(self.periodData.stock, self.periodData.date, entry_price, stop) if self.target is not None: trade.target = trade.entryPrice + (trade.entryPrice - trade.stop) * self.target return trade if self.setupShort and self.periodData.low <= (self.triggerShortPrice - 0.01) \ and self.currentDayOpen is not None and self.currentDayOpen > self.triggerShortPrice: entry_price = min(self.periodData.open, self.triggerShortPrice - 0.01) stop = self.hod.value() + 0.01 trade = Trade(self.periodData.stock, self.periodData.date, entry_price, stop) if self.target is not None: trade.target = trade.entryPrice - (trade.stop - trade.entryPrice) * self.target 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): 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