def __init__(self, settings): DailyTrigger.__init__(self, settings) # this is a hack until we implement subscribing to multiple streams of data self.uptrendcheck = dict() # if True, we are filtering on uptrending SPY, if false, downtrending SPY # we are using the PREVIOUS bar data, hence the use of HistoricMetric. # we do not now if TODAY will close above/below the ma before we enter our # day trades. An alternative would have been to use the open ticker = settings.get("TrendFilterDailyTrigger", "ticker") self.uptrend = settings.getboolean("TrendFilterDailyTrigger", "uptrend") period = settings.getint("TrendFilterDailyTrigger", "period") close = AdjustedClose() lastclose = HistoricMetric(close, 1) ma = SimpleMovingAverage(metric=close, period=period) lastma = HistoricMetric(ma, 1) fromdt = datetime(1900, 1, 1) todt = datetime.now() datastore = datastorefactory.get_datastore() for dd in datastore.getDailyData(ticker, fromdt, todt): close.handle(dd) lastclose.handle(dd) ma.handle(dd) lastma.handle(dd) if lastma.ready() and lastclose.ready(): if lastclose.value() > lastma.value(): self.uptrendcheck[dd.date] = True if lastclose.value() < lastma.value(): self.uptrendcheck[dd.date] = False
class MACrossoverExitManager(ExitManager): """ Exit on a downard cross of a fast ma through a slow ma. This only handles long trades """ def __init__(self, settings): ExitManager.__init__(self) fastma = settings.getfloat("MACrossoverExitManager", "fastma") slowma = settings.getfloat("MACrossoverExitManager", "slowma") self.close = AdjustedClose() self.fastma = SimpleMovingAverage(metric=self.close, period=fastma) self.slowma = SimpleMovingAverage(metric=self.close, period=slowma) # add the metrics to the entry manager, this will cause them # to automatically handle the stream of bar data self._addMetric(self.close) self._addMetric(self.fastma) self._addMetric(self.slowma) def checkTrade(self, trade): if trade is not None and self.fastma.ready() and self.slowma.ready() \ and trade.exit is None \ and self.fastma.value() < self.slowma.value(): trade.exit = self.perioddata.date trade.exitPrice = self.perioddata.adjustedClose return trade
class GapUpEntryManager: def __init__(self, settings): self.minPrice = settings.getfloat("GapAndGoSwingEntry", "minPrice") self.minAvgVol = settings.getint("GapAndGoSwingEntry", "minAvgVol") self.minPercent = settings.getfloat("GapAndGoSwingEntry", "minPercent") targetstr = settings.get("GapAndGoSwingEntry", "target") if targetstr == "None": self.target = None else: self.target = float(targetstr) self.volume = Volume() self.avgvol = SimpleMovingAverage(metric=self.volume, period=21) self.opn = AdjustedOpen() self.close = AdjustedClose() self.lastClose = HistoricMetric(metric=self.close, period=1) self.high = AdjustedHigh() self.lastHigh = HistoricMetric(metric=self.high, period=1) self.low = AdjustedLow() self.inBottomRange=0.1 self.inTopRange=None def handle(self, perioddata): self.close.handle(perioddata) self.lastClose.handle(perioddata) self.high.handle(perioddata) self.lastHigh.handle(perioddata) self.opn.handle(perioddata) self.volume.handle(perioddata) self.avgvol.handle(perioddata) self.low.handle(perioddata) self.lastdd = perioddata def checkTrade(self): if self.close.ready() and self.lastClose.ready() \ and self.opn.ready() and self.volume.ready() \ and self.avgvol.ready(): if self.lastdd.close >= self.minPrice and self.avgvol.value() >= self.minAvgVol \ and self.lastClose.value() > 0 and self.opn.value() > 0 \ and ((self.opn.value()-self.lastClose.value())/self.lastClose.value()) >= self.minPercent \ and self.low.value() >= self.lastHigh.value() \ and (self.inBottomRange == None or ((self.lastdd.adjustedHigh != self.lastdd.adjustedLow) and (self.close.value()-self.lastdd.adjustedLow)/(self.lastdd.adjustedHigh-self.lastdd.adjustedLow)) <= self.inBottomRange) \ and (self.inTopRange == None or ((self.lastdd.adjustedHigh != self.lastdd.adjustedLow) and (self.close.value()-self.lastdd.adjustedLow)/(self.lastdd.adjustedHigh-self.lastdd.adjustedLow)) >= self.inTopRange): stop = max(0.0, self.low.value() - 0.01) # stop = max(0.0, self.lastHigh.value()) trade = Trade(self.lastdd.stock, self.lastdd.date, self.close.value(), stop) if self.target != None: target = self.close.value() + ((self.close.value()-stop)*self.target) trade.target = target return trade return None def recommendedPreload(self): return 22
class PullbackEntryManager(EntryManager): """ Enter after a minimum move size, on a subsequent pullback to a moving average. """ def __init__(self, settings, name=None): EntryManager.__init__(self, settings, name) self.maperiod = settings.getint("PullbackEntry", "ma") self.minmove = self._getfloatsetting(settings, "PullbackEntry", "minmove") self.target = self._getfloatsetting(settings, "PullbackEntry", "target") self.opn = None self.low = None self.high = None self.ma = SimpleMovingAverage(period=self.maperiod) self.lastma = HistoricMetric(self.ma, 1) def handle(self, perioddata): if self.periodData is None or self.periodData.date.day != perioddata.date.day: self.opn = None self.low = None self.high = None EntryManager.handle(self, perioddata) self.ma.handle(perioddata) if self.opn is None: self.opn = perioddata.open if self.low is None or perioddata.low < self.low: self.low = perioddata.low if self.high is None or perioddata.high > self.high: self.high = perioddata.high def checkTrade(self): if self.lastma.ready() and ((self.high - self.opn) / self.opn) >= self.minmove: if self.periodData.low <= self.lastma.value(): entry_price = min(self.periodData.open, self.lastma.value()) stop = self.low - 0.01 trade = Trade(self.lastdd.stock, self.lastdd.date, entry_price, stop) if self.target is not None: trade.target = trade.entryPrice + (trade.entryPrice - trade.stop) * self.target return trade if self.lastma.ready() and ((self.opn - self.low) / self.opn) >= self.minmove: if self.periodData.high >= self.lastma.value(): entry_price = max(self.periodData.open, self.lastma.value()) stop = self.high + 0.01 trade = Trade(self.lastdd.stock, self.lastdd.date, entry_price, stop) if self.target is not None: trade.target = trade.entryPrice + (trade.entryPrice - trade.stop) * self.target return trade return None
def __init__(self, settings): ExitManager.__init__(self) fastma = settings.getfloat("MACrossoverExitManager", "fastma") slowma = settings.getfloat("MACrossoverExitManager", "slowma") self.close = AdjustedClose() self.fastma = SimpleMovingAverage(metric=self.close, period=fastma) self.slowma = SimpleMovingAverage(metric=self.close, period=slowma) # add the metrics to the entry manager, this will cause them # to automatically handle the stream of bar data self._addMetric(self.close) self._addMetric(self.fastma) self._addMetric(self.slowma)
class MomoPullbackDailyTrigger(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 = AdjustedClose() if self.dailysmatrendfilter is not None: self.ma = SimpleMovingAverage(metric=self.close, 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.lastpd.open >= 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: logger.debug("Saw minimum move in MomoPullbackDailyTrigger, indicating we have a good day") 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())
def __init__(self, settings, name=None): EntryManager.__init__(self, settings, name=name) fastma = settings.getint("MACrossoverEntryManager", "fastma") slowma = settings.getint("MACrossoverEntryManager", "slowma") # AdjustedClose is adjusted for splits and dividends self.close = AdjustedClose() self.fastma = SimpleMovingAverage(metric=self.close, period=fastma) self.slowma = SimpleMovingAverage(metric=self.close, period=slowma) # add the metrics to the entry manager, this will cause them # to automatically handle the stream of bar data self._addMetric(self.close) self._addMetric(self.fastma) self._addMetric(self.slowma)
class MyTrendCheck(Check): def __init__(self): Check.__init__(self) # adjusted close accounts for splits and dividends self.close = AdjustedClose() self.ma = SimpleMovingAverage(metric=self.close, period=200) def handle(self, periodData): self.close.handle(periodData) self.ma.handle(periodData) def ready(self): return self.close.ready() and self.ma.ready() def check(self): if not self.ready(): return False return self.close.value() > self.ma.value()
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
class MovingAverageExitManager(ExitManager): """ Exit on a moving average as a trailing stop """ def __init__(self, settings): ExitManager.__init__(self) self.period = settings.getint("MovingAverageExitManager", "period") self.close = AdjustedClose() self.ma = SimpleMovingAverage(metric=self.close, period=self.period) def handle(self, perioddata): ExitManager.handle(self, perioddata) self.close.handle(perioddata) self.ma.handle(perioddata) def checkTrade(self, trade): if trade is not None and self.ma.ready() and trade.exit is None \ and trade.entryPrice > trade.stop \ and self.perioddata.adjustedClose >= self.ma.value(): trade.exit = self.perioddata.date trade.exitPrice = self.perioddata.adjustedClose if trade is not None and self.ma.ready() and trade.exit is None \ and trade.entryPrice < trade.stop \ and self.perioddata.adjustedClose <= self.ma.value(): trade.exit = self.perioddata.date trade.exitPrice = self.perioddata.adjustedClose return trade def recommendedPreload(self): return self.period + 1
class BollingerBreakoutEntryManager(NoScaleInEntryManager): def __init__(self, settings=None, name=None): NoScaleInEntryManager.__init__(self, settings, name) self.min_price = self._getfloatsetting("BollingerBreakoutEntryManager", "minPrice") self.min_vol = self._getintsetting("BollingerBreakoutEntryManager", "minVolume") bb_period = self._getintsetting("BollingerBreakoutEntryManager", "bbPeriod") bb_stdevs = self._getfloatsetting("BollingerBreakoutEntryManager", "bbStdevs") self.do_long = self._getboolsetting("BollingerBreakoutEntryManager", "doLong") self.do_short = self._getboolsetting("BollingerBreakoutEntryManager", "doShort") sma_period = self._getintsetting("BollingerBreakoutEntryManager", "smaPeriod") if sma_period is not None: self.sma = SimpleMovingAverage(period=sma_period) else: self.sma = None self.raw_close = Close() self.close = AdjustedClose() self.vol = AverageVolume() self.bb = BollingerBands(metric=self.close, period=bb_period, stdev=bb_stdevs) self._addMetrics(self.sma, self.raw_close, self.close, self.vol, self.bb) def _checkTradeNoScale(self): trade = None if self.raw_close.value() >= self.min_price and self.vol.value() >= self.min_vol \ and self.close.value() > self.bb.upperBand() and self.do_long \ and (self.sma is None or self.close.value() > self.sma.value()): entry_price = self.close.value() stop = 0 trade = Trade(stock=self.periodData.stock, entry=self.periodData.date, entryPrice=entry_price, stop=stop) if self.raw_close.value() >= self.min_price and self.vol.value() >= self.min_vol \ and self.close.value() < self.bb.upperBand() and self.do_short \ and (self.sma is None or self.close.value() < self.sma.value()): entry_price = self.close.value() stop = entry_price * 10 trade = Trade(stock=self.periodData.stock, entry=self.periodData.date, entryPrice=entry_price, stop=stop) return trade
def __init__(self, settings, name=None): EntryManager.__init__(self, settings, name) self.maperiod = settings.getint("PullbackEntry", "ma") self.minmove = self._getfloatsetting(settings, "PullbackEntry", "minmove") self.target = self._getfloatsetting(settings, "PullbackEntry", "target") self.opn = None self.low = None self.high = None self.ma = SimpleMovingAverage(period=self.maperiod) self.lastma = HistoricMetric(self.ma, 1)
class MACrossoverEntryManager(EntryManager): """ Enter on cross higher of the fast ma over the slow ma """ def __init__(self, settings, name=None): EntryManager.__init__(self, settings, name=name) fastma = settings.getint("MACrossoverEntryManager", "fastma") slowma = settings.getint("MACrossoverEntryManager", "slowma") # AdjustedClose is adjusted for splits and dividends self.close = AdjustedClose() self.fastma = SimpleMovingAverage(metric=self.close, period=fastma) self.slowma = SimpleMovingAverage(metric=self.close, period=slowma) # add the metrics to the entry manager, this will cause them # to automatically handle the stream of bar data self._addMetric(self.close) self._addMetric(self.fastma) self._addMetric(self.slowma) def checkTrade(self, trade): if trade is not None: # we don't scale in additional size, already in a trade return trade if self.fastma.ready() and self.slowma.ready() \ and self.fastma.value() > self.slowma.value() \ and self.close.value() > 0: # new trade entry = self.close.value() # no stops for this simple strategy stop = 0.0 # note, self.periodData is the last bar seen, this is provided from # the base class EntryManager trade = Trade(self.periodData.stock, self.periodData.date, entry, stop) return trade return None
def __init__(self, settings): self.minPrice = settings.getfloat("GapAndGoSwingEntry", "minPrice") self.minAvgVol = settings.getint("GapAndGoSwingEntry", "minAvgVol") self.minPercent = settings.getfloat("GapAndGoSwingEntry", "minPercent") targetstr = settings.get("GapAndGoSwingEntry", "target") if targetstr == "None": self.target = None else: self.target = float(targetstr) self.volume = Volume() self.avgvol = SimpleMovingAverage(metric=self.volume, period=21) self.opn = AdjustedOpen() self.close = AdjustedClose() self.lastClose = HistoricMetric(metric=self.close, period=1) self.high = AdjustedHigh() self.lastHigh = HistoricMetric(metric=self.high, period=1) self.low = AdjustedLow() self.inBottomRange=0.1 self.inTopRange=None
def __init__(self, settings=None, name=None): NoScaleInEntryManager.__init__(self, settings, name) self.min_price = self._getfloatsetting("BollingerBreakoutEntryManager", "minPrice") self.min_vol = self._getintsetting("BollingerBreakoutEntryManager", "minVolume") bb_period = self._getintsetting("BollingerBreakoutEntryManager", "bbPeriod") bb_stdevs = self._getfloatsetting("BollingerBreakoutEntryManager", "bbStdevs") self.do_long = self._getboolsetting("BollingerBreakoutEntryManager", "doLong") self.do_short = self._getboolsetting("BollingerBreakoutEntryManager", "doShort") sma_period = self._getintsetting("BollingerBreakoutEntryManager", "smaPeriod") if sma_period is not None: self.sma = SimpleMovingAverage(period=sma_period) else: self.sma = None self.raw_close = Close() self.close = AdjustedClose() self.vol = AverageVolume() self.bb = BollingerBands(metric=self.close, period=bb_period, stdev=bb_stdevs) self._addMetrics(self.sma, self.raw_close, self.close, self.vol, self.bb)
def __init__(self): Check.__init__(self) # adjusted close accounts for splits and dividends self.close = AdjustedClose() self.ma = SimpleMovingAverage(metric=self.close, period=200)
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()
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): 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 smafromdt = fromdt - timedelta(days=self.period+1) dailydata = datastore.getData(stock, self.timescale, smafromdt, todt) bb = BollingerBands(period=self.period, stdev=float(self.bandwidth)) outerbb = None if self.bandStop != None: outerbb = BollingerBands(period=self.period, stdev=self.bandStop) sma = None if self.sma: sma = SimpleMovingAverage(period=self.sma) lastdd = None trade = None for pd in dailydata: bb.handle(pd) if outerbb != None: outerbb.handle(pd) if sma != None: sma.handle(pd) # check for long stopout if trade != None and trade.stop < trade.entryPrice and pd.low <= trade.trailingstop: trade.exit = pd.date trade.exitPrice = min(pd.open, trade.trailingstop) self.tradeManager.addTrade(trade) trade = None # check for long exit if trade != None and ((self.exitAtOtherBand == False and pd.close > bb.movingAverage()) or (self.exitAtOtherBand and pd.close >= bb.upperBand())): trade.exit = pd.date trade.exitPrice = pd.close self.tradeManager.addTrade(trade) trade = None # check for short stopout if trade != None and trade.stop > trade.entryPrice and pd.high >= trade.trailingstop: trade.exit = pd.date trade.exitPrice = max(pd.open, trade.trailingstop) self.tradeManager.addTrade(trade) trade = None # check for short exit if trade != None and ((self.exitAtOtherBand == False and pd.close < bb.movingAverage()) or (self.exitAtOtherBand and pd.close <= bb.lowerBand())): trade.exit = pd.date trade.exitPrice = pd.close self.tradeManager.addTrade(trade) trade = None # check for new long if trade == None and self.doLong and pd.close > self.minprice and bb.ready() and pd.date >= fromdt and \ pd.close < bb.lowerBand() and (sma == None or sma.value() < pd.close): stop = 0 if self.percentStop != None: stop = pd.close * (1-self.percentStop) if self.bandStop != None: stop = outerbb.lowerBand() trade = Trade(stock=stock, entry=pd.date, entryPrice=pd.close, stop=stop) # check for new short if trade == None and self.doShort and pd.close > self.minprice and bb.ready() and pd.date >= fromdt and \ pd.close > bb.upperBand() and (sma == None or sma.value() > pd.close): stop = 0 if self.percentStop != None: stop = pd.close * (1+self.percentStop) if self.bandStop != None: stop = outerbb.upperBand() 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 return self.tradeManager.getStats()
def __init__(self, settings): ExitManager.__init__(self) self.period = settings.getint("MovingAverageExitManager", "period") self.close = AdjustedClose() self.ma = SimpleMovingAverage(metric=self.close, period=self.period)
def generate_random_perioddata(dt): a = random()*50+50 b = random()*50+50 c = random()*50+50 d = random()*50+50 retval = PeriodData(date=dt,period=Period.DAILY, stock="AAPL", open=a,high=max((a,b,c,d)),low=min(a,b,c,d),close=d,volume=100000,adjustedClose=d) return retval def generate_random_series(): retval = list() dt = datetime(year=2015,month=1,day=1) for i in range(1000): dt = dt + timedelta(days=1) retval.append(generate_random_perioddata(dt)) return retval # Here begins the example code # Track the adjusted close and 20 period simple moving average close = AdjustedClose() sma = SimpleMovingAverage(metric=close, period=20) print "Date,SMA" for periodData in generate_random_series(): close.handle(periodData) sma.handle(periodData) if sma.ready() and close.ready(): print "%s,%f" % (periodData.date, sma.value())
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()