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 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 RSIExitManager(ExitManager): """ Exit on a target RSI value. Handles long and short """ def __init__(self, settings): ExitManager.__init__(self) self.period = settings.getint("RSIExitManager", "period") self.longExit = settings.getfloat("RSIExitManager", "longExit") self.shortExit = settings.getfloat("RSIExitManager", "shortExit") self.close = AdjustedClose() self.rsi = RSI(metric=self.close, period=self.period) def handle(self, perioddata): ExitManager.handle(self, perioddata) self.close.handle(perioddata) self.rsi.handle(perioddata) def checkTrade(self, trade): if trade is not None and self.rsi.ready() and trade.is_open() \ and ((trade.is_long() and self.rsi.value() >= self.longExit) or (trade.is_short() and self.rsi.value() <= self.shortExit)): trade.close(self.perioddata.date, self.perioddata.adjustedClose) return trade def recommendedPreload(self): return self.period + 3
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): NoScaleInEntryManager.__init__(self, settings, name) self.minPrice = settings.getfloat("JBMarwoodSupernovaShortEntry", "minPrice") self.maxPrice = settings.getfloat("JBMarwoodSupernovaShortEntry", "maxPrice") self.minVol = settings.getint("JBMarwoodSupernovaShortEntry", "minVol") self.minPctChange = settings.getfloat("JBMarwoodSupernovaShortEntry", "minPctChange") self.numdays = settings.getint("JBMarwoodSupernovaShortEntry", "numBars") self.onOpen = settings.getboolean("JBMarwoodSupernovaShortEntry", "enterNextOpen") self.onDownClose = settings.getboolean("JBMarwoodSupernovaShortEntry", "enterNextDayDownClose") targetstr = settings.get("JBMarwoodSupernovaShortEntry", "target") if targetstr == "None": self.target = None else: self.target = float(targetstr) self.stopPercent = settings.getfloat("JBMarwoodSupernovaShortEntry", "stopPercent") self.setupYesterday = True self.rawclose = Close() self.close = AdjustedClose() self.oldClose = HistoricMetric(self.close, period=self.numdays) self.change = Subtract(self.close, self.oldClose) self.pctChange = Divide(self.change, self.oldClose) self.volume = Volume() self._addMetric(self.rawclose) self._addMetric(self.close) self._addMetric(self.oldClose) self._addMetric(self.change) self._addMetric(self.pctChange) self._addMetric(self.volume)
def __init__(self, settings): ExitManager.__init__(self) self.period = settings.getint("RSIExitManager", "period") self.longExit = settings.getfloat("RSIExitManager", "longExit") self.shortExit = settings.getfloat("RSIExitManager", "shortExit") self.close = AdjustedClose() self.rsi = RSI(metric=self.close, period=self.period)
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=None, name=None): self.name = name ExitManager.__init__(self, settings) bb_period = self._getintsetting("BollingerBreakoutExitManager", "bbPeriod") bb_stdevs = self._getfloatsetting("BollingerBreakoutExitManager", "bbStdevs") self.close = AdjustedClose() self.bb = BollingerBands(metric=self.close, period=bb_period, stdev=bb_stdevs) self._addMetrics(self.close, self.bb)
class BollingerBreakoutExitManager(ExitManager): def __init__(self, settings=None, name=None): self.name = name ExitManager.__init__(self, settings) bb_period = self._getintsetting("BollingerBreakoutExitManager", "bbPeriod") bb_stdevs = self._getfloatsetting("BollingerBreakoutExitManager", "bbStdevs") self.close = AdjustedClose() self.bb = BollingerBands(metric=self.close, period=bb_period, stdev=bb_stdevs) self._addMetrics(self.close, self.bb) def checkTrade(self, trade): if trade is not None and trade.is_open(): if trade.is_long(): if self.close.value() < self.bb.lowerBand(): trade.close(self.perioddata.date, self.perioddata.adjustedClose) else: if self.close.value() > self.bb.upperBand(): trade.close(self.perioddata.date, self.perioddata.adjustedClose) return trade
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, 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 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
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 __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)
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
class JBMarwoodSupernovaShortEntryManager(NoScaleInEntryManager): def __init__(self, settings, name=None): NoScaleInEntryManager.__init__(self, settings, name) self.minPrice = settings.getfloat("JBMarwoodSupernovaShortEntry", "minPrice") self.maxPrice = settings.getfloat("JBMarwoodSupernovaShortEntry", "maxPrice") self.minVol = settings.getint("JBMarwoodSupernovaShortEntry", "minVol") self.minPctChange = settings.getfloat("JBMarwoodSupernovaShortEntry", "minPctChange") self.numdays = settings.getint("JBMarwoodSupernovaShortEntry", "numBars") self.onOpen = settings.getboolean("JBMarwoodSupernovaShortEntry", "enterNextOpen") self.onDownClose = settings.getboolean("JBMarwoodSupernovaShortEntry", "enterNextDayDownClose") targetstr = settings.get("JBMarwoodSupernovaShortEntry", "target") if targetstr == "None": self.target = None else: self.target = float(targetstr) self.stopPercent = settings.getfloat("JBMarwoodSupernovaShortEntry", "stopPercent") self.setupYesterday = True self.rawclose = Close() self.close = AdjustedClose() self.oldClose = HistoricMetric(self.close, period=self.numdays) self.change = Subtract(self.close, self.oldClose) self.pctChange = Divide(self.change, self.oldClose) self.volume = Volume() self._addMetric(self.rawclose) self._addMetric(self.close) self._addMetric(self.oldClose) self._addMetric(self.change) self._addMetric(self.pctChange) self._addMetric(self.volume) def _checkTradeNoScale(self): trade = None if self.setupYesterday: if self.onOpen: entry = self.periodData.adjustedOpen stop = entry * (1 + self.stopPercent) if entry != stop: trade = Trade(self.periodData.stock, self.periodData.date, entry, stop) if self.target != None: target = self.close.value() * (1.0 - self.target) trade.target = target elif self.onDownClose and self.periodData.adjustedClose < self.periodData.adjustedOpen: stop = self.periodData.adjustedHigh + 0.01 # stop = self.close.value()*(1+self.stopPercent) if stop != self.close.value(): trade = Trade(self.periodData.stock, self.periodData.date, self.close.value(), stop) if self.target != None: target = self.close.value() * (1.0 - self.target) trade.target = target if ( self.pctChange.ready() and self.rawclose.value() >= self.minPrice and self.rawclose.value() <= self.maxPrice and self.volume.value() >= self.minVol and self.pctChange.value() >= self.minPctChange ): if not self.onDownClose and not self.onOpen: # enter immediately stop = self.close.value() * (1 + self.stopPercent) if stop != self.close.value(): trade = Trade(self.periodData.stock, self.periodData.date, self.close.value(), stop) if self.target != None: target = self.close.value() * (1.0 - self.target) trade.target = target self.setupYesterday = True else: self.setupYesterday = False if trade is not None and (trade.entryPrice == 0 or trade.entryPrice == trade.stop): return None return trade
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 __init__(self): Check.__init__(self) # adjusted close accounts for splits and dividends self.close = AdjustedClose() self.ma = SimpleMovingAverage(metric=self.close, period=200)