def onTick(self, tickEvent): if self.subc == None: self.subc = SubChart("SimpleMarket", self.instrument, self.granularity, endep=tickEvent.time) now = self.subc.onTick(tickEvent) if now == self.now: return [] self.now = now orders = [] if self.id == -1: self.curr_side *= -1 if self.curr_side == env.SIDE_BUY: price = tickEvent.ask else: price = tickEvent.bid order = self.createMarketOrder( tickEvent, self.instrument, self.curr_side, 1, price, takeprofit=price + self.curr_side * self.profit, stoploss=price - self.curr_side * self.profit) self.id = order.id orders.append(order) return orders
def __init__(self, instrument, granularity, startep=-1, endep=-1, peakspan=12 * 6, peaksize=5, analspan=12 * 4): self.instrument = instrument self.granularity = granularity self.subc = SubChart("PriceAction", self.instrument, self.granularity, startep=startep, endep=endep, nbars=peakspan + peaksize * 2) self.peaks = PeakIndex(self.subc, peaksize, peakspan) self.analspan = analspan self.hist = MultiObjHistory(analspan) self.candleshapes = CandleShapeIndex(self.subc, statistics_span=analspan) self.unitsecs = tradelib.getUnitSecs(granularity) self.pipprice = tradelib.pip2Price(1, instrument) self.nowi = -1 self.now = -1 self.linehists = { const_candles.LINE_TPTREND: {}, # dict of History() const_candles.LINE_BTTREND: {}, const_candles.LINE_MAX: {}, const_candles.LINE_MIN: {} }
def __init__(self, instrument, granularity, startep=-1, endep=-1): super(CheckIndex, self).__init__(instrument, granularity) self.subc = SubChart(self.__class__.__name__, instrument, granularity, startep, endep) self.cntForNext = 0 self.nowidx = -1 self.now = -1
def __init__(self, instrument, granularity, startep, endep, sumspan=20): super(PowerIndex, self).__init__(instrument, granularity) self.subc = SubChart("PowerIndex", instrument, granularity, startep, endep) self.sumspan = sumspan self.bull = [] self.bear = [] self.bull_totals = [] self.bear_totals = [] self.epochs = [] (tl, _, hl, ll, cl, _) = self.subc.getPrices() self._calcPower(tl, hl, ll, cl)
def __init__(self): self.startep = lib.str2epoch("2019-11-27T17:45:00") self.endep = lib.str2epoch("2019-11-28T00:25:00") name = "TestHistIndex" subc = SubChart(name, "USD_JPY", "M5", startep=self.startep, endep=self.endep) super(TestHistIndex, self).__init__("TestHistIndex", subc) super(HistIndex, self).__init__(name, subc) subc.onTick(TickEvent(self.endep,0,0,0)) (t,_,_,_,_,_) = subc.getPrices(self.startep, self.endep) self.subc = subc for epoch in t: self.calcHist(epoch)
def __init__(self, instrument, granularity, startep, endep, ema_span=20): super(EmaIndex, self).__init__("EmaIndex", instrument, granularity) self.subc = SubChart("EmaIndex", instrument, granularity, startep, endep) (t, _, _, _, cl, _) = self.subc.getPrices() self.epochs = t[ema_span:] self.alpha = 2.0 / (ema_span + 1) self.ema_span = ema_span self.now = 0 first_ema = sum(cl[:ema_span]) / ema_span self.ema = [] self._calcEma(t[ema_span - 1:], cl[ema_span - 1:], first_ema)
class EmaIndex(TechnicalIndex): def __init__(self, instrument, granularity, startep, endep, ema_span=20): super(EmaIndex, self).__init__("EmaIndex", instrument, granularity) self.subc = SubChart("EmaIndex", instrument, granularity, startep, endep) (t, _, _, _, cl, _) = self.subc.getPrices() self.epochs = t[ema_span:] self.alpha = 2.0 / (ema_span + 1) self.ema_span = ema_span self.now = 0 first_ema = sum(cl[:ema_span]) / ema_span self.ema = [] self._calcEma(t[ema_span - 1:], cl[ema_span - 1:], first_ema) def _calcEma(self, t, cl, last_ema): ema = self.ema for i in range(1, len(cl)): if t[i] - t[i - 1] > self.unitsecs: preema = cl[i] else: preema = last_ema last_ema = preema + self.alpha * (cl[i] - preema) ema.append(last_ema) self.ema = ema def onTick(self, tickEvent): epoch = tickEvent.time i, epoch = self.subc.getTime(epoch) if epoch == self.now: return i, epoch, self.ema[i - self.ema_span] if i < 0: self.updateEma() self.now = epoch i = i - self.ema_span if i >= 0: return i, epoch, self.ema[i - self.ema_span] else: return i, epoch, -1 def updateEma(self): (t1, _, _, _, cl1, _) = self.subc.getLatestChart(self.epochs[-1]) self._calcEma(t1, cl1, self.ema[-1]) def getPlotElement(self, color="k"): return PlotEleLineChart(self.epochs, self.ema)
def run(startep, endep, instrument="USD_JPY", granularity="M5", peakspan=12*6, peaksize=5): subc = SubChart("PeakIndex", instrument, granularity, startep=startep, endep=endep, nbars=peakspan+peaksize*2, truncateOld=False) p = PeakIndex(subc,peaksize, peakspan, deleteOld=False) tickEvent = TickEvent(endep,0,0,0) subc.onTick(tickEvent) p.onTick(tickEvent) return p.getPlotElements()
class SimpleStopStrategy(Strategy): def __init__(self, instrument, granularity, profitpips): self.instrument = instrument self.granularity = granularity self.subc = None self.profit = tradelib.pip2Price(profitpips, instrument) self.unitsecs = tradelib.getUnitSecs(granularity) self.pipprice = tradelib.pip2Price(1, instrument) self.id = -1 self.curr_side = env.SIDE_BUY self.now = -1 def onTick(self, tickEvent): if self.subc == None: self.subc = SubChart("SimpleStop", self.instrument, self.granularity, endep=tickEvent.time) now = self.subc.onTick(tickEvent) if now == self.now: return [] self.now = now orders = [] #if lib.str2epoch("2019-11-15T00:30:00") == tickEvent.time: # print(tickEvent.time) if self.id == -1: self.curr_side *= -1 if self.curr_side == env.SIDE_BUY: price = tickEvent.l - self.pipprice * 3 else: price = tickEvent.h + self.pipprice * 3 order = self.createStopOrder( tickEvent, self.instrument, self.curr_side, 1, price, validep=tickEvent.time + self.unitsecs, takeprofit=price + self.curr_side * self.profit, stoploss=price - self.curr_side * self.profit) if order != None: self.id = order.id orders.append(order) return orders def onSignal(self, signalEvent): if self.id == signalEvent.id: if signalEvent.signal in [ env.ESTATUS_ORDER_CLOSED, env.ESTATUS_TRADE_CLOSED ]: self.id = -1
def run(startep, endep, instrument="USD_JPY", granularity="M5", peakspan=12 * 3, peaksize=5, analspan=12 * 4): from tools.subchart import SubChart from event.tick import TickEvent subc = SubChart("TrendlineIndex", instrument, granularity, startep=startep, endep=endep, nbars=peakspan + peaksize * 2, truncateOld=False) p = TrendLinesIndex(subc, peaksize, peakspan, analspan, deleteOld=False) tickEvent = TickEvent(endep, 0, 0, 0) subc.onTick(tickEvent) p.onTick(tickEvent) return p.getPlotElements()
def onTick(self, tickEvent): if self.subc == None: self.subc = SubChart("SimpleStop", self.instrument, self.granularity, endep=tickEvent.time) now = self.subc.onTick(tickEvent) if now == self.now: return [] self.now = now orders = [] #if lib.str2epoch("2019-11-15T00:30:00") == tickEvent.time: # print(tickEvent.time) if self.id == -1: self.curr_side *= -1 if self.curr_side == env.SIDE_BUY: price = tickEvent.l - self.pipprice * 3 else: price = tickEvent.h + self.pipprice * 3 order = self.createStopOrder( tickEvent, self.instrument, self.curr_side, 1, price, validep=tickEvent.time + self.unitsecs, takeprofit=price + self.curr_side * self.profit, stoploss=price - self.curr_side * self.profit) if order != None: self.id = order.id orders.append(order) return orders
class SimpleMarketStrategy(Strategy): def __init__(self, instrument, granularity, profitpips): self.instrument = instrument self.unitsecs = tradelib.getUnitSecs(granularity) self.granularity = granularity self.subc = None self.profit = tradelib.pip2Price(profitpips, instrument) self.id = -1 self.curr_side = env.SIDE_BUY self.now = -1 def onTick(self, tickEvent): if self.subc == None: self.subc = SubChart("SimpleMarket", self.instrument, self.granularity, endep=tickEvent.time) now = self.subc.onTick(tickEvent) if now == self.now: return [] self.now = now orders = [] if self.id == -1: self.curr_side *= -1 if self.curr_side == env.SIDE_BUY: price = tickEvent.ask else: price = tickEvent.bid order = self.createMarketOrder( tickEvent, self.instrument, self.curr_side, 1, price, takeprofit=price + self.curr_side * self.profit, stoploss=price - self.curr_side * self.profit) self.id = order.id orders.append(order) return orders def onSignal(self, signalEvent): if self.id == signalEvent.id: if signalEvent.signal in [ env.ESTATUS_ORDER_CLOSED, env.ESTATUS_TRADE_CLOSED ]: self.id = -1
class PowerIndex(TechnicalIndex): def __init__(self, instrument, granularity, startep, endep, sumspan=20): super(PowerIndex, self).__init__(instrument, granularity) self.subc = SubChart("PowerIndex", instrument, granularity, startep, endep) self.sumspan = sumspan self.bull = [] self.bear = [] self.bull_totals = [] self.bear_totals = [] self.epochs = [] (tl, _, hl, ll, cl, _) = self.subc.getPrices() self._calcPower(tl, hl, ll, cl) def _calcPower(self, tl, hl, ll, cl): bull = [] bear = [] for i in range(1, len(tl)): j = i - 1 u = hl[i] - ll[i] e = u c1 = cl[j] c2 = cl[i] d = c2 - c1 if d >= 0: e -= d if e < 0: e = 0 else: u += d if u < 0: u = 0 bull.append(u) bear.append(e) for i in range(self.sumspan, len(bull)): self.bull_totals.append(sum(bull[i - self.sumspan:i])) self.bear_totals.append(sum(bear[i - self.sumspan:i])) self.bull.extend(bull[self.sumspan:]) self.bear.extend(bear[self.sumspan:]) self.epochs.extend(tl[self.sumspan + 1:])
def testWeekends(self): st = lib.str2epoch("2019/04/05 20:00", "%Y/%m/%d %H:%M") ed = lib.str2epoch("2019/04/08 01:00", "%Y/%m/%d %H:%M") s = SubChart("testWeekends", "USD_JPY", "H1", st, ed, 5) u = s.unitsecs i, now = s.getTime(st + 100) self.assertEqual(i,5) self.assertEqual(now,1554494400) i, now = s.getTime(st + u + 100) self.assertEqual(i,-1) i, now = s.getTime(1554670800 -u + 100) self.assertEqual(i,-1) i, now = s.getTime(1554670800 + 100) self.assertEqual(i,6) self.assertEqual(now,1554670800)
def testNormal(self): env.run_mode = env.MODE_SIMULATE st = lib.str2epoch("2019/04/02 09:00", "%Y/%m/%d %H:%M") ed = lib.str2epoch("2019/04/02 12:00", "%Y/%m/%d %H:%M") s = SubChart("testNormal", "USD_JPY", "M5", st, ed, 5, 48) u = s.unitsecs (t,_,_,_,_,_) = s.getPrices() self.assertEqual(len(t), len(s.prices[0])) # 1 i, now = s.getTime(st + 100) self.assertEqual(i,5) self.assertEqual(now,1554195600) # 2 i, now = s.getTime(st + 400) self.assertEqual(i,6) self.assertEqual(now,1554195900) # 3 i, now = s.getTime(ed + 400) self.assertEqual(i,42) self.assertEqual(now,1554206700) # 4 i, now = s.getTime(ed - 500) self.assertEqual(i,39) self.assertEqual(now,1554205800) from event.tick import TickEvent tickEvent = TickEvent(1554196200+100, 1, 1) s.onTick(tickEvent) (t,o,h,l,c,v) = s.getPrices() self.assertEqual(t[-1], 1554196200) self.assertEqual(o[-1], 111.372) self.assertEqual(v[-1], 22) (t,o,h,l,c,v) = s.getPrices(5) self.assertEqual(t[0], 1554195600) self.assertEqual(t[-1], 1554196200) (t,o,h,l,c,v) = s.getPrices(5,6) self.assertEqual(t[-1], 1554195900) ep = ed + u*(48-len(s.prices[0])+48*0.5+1) tickEvent = TickEvent(ep, 1, 1) s.onTick(tickEvent) self.assertEqual(len(s.prices[0]), 48+48*0.5) (t,_,_,_,_,_) = s.getPrices() self.assertEqual(t[-1],ep) ep = t[-1] + u tickEvent = TickEvent(ep+100, 1, 1) s.onTick(tickEvent) self.assertEqual(len(s.prices[0]), 48) (t,_,_,_,_,_) = s.getPrices() self.assertEqual(t[-1],ep)
class PriceActionStrategy(Strategy): def __init__(self, instrument, granularity, startep=-1, endep=-1, peakspan=12 * 6, peaksize=5, analspan=12 * 4): self.instrument = instrument self.granularity = granularity self.subc = SubChart("PriceAction", self.instrument, self.granularity, startep=startep, endep=endep, nbars=peakspan + peaksize * 2) self.peaks = PeakIndex(self.subc, peaksize, peakspan) self.analspan = analspan self.hist = MultiObjHistory(analspan) self.candleshapes = CandleShapeIndex(self.subc, statistics_span=analspan) self.unitsecs = tradelib.getUnitSecs(granularity) self.pipprice = tradelib.pip2Price(1, instrument) self.nowi = -1 self.now = -1 self.linehists = { const_candles.LINE_TPTREND: {}, # dict of History() const_candles.LINE_BTTREND: {}, const_candles.LINE_MAX: {}, const_candles.LINE_MIN: {} } def updateLineHistory(self, line_id, linehist, line_type, coord, epoch, pos): lastepoch, lastpos = linehist.last() if lastepoch > 0 and abs(lastpos) <= const_candles.LINEDIST_ABOVE_NEAR: he = HistEvent(line_id, line_type, pos, coord) self.hist.append(epoch, he) self.hist.log(epoch) linehist.append(epoch, pos) lib.printDebug( epoch, "id=%s type=%s pos=%s coord=%.3f" % (line_id, line_type, pos, coord)) def getLineID(self, epoch, line_type): return "%d_%d" % (line_type, epoch) def detectLineDist(self): tprices = self.peaks.getPriceOnTrendlines(self.now, True) bprices = self.peaks.getPriceOnTrendlines(self.now, False) maxs = self.peaks.maxs.items() mins = self.peaks.mins.items() t, o, h, l, c, _ = self.subc.getPrice() candlelen = h - l expiration, _, _, _, _, _ = self.subc.getPrice(self.analspan) for (baseps, ltype) in [(tprices, const_candles.LINE_TPTREND), (bprices, const_candles.LINE_BTTREND), (maxs, const_candles.LINE_MAX), (mins, const_candles.LINE_MIN)]: lines = self.linehists[ltype] for line_id in list(lines.keys()): (lastep, _) = lines[line_id].last() if lastep < expiration: del lines[line_id] for items in baseps: if ltype in [ const_candles.LINE_TPTREND, const_candles.LINE_BTTREND ]: line_epoch, baseprice, coord = items else: line_epoch, baseprice = items coord = baseprice line_id = self.getLineID(line_epoch, ltype) if line_id in lines.keys(): linehist = lines[line_id] else: linehist = History(self.analspan) pos = 0 if h < baseprice - candlelen * 0.2: pos = const_candles.LINEDIST_ABOVE_FAR elif h < baseprice: pos = const_candles.LINEDIST_ABOVE_NEAR elif h >= baseprice and max(o, c) <= baseprice: pos = const_candles.LINEDIST_ABOVE_TOUCHED elif max(o, c) > baseprice and min(o, c) < baseprice: pos = const_candles.LINEDIST_CROSSED elif min(o, c) >= baseprice and l <= baseprice: pos = const_candles.LINEDIST_BELOW_TOUCHED elif l - candlelen * 0.2 < baseprice: pos = const_candles.LINEDIST_BELOW_NEAR elif l > baseprice: pos = const_candles.LINEDIST_BELOW_FAR #linehist.append(t, pos) self.updateLineHistory(line_id, linehist, ltype, coord, t, pos) def onTick(self, tickEvent): now = self.subc.onTick(tickEvent) if now == self.now: return [] self.now = now self.candleshapes.onTick(tickEvent) self.peaks.onTick(tickEvent) self.detectLineDist() orders = [] #if lib.str2epoch("2019-11-15T00:30:00") == tickEvent.time: # print(tickEvent.time) ''' if self.id == -1: self.curr_side *= -1 if self.curr_side == env.SIDE_BUY: price = tickEvent.l - self.pipprice*3 else: price = tickEvent.h + self.pipprice*3 order = self.createStopOrder( tickEvent, self.instrument, self.curr_side, 1, price, validep=tickEvent.time+self.unitsecs, takeprofit=price+self.curr_side*self.profit, stoploss=price-self.curr_side*self.profit) if order != None: self.id = order.id orders.append(order) ''' return orders def onSignal(self, signalEvent): if self.id == signalEvent.id: if signalEvent.signal in [ env.ESTATUS_ORDER_CLOSED, env.ESTATUS_TRADE_CLOSED ]: self.id = -1
def testCase1(self): instrument = "USD_JPY" granularity = "M5" startep = lib.str2epoch("2019-11-12T12:00:00") endep = lib.str2epoch("2019-11-12T15:00:00") peakspan = 48 peaksize = 5 subc = SubChart("PeakIndex%d" % peakspan, instrument, granularity, startep, endep, nbars=max(peakspan + peaksize * 2 + 1, peakspan * 2)) p = PeakIndex(subc, peaksize, peakspan, peakspan * 2) # Just after initialization self.assertEqual(len(p.tops), 4) self.assertEqual(len(p.bottoms), 6) self.assertEqual(p.tops[1573548300], 109.266) self.assertEqual(p.tops[1573553400], 109.205) self.assertEqual(p.bottoms[1573545600], 109.21) self.assertEqual(p.bottoms[1573558200], 109.184) self.assertEqual(len(p.top_trendlines), 2) self.assertEqual(len(p.bottom_trendlines), 1) self.assertEqual("%.8f" % p.top_trendlines[1573550700], '-0.00000593') self.assertEqual("%.8f" % p.top_trendlines[1573548300], '-0.00001196') self.assertEqual("%.8f" % p.bottom_trendlines[1573554300], '0.00000769') self.assertEqual("%.3f" % p.maxs[1573548300], '109.266') self.assertEqual("%.3f" % p.mins[1573552500], '109.142') #After tick epoch = startep + 60 tickEvent = TickEvent(epoch, 0, 0, 0) subc.onTick(tickEvent) self.assertFalse(p.onTick(tickEvent)) epoch = startep + 300 tickEvent = TickEvent(epoch, 0, 0, 0) subc.onTick(tickEvent) self.assertTrue(p.onTick(tickEvent)) epoch = lib.str2epoch("2019-11-12T14:00:00") tickEvent = TickEvent(epoch, 0, 0, 0) subc.onTick(tickEvent) self.assertTrue(p.onTick(tickEvent)) self.assertEqual(len(p.tops), 5) self.assertEqual(len(p.bottoms), 6) self.assertEqual(len(p.top_trendlines), 1) self.assertEqual(len(p.bottom_trendlines), 3) self.assertEqual(p.tops[1573553100], 109.205) self.assertEqual(p.bottoms[1573552500], 109.142) epoch = lib.str2epoch("2019-11-12T16:00:00") tickEvent = TickEvent(epoch, 0, 0, 0) subc.onTick(tickEvent) self.assertTrue(p.onTick(tickEvent)) self.assertEqual(len(p.tops), 3) self.assertEqual(len(p.bottoms), 4) self.assertEqual(len(p.top_trendlines), 2) self.assertEqual(len(p.bottom_trendlines), 2)
class CheckIndex(TechnicalIndex): def __init__(self, instrument, granularity, startep=-1, endep=-1): super(CheckIndex, self).__init__(instrument, granularity) self.subc = SubChart(self.__class__.__name__, instrument, granularity, startep, endep) self.cntForNext = 0 self.nowidx = -1 self.now = -1 def onTick(self, tickEvent): i, epoch = self.subc.onTick(tickEvent) if i == -1: return False if self.now == epoch: return if self.cntForNext > 0: self.cntForNext -= (epoch - self.now) / self.unitsecs if self.cntForNext < 0: self.cntForNext = 0 self.nowidx = i self.now = epoch return True def isNextOK(self): if self.cntForNext == 0: return True else: return False def addForNext(self, cnt): self.cntForNext += cnt def getPriceAt(self, j=0): i = self.nowidx (t, ol, hl, ll, cl, vl) = self.subc.getPrices() k = i - j return (t[k], ol[k], hl[k], ll[k], cl[k], vl[k]) #direction=1: up dow #direction=-1: down dow def isDowCandle(self, direction=1): try: i = self.nowidx (_, _, hl, ll, _, _) = self.subc.getPrices() if direction == 1: if hl[i] > hl[i - 1] and ll[i] > ll[i - 1]: return True else: return False elif direction == -1: if hl[i] < hl[i - 1] and ll[i] < ll[i - 1]: return True else: return False else: return False except IndexError: lib.printError( self.now, "index error: i=%d len(hl)=%d len(ll)=%d" % (i, len(hl), len(ll))) raise IndexError def isWindowOpen(self, wsize=0): i = self.nowidx (_, _, hl, ll, _, _) = self.subc.getPrices() if hl[i] + wsize < ll[i - 1] or ll[i] - wsize > hl[i - 1]: return True return False def isHourRange(self, startHour, endHour): eh = (self.now % (3600 * 24)) / 3600 if eh >= startHour and eh <= endHour: return True return False def isNHoursBeforeWeekend(self, n): if self.isWeekend(): return False if math.floor((self.now / (3600 * 24) + 4) % 7) == 5: #Friday if self.isHourRange(20 - n, 21): return False return True def isNHoursAfterWeekend(self, n): if self.isWeekend(): return False dn = math.floor((self.now / (3600 * 24) + 4) % 7) if dn == 0: #Sunday if self.isHourRange(22, 22 + n): return False elif dn == 1 and n >= 2: # Monday if self.isHourRange(22, 24) or self.isHourRange(0, n - 2): return False return True # considering summer time, at this funtion # weekend starts 1 hour earlier on winter # and ends 1 hour later on summer, to make always the same result # New York time def isWeekend(self): dn = math.floor((self.now / (3600 * 24) + 4) % 7) if dn == 6: # Saturday return True elif dn == 0: # Sunday if self.isHourRange(0, 22): return True elif dn == 5: # Friday if self.isHourRange(20, 24): return True return False