def param_updated(self): # make sure parent updates its param super(OUAlgo, self).param_updated() # create autoregressive self.long_autoreg = AutoregOU(size=self.param['rolling']) self.short_autoreg = AutoregOU(size=self.param['rolling']) # create rolling self.spreadx_roll = SimpleMoving(size=self.param['rolling']) self.spready_roll = SimpleMoving(size=self.param['rolling']) #params self.bollinger = self.param['bollinger'] self.block = self.param['block'] #other params self.last_long_res = -999 self.last_short_res = -999 #records self.records = { 'timestamp': [], 'longs': [], 'shorts': [], 'long_mean': [], 'short_mean': [], 'long_sd': [], 'short_sd': [] } #tracker self.tracker = self.param['tracker']
def param_updated(self): # make sure parent updates its param super(StopWinSpreadGuardAlgo, self).param_updated() # algo settings self.min_ticksize = self.pair.x.symbol.min_ticksize # create rolling self.long_roll = SimpleMoving(size=self.param["rolling"]) self.short_roll = SimpleMoving(size=self.param["rolling"]) self.spreadx_roll = SimpleMoving(size=self.param["rolling"]) self.spready_roll = SimpleMoving(size=self.param["rolling"]) self.bollinger = self.param["bollinger"] self.block = self.param["block"] self.stop_win = self.param["stop_win"] # other params self.last_long_res = -999 self.last_short_res = -999 # records self.records = { "timestamp": [], "longs": [], "shorts": [], "long_mean": [], "short_mean": [], "long_sd": [], "short_sd": [], } # tracker self.tracker = self.param["tracker"]
def param_updated(self): # make sure parent updates its param super(SpreadGuardAlgo, self).param_updated() # algo settings self.min_ticksize = self.pair.x.symbol.min_ticksize # create rolling self.long_roll = SimpleMoving(size=self.param['rolling']) self.short_roll = SimpleMoving(size=self.param['rolling']) self.spreadx_roll = SimpleMoving(size = self.param['rolling']) self.spready_roll = SimpleMoving(size = self.param['rolling']) self.bollinger = self.param['bollinger'] self.block = self.param['block'] #other params self.last_long_res = -999 self.last_short_res = -999 #records self.records = {'timestamp': [], 'longs': [], 'shorts': [], 'long_mean': [], 'short_mean': [], 'long_sd': [], 'short_sd':[]} #tracker self.tracker = self.param['tracker']
def on_daystart(self, date, info_x, info_y): # recreate rolling at each day start self.long_autoreg = AutoregOU(size=self.param['rolling']) self.short_autoreg = AutoregOU(size=self.param['rolling']) self.spreadx_roll = SimpleMoving(size=self.param['rolling']) self.spready_roll = SimpleMoving(size=self.param['rolling'])
def param_updated(self): # make sure parent updates its param super(OUAlgo, self).param_updated() # create autoregressive self.long_autoreg = AutoregOU(size = self.param['rolling']) self.short_autoreg = AutoregOU(size = self.param['rolling']) # create rolling self.spreadx_roll = SimpleMoving(size = self.param['rolling']) self.spready_roll = SimpleMoving(size = self.param['rolling']) #params self.bollinger = self.param['bollinger'] self.block = self.param['block'] #other params self.last_long_res = -999 self.last_short_res = -999 #records self.records = {'timestamp': [], 'longs': [], 'shorts': [], 'long_mean': [], 'short_mean': [], 'long_sd': [], 'short_sd':[]} #tracker self.tracker = self.param['tracker'] self.orderfee = 0
def on_daystart(self, date, info_x, info_y): # recreate rolling at each day start self.long_autoreg = AutoregOU(size=self.param['rolling']) self.short_autoreg = AutoregOU(size=self.param['rolling']) self.spreadx_roll = SimpleMoving(size = self.param['rolling']) self.spready_roll = SimpleMoving(size = self.param['rolling'])
def param_updated(self): # make sure parent updates its param super(StopWinAlgo, self).param_updated() # algo settings self.if_ema = self.param['if_ema'] # if false, use sma self.if_stop_win = self.param['if_stop_win'] #if false, don't stop win self.if_consider_spread = self.param['if_consider_spread'] #if false, don't consider spread and fee # create rolling self.long_roll = SimpleMoving(size=self.param['rolling']) self.short_roll = SimpleMoving(size=self.param['rolling']) self.long_autoreg = Autoregressive(alpha = self.param['alpha']) self.short_autoreg = Autoregressive(alpha = self.param['alpha']) self.spreadx_roll = SimpleMoving(size = self.param['rolling']) self.spready_roll = SimpleMoving(size = self.param['rolling']) self.bollinger = self.param['bollinger'] self.block = self.param['block'] self.stop_win = self.param['stop_win'] #other params self.last_long_res = -999 self.last_short_res = -999 #records self.records = {'timestamp': [], 'longs': [], 'shorts': [], 'long_mean': [], 'short_mean': [], 'long_sd': [], 'short_sd':[]} #tracker self.tracker = TradeAnalysis(self.pair.x)
def param_updated(self): # make sure parent updates its param super(OUAlgo, self).param_updated() # create autoregressive self.long_autoreg = AutoregOU(size=self.param["rolling"]) self.short_autoreg = AutoregOU(size=self.param["rolling"]) # create rolling self.spreadx_roll = SimpleMoving(size=self.param["rolling"]) self.spready_roll = SimpleMoving(size=self.param["rolling"]) # params self.bollinger = self.param["bollinger"] self.block = self.param["block"] # other params self.last_long_res = -999 self.last_short_res = -999 # records self.records = { "timestamp": [], "longs": [], "shorts": [], "long_mean": [], "short_mean": [], "long_sd": [], "short_sd": [], } # tracker self.tracker = self.param["tracker"]
def on_daystart(self, date, info_x, info_y): # recreate rolling at each day start self.long_roll = SimpleMoving(size=self.param["rolling"]) self.short_roll = SimpleMoving(size=self.param["rolling"]) self.long_autoreg = Autoregressive(alpha=self.param["alpha"]) self.short_autoreg = Autoregressive(alpha=self.param["alpha"]) self.spreadx_roll = SimpleMoving(size=self.param["rolling"]) self.spready_roll = SimpleMoving(size=self.param["rolling"])
def param_updated(self): # make sure parent updates its param super(SMAAlgo, self).param_updated() # create rolling self.long_roll = SimpleMoving(size=self.param['rolling']) self.short_roll = SimpleMoving(size=self.param['rolling']) self.spreadx_roll = SimpleMoving(size = self.param['rolling']) self.spready_roll = SimpleMoving(size = self.param['rolling']) #params self.bollinger = self.param['bollinger'] self.block = self.param['block'] self.stop_win = self.param['stop_win'] #other params self.last_long_res = -999 self.last_short_res = -999 #records self.records = {'timestamp': [], 'longs': [], 'shorts': [], 'long_mean': [], 'short_mean': [], 'long_sd': [], 'short_sd':[]} self.max_profit = 0 #tracker self.tracker = TradeAnalysis(self.pair.x)
def param_updated(self): # make sure parent updates its param super(StopWinSpreadGuardAlgo, self).param_updated() # algo settings self.min_ticksize = self.pair.x.symbol.min_ticksize # create rolling self.long_roll = SimpleMoving(size=self.param['rolling']) self.short_roll = SimpleMoving(size=self.param['rolling']) self.spreadx_roll = SimpleMoving(size = self.param['rolling']) self.spready_roll = SimpleMoving(size = self.param['rolling']) self.bollinger = self.param['bollinger'] self.block = self.param['block'] self.stop_win = self.param['stop_win'] #other params self.last_long_res = -999 self.last_short_res = -999 #records self.records = {'timestamp': [], 'longs': [], 'shorts': [], 'long_mean': [], 'short_mean': [], 'long_sd': [], 'short_sd':[]} #tracker self.tracker = self.param['tracker']
def param_updated(self): # make sure parent updates its param super(SMAAlgo, self).param_updated() # create rolling self.long_roll = SimpleMoving(size=self.param['rolling']) self.short_roll = SimpleMoving(size=self.param['rolling']) self.bollinger = self.param['bollinger'] self.block = self.param['block'] self.stop_win = self.param['stop_win'] #other params self.last_long_res = -999 self.last_short_res = -999
def param_updated(self): # make sure parent updates its param super(StopWinAlgo, self).param_updated() # algo settings self.if_ema = self.param["if_ema"] # if false, use sma self.if_stop_win = self.param["if_stop_win"] # if false, don't stop win self.if_consider_spread = self.param["if_consider_spread"] # if false, don't consider spread and fee # create rolling self.long_roll = SimpleMoving(size=self.param["rolling"]) self.short_roll = SimpleMoving(size=self.param["rolling"]) self.long_autoreg = Autoregressive(alpha=self.param["alpha"]) self.short_autoreg = Autoregressive(alpha=self.param["alpha"]) self.spreadx_roll = SimpleMoving(size=self.param["rolling"]) self.spready_roll = SimpleMoving(size=self.param["rolling"]) self.bollinger = self.param["bollinger"] self.block = self.param["block"] self.stop_win = self.param["stop_win"] # other params self.last_long_res = -999 self.last_short_res = -999 # records self.records = { "timestamp": [], "longs": [], "shorts": [], "long_mean": [], "short_mean": [], "long_sd": [], "short_sd": [], } # tracker self.tracker = TradeAnalysis(self.pair.x)
class TestAlgo(PairAlgoWrapper): # called when algo param is set def param_updated(self): # make sure parent updates its param super(TestAlgo, self).param_updated() #self.long_roll = SimpleMoving(size=self.param['rolling']) #self.short_roll = SimpleMoving(size=self.param['rolling']) self.sd_coef = self.param['sd_coef'] self.block = self.param['block'] def on_daystart(self, date, info_x, info_y): pass # recreate rolling at each day start self.long_roll = SimpleMoving(size=self.param['rolling']) self.short_roll = SimpleMoving(size=self.param['rolling']) def on_dayend(self, date, info_x, info_y): pos = self.position_y() # stop short position if pos == -1: self.long_y(y_qty = 1) return # stop long position if pos == 1: self.short_y(y_qty = 1) return def on_tick(self, multiple, contract, info): # skip if price_table doesnt have both, TODO fix this bug internally if len(self.price_table.table) < 2: return # get residuals and position long_res = self.pair.get_long_residual() short_res = self.pair.get_short_residual() pos = self.position_y() # action only when unblocked: bock size < rolling queue size if self.long_roll.queue.qsize() > self.block: # long when test long_res > roll.mean+sd_coef*roll.sd if self.long_roll.test_sigma(long_res, self.sd_coef): # only long when position is 0 or -1 if pos <= 0: self.long_y(y_qty=1) # short when test short_res > roll.mean+sd_coef*roll.sd elif self.short_roll.test_sigma(short_res, self.sd_coef): # only short when position is 0 or 1 if pos >= 0: self.short_y(y_qty=1) else: pass # update rolling self.long_roll.add(long_res) self.short_roll.add(short_res)
class TestAlgo(PairAlgoWrapper): # called when algo param is set def param_updated(self): # make sure parent updates its param super(TestAlgo, self).param_updated() #self.long_roll = SimpleMoving(size=self.param['rolling']) #self.short_roll = SimpleMoving(size=self.param['rolling']) self.sd_coef = self.param['sd_coef'] self.block = self.param['block'] def on_daystart(self, date, info_x, info_y): pass # recreate rolling at each day start self.long_roll = SimpleMoving(size=self.param['rolling']) self.short_roll = SimpleMoving(size=self.param['rolling']) def on_dayend(self, date, info_x, info_y): pos = self.position_y() # stop short position if pos == -1: self.long_y(y_qty=1) return # stop long position if pos == 1: self.short_y(y_qty=1) return def on_tick(self, multiple, contract, info): # skip if price_table doesnt have both, TODO fix this bug internally if len(self.price_table.table) < 2: return # get residuals and position long_res = self.pair.get_long_residual() short_res = self.pair.get_short_residual() pos = self.position_y() # action only when unblocked: bock size < rolling queue size if self.long_roll.queue.qsize() > self.block: # long when test long_res > roll.mean+sd_coef*roll.sd if self.long_roll.test_sigma(long_res, self.sd_coef): # only long when position is 0 or -1 if pos <= 0: self.long_y(y_qty=1) # short when test short_res > roll.mean+sd_coef*roll.sd elif self.short_roll.test_sigma(short_res, self.sd_coef): # only short when position is 0 or 1 if pos >= 0: self.short_y(y_qty=1) else: pass # update rolling self.long_roll.add(long_res) self.short_roll.add(short_res)
class TestAlgo(PairAlgoWrapper): # called when algo param is set def param_updated(self): # make sure parent updates its param super(TestAlgo, self).param_updated() self.sd_coef = self.param['sd_coef'] self.block = self.param['block'] self.guard_coef = self.param['guard_coef'] self.stop_win = self.param['stop_win'] self.min_ticksize = self.pair.x.symbol.min_ticksize self.last_long_res = -999 self.last_short_res = -999 def on_daystart(self, date, info_x, info_y): # recreate rolling at each day start self.long_roll = SimpleMoving(size=self.param['rolling']) self.short_roll = SimpleMoving(size=self.param['rolling']) def on_dayend(self, date, info_x, info_y): pass def on_tick(self, multiple, contract, info): # skip if price_table doesnt have both, TODO fix this bug internally if len(self.price_table.table) < 2: return # get residuals and position long_res = self.pair.get_long_residual() short_res = self.pair.get_short_residual() pos = self.position_y() if pos == -1: if long_res + self.last_short_res >= max( self.stop_win, 2 * self.long_roll.sd) * self.min_ticksize: self.long_y(y_qty=1) return # stop long position if pos == 1: if short_res + self.last_long_res >= max( self.stop_win, 2 * self.short_roll.sd) * self.min_ticksize: self.short_y(y_qty=1) return # get ask-bid spread cost spreadcost = self.price_table.get_ask( self.pair.x) - self.price_table.get_bid( self.pair.x) + self.price_table.get_ask( self.pair.y) - self.price_table.get_bid(self.pair.y) if spreadcost < 0: raise Exception # action only when unblocked: bock size < rolling queue size if self.long_roll.queue.qsize() > self.block: # long when test long_res > roll.mean+sd_coef*roll.sd # if self.long_roll.test_sigma(long_res, self.sd_coef): if long_res > self.long_roll.mean + max( self.sd_coef * self.long_roll.sd, (self.guard_coef * self.min_ticksize + spreadcost)): # only long when position is 0 or -1 if pos <= 0: self.long_y(y_qty=1) self.last_long_res = long_res return # short when test short_res > roll.mean+sd_coef*roll.sd #elif self.short_roll.test_sigma(short_res, self.sd_coef): elif short_res > self.short_roll.mean + max( self.sd_coef * self.short_roll.sd, (self.guard_coef * self.min_ticksize + spreadcost)): # only short when position is 0 or 1 if pos >= 0: self.short_y(y_qty=1) self.last_short_res = short_res return # update rolling self.long_roll.add(long_res) self.short_roll.add(short_res)
class SpreadGuardAlgo(PairAlgoWrapper): # called when algo param is set def param_updated(self): # make sure parent updates its param super(SpreadGuardAlgo, self).param_updated() # algo settings self.min_ticksize = self.pair.x.symbol.min_ticksize # create rolling self.long_roll = SimpleMoving(size=self.param['rolling']) self.short_roll = SimpleMoving(size=self.param['rolling']) self.spreadx_roll = SimpleMoving(size = self.param['rolling']) self.spready_roll = SimpleMoving(size = self.param['rolling']) self.bollinger = self.param['bollinger'] self.block = self.param['block'] #other params self.last_long_res = -999 self.last_short_res = -999 #records self.records = {'timestamp': [], 'longs': [], 'shorts': [], 'long_mean': [], 'short_mean': [], 'long_sd': [], 'short_sd':[]} #tracker self.tracker = self.param['tracker'] # what to do on every tick def on_tick(self, multiple, contract, info): self.tracker.tick_pass_by() # tell the tracker that one tick passed by # skip if price_table doesnt have both if len(self.price_table.table) < 2: return # get residuals and position long_res = self.pair.get_long_residual() short_res = self.pair.get_short_residual() pos = self.position_y() trade_flag = 0 ## only do this when plotting is needed #update record # self._update_record(long_res, self.long_roll.mean, self.long_roll.sd,\ # short_res, self.short_roll.mean, self.short_roll.sd) #calculate profit for this round profit = 0 if pos == -1: profit = long_res + self.last_short_res elif pos == 1: profit = short_res + self.last_long_res #two spread spreadx = self.spreadx_roll.mean spready = self.spready_roll.mean avg_spread = (spreadx + spready)/2 #fee fee = self.pair.get_fee() # open or close position # action only when unblocked: bock size < rolling queue size if self.long_roll.queue.qsize() > self.block and trade_flag == 0: # long when test long_res > mean+bollinger*sd if self.long_roll.test_sigma(long_res, self.bollinger) and long_res - self.long_roll.mean > fee + avg_spread: # only long when position is 0 or -1 if pos <= 0: self.long_y(y_qty=1) self.last_long_res = long_res #tell the tracker if pos == 0: self.tracker.open_position() else: self.tracker.close_with_exit(profit - fee) # short when test short_res > mean+bollinger*sd elif self.short_roll.test_sigma(short_res, self.bollinger) and short_res - self.short_roll.mean > fee + avg_spread: # only short when position is 0 or 1 if pos >= 0: self.short_y(y_qty=1) self.last_short_res = short_res #tell the tracker if pos == 0: self.tracker.open_position() else: self.tracker.close_with_exit(profit - fee) # update rolling self.long_roll.add(long_res) self.short_roll.add(short_res) self.spreadx_roll.add(self.pair.get_spread_x()) self.spready_roll.add(self.pair.get_spread_y()) def on_daystart(self, date, info_x, info_y): # recreate rolling at each day start self.long_roll = SimpleMoving(size=self.param['rolling']) self.short_roll = SimpleMoving(size=self.param['rolling']) self.spreadx_roll = SimpleMoving(size = self.param['rolling']) self.spready_roll = SimpleMoving(size = self.param['rolling']) def on_dayend(self, date, info_x, info_y): #force close on day end pos = self.position_y() # stop short position if pos == -1: self.long_y(y_qty = 1) return # stop long position if pos == 1: self.short_y(y_qty = 1) return def _update_record(self, long_res, long_mean, long_std, short_res, short_mean, short_std): self.records['timestamp'].append(Clock.timestamp) self.records['longs'].append(long_res) self.records['shorts'].append(short_res) self.records['long_mean'].append(long_mean) self.records['short_mean'].append(short_mean) self.records['long_sd'].append(long_std) self.records['short_sd'].append(short_std)
class TestAlgo(PairAlgoWrapper): # called when algo param is set def param_updated(self): # make sure parent updates its param super(TestAlgo, self).param_updated() self.sd_coef = self.param['sd_coef'] self.block = self.param['block'] self.guard_coef = self.param['guard_coef'] self.stop_win = self.param['stop_win'] self.min_ticksize = self.pair.x.symbol.min_ticksize self.last_long_res = -999 self.last_short_res = -999 def on_daystart(self, date, info_x, info_y): # recreate rolling at each day start self.long_roll = SimpleMoving(size=self.param['rolling']) self.short_roll = SimpleMoving(size=self.param['rolling']) def on_dayend(self, date, info_x, info_y): print '{} settle price: x {}, y {}. PNL is {}'.format( date, info_x['SettlePrice'], info_y['SettlePrice'], self.account.get_pnl()) def on_tick(self, multiple, contract, info): # skip if price_table doesnt have both, TODO fix this bug internally if len(self.price_table.table) < 2: return # get residuals and position long_res = self.pair.get_long_residual() short_res = self.pair.get_short_residual() pos = self.position_y() if pos == -1: if long_res + self.last_short_res >= max(self.stop_win, 2*self.long_roll.sd) * self.min_ticksize: self.long_y(y_qty = 1) return # stop long position if pos == 1: if short_res + self.last_long_res >= max(self.stop_win, 2*self.short_roll.sd) * self.min_ticksize: self.short_y(y_qty = 1) return # get ask-bid spread cost spreadcost = self.price_table.get_ask(self.pair.x) - self.price_table.get_bid(self.pair.x) + self.price_table.get_ask(self.pair.y) - self.price_table.get_bid(self.pair.y) if spreadcost < 0: raise Exception # action only when unblocked: bock size < rolling queue size if self.long_roll.queue.qsize() > self.block: # long when test long_res > roll.mean+sd_coef*roll.sd # if self.long_roll.test_sigma(long_res, self.sd_coef): if long_res > self.long_roll.mean + max( self.sd_coef*self.long_roll.sd,(self.guard_coef*self.min_ticksize + spreadcost)) : # only long when position is 0 or -1 if pos <= 0: self.long_y(y_qty=1) # short when test short_res > roll.mean+sd_coef*roll.sd #elif self.short_roll.test_sigma(short_res, self.sd_coef): elif short_res > self.short_roll.mean + max( self.sd_coef*self.short_roll.sd,(self.guard_coef*self.min_ticksize + spreadcost)) : # only short when position is 0 or 1 if pos >= 0: self.short_y(y_qty=1) else: pass # update rolling self.long_roll.add(long_res) self.short_roll.add(short_res)
class StopWinSpreadGuardAlgo(PairAlgoWrapper): # called when algo param is set def param_updated(self): # make sure parent updates its param super(StopWinSpreadGuardAlgo, self).param_updated() # algo settings self.min_ticksize = self.pair.x.symbol.min_ticksize # create rolling self.long_roll = SimpleMoving(size=self.param['rolling']) self.short_roll = SimpleMoving(size=self.param['rolling']) self.spreadx_roll = SimpleMoving(size = self.param['rolling']) self.spready_roll = SimpleMoving(size = self.param['rolling']) self.bollinger = self.param['bollinger'] self.block = self.param['block'] self.stop_win = self.param['stop_win'] #other params self.last_long_res = -999 self.last_short_res = -999 #records self.records = {'timestamp': [], 'longs': [], 'shorts': [], 'long_mean': [], 'short_mean': [], 'long_sd': [], 'short_sd':[]} #tracker self.tracker = self.param['tracker'] # what to do on every tick def on_tick(self, multiple, contract, info): self.tracker.tick_pass_by() # tell the tracker that one tick passed by # skip if price_table doesnt have both if len(self.price_table.table) < 2: return # get residuals and position long_res = self.pair.get_long_residual() short_res = self.pair.get_short_residual() pos = self.position_y() trade_flag = 0 ## only do this when plotting is needed #update record # self._update_record(long_res, self.long_roll.mean, self.long_roll.sd,\ # short_res, self.short_roll.mean, self.short_roll.sd) #calculate profit for this round profit = 0 if pos == -1: profit = long_res + self.last_short_res elif pos == 1: profit = short_res + self.last_long_res #two spread spreadx = self.spreadx_roll.mean spready = self.spready_roll.mean avg_spread = (spreadx + spready)/2 #fee fee = self.pair.get_fee() #stop win # stop short position if pos == -1: if profit >= max(self.min_ticksize, self.stop_win * self.long_roll.sd, fee): self.long_y(y_qty = 1) self.last_long_res = long_res self.tracker.close_with_stop(profit - fee) trade_flag = 1 # stop long position if pos == 1: if profit >= max(self.min_ticksize, self.stop_win * self.short_roll.sd, fee): self.short_y(y_qty = 1) self.last_short_res = short_res self.tracker.close_with_stop(profit - fee) trade_flag = 1 # open or close position # action only when unblocked: bock size < rolling queue size if self.long_roll.queue.qsize() > self.block and trade_flag == 0: # long when test long_res > mean+bollinger*sd if self.long_roll.test_sigma(long_res, self.bollinger) \ and long_res - self.long_roll.mean > fee + avg_spread: # only long when position is 0 or -1 if pos <= 0: self.long_y(y_qty=1) self.last_long_res = long_res #tell the tracker if pos == 0: self.tracker.open_position() else: self.tracker.close_with_exit(profit - fee) # short when test short_res > mean+bollinger*sd elif self.short_roll.test_sigma(short_res, self.bollinger) \ and short_res - self.short_roll.mean > fee + avg_spread: # only short when position is 0 or 1 if pos >= 0: self.short_y(y_qty=1) self.last_short_res = short_res #tell the tracker if pos == 0: self.tracker.open_position() else: self.tracker.close_with_exit(profit - fee) # update rolling self.long_roll.add(long_res) self.short_roll.add(short_res) self.spreadx_roll.add(self.pair.get_spread_x()) self.spready_roll.add(self.pair.get_spread_y()) def on_daystart(self, date, info_x, info_y): # recreate rolling at each day start self.long_roll = SimpleMoving(size=self.param['rolling']) self.short_roll = SimpleMoving(size=self.param['rolling']) self.spreadx_roll = SimpleMoving(size = self.param['rolling']) self.spready_roll = SimpleMoving(size = self.param['rolling']) def on_dayend(self, date, info_x, info_y): #force close on day end pos = self.position_y() # stop short position if pos == -1: self.long_y(y_qty = 1) return # stop long position if pos == 1: self.short_y(y_qty = 1) return def _update_record(self, long_res, long_mean, long_std, short_res, short_mean, short_std): self.records['timestamp'].append(Clock.timestamp) self.records['longs'].append(long_res) self.records['shorts'].append(short_res) self.records['long_mean'].append(long_mean) self.records['short_mean'].append(short_mean) self.records['long_sd'].append(long_std) self.records['short_sd'].append(short_std)
class EMAAlgo(PairAlgoWrapper): # called when algo param is set def param_updated(self): # make sure parent updates its param super(EMAAlgo, self).param_updated() # create rolling self.long_autoreg = Autoregressive(alpha = self.param['alpha']) self.short_autoreg = Autoregressive(alpha = self.param['alpha']) self.long_roll = SimpleMoving(size = self.param['rolling']) self.short_roll = SimpleMoving(size = self.param['rolling']) self.bollinger = self.param['bollinger'] self.block = self.param['block'] self.stop_win = self.param['stop_win'] #other params self.last_long_res = -999 self.last_short_res = -999 def on_tick(self, multiple, contract, info): # skip if price_table doesnt have both, TODO fix this bug internally if len(self.price_table.table) < 2: return # get residuals and position long_res = self.pair.get_long_residual() short_res = self.pair.get_short_residual() pos = self.position_y() # update rolling self.long_autoreg.add(long_res) self.short_autoreg.add(short_res) self.long_roll.add(long_res) self.short_roll.add(short_res) long_mean = self.long_autoreg.getMean() short_mean = self.short_autoreg.getMean() long_std = self.long_roll.sd short_std = self.short_roll.sd # stop short position if pos == -1: if long_res + self.last_short_res >= self.stop_win * long_std: self.long_y(y_qty = 1) return # stop long position if pos == 1: if short_res + self.last_long_res >= self.stop_win * short_std: self.short_y(y_qty = 1) return # action only when unblocked: bock size < rolling queue size if self.long_roll.queue.qsize() > self.block: # long when test long_res > mean+bollinger*std if long_res > long_mean + self.bollinger * long_std: # only long when position is 0 or -1 if pos <= 0: self.long_y(y_qty=1) self.last_long_res = long_res return # short when test short_res > mean+bollinger*std elif short_res > short_mean + self.bollinger * short_std: # only short when position is 0 or 1 if pos >= 0: self.short_y(y_qty=1) self.last_short_res = short_res return def on_daystart(self, date, info_x, info_y): #create new stuff on day start self.long_autoreg = Autoregressive(alpha = self.param['alpha']) self.short_autoreg = Autoregressive(alpha = self.param['alpha']) self.long_roll = SimpleMoving(size = self.param['rolling']) self.short_roll = SimpleMoving(size = self.param['rolling']) def on_dayend(self, date, info_x, info_y): pos = self.position_y() # stop short position if pos == -1: self.long_y(y_qty = 1) return # stop long position if pos == 1: self.short_y(y_qty = 1) return
def on_daystart(self, date, info_x, info_y): #create new stuff on day start self.long_autoreg = Autoregressive(alpha = self.param['alpha']) self.short_autoreg = Autoregressive(alpha = self.param['alpha']) self.long_roll = SimpleMoving(size = self.param['rolling']) self.short_roll = SimpleMoving(size = self.param['rolling'])
class StopWinAlgo(PairAlgoWrapper): # called when algo param is set def param_updated(self): # make sure parent updates its param super(StopWinAlgo, self).param_updated() # algo settings self.if_ema = self.param['if_ema'] # if false, use sma self.if_stop_win = self.param['if_stop_win'] #if false, don't stop win self.if_consider_spread = self.param[ 'if_consider_spread'] #if false, don't consider spread and fee # create rolling self.long_roll = SimpleMoving(size=self.param['rolling']) self.short_roll = SimpleMoving(size=self.param['rolling']) self.long_autoreg = Autoregressive(alpha=self.param['alpha']) self.short_autoreg = Autoregressive(alpha=self.param['alpha']) self.spreadx_roll = SimpleMoving(size=self.param['rolling']) self.spready_roll = SimpleMoving(size=self.param['rolling']) self.bollinger = self.param['bollinger'] self.block = self.param['block'] self.stop_win = self.param['stop_win'] #other params self.last_long_res = -999 self.last_short_res = -999 #records self.records = { 'timestamp': [], 'longs': [], 'shorts': [], 'long_mean': [], 'short_mean': [], 'long_sd': [], 'short_sd': [] } #tracker self.tracker = TradeAnalysis(self.pair.x) # what to do on every tick def on_tick(self, multiple, contract, info): self.tracker.tick_pass_by() # tell the tracker that one tick passed by # skip if price_table doesnt have both if len(self.price_table.table) < 2: return # get residuals and position long_res = self.pair.get_long_residual() short_res = self.pair.get_short_residual() pos = self.position_y() ## only do this when plotting is neede #update record # if self.if_ema: # self._update_record(long_res, self.autoreg.mean, self.long_roll.sd,\ # short_res, self.autoreg.mean, self.short_roll.sd) # else: # self._update_record(long_res, self.long_roll.mean, self.long_roll.sd,\ # short_res, self.short_roll.mean, self.short_roll.sd) #calculate profit for this round profit = 0 if pos == -1: profit = long_res + self.last_short_res elif pos == 1: profit = short_res + self.last_long_res #two spread spreadx = self.spreadx_roll.mean spready = self.spready_roll.mean avg_spread = (spreadx + spready) / 2 #fee fee = self.pair.get_fee() # stop short position if self.if_stop_win: if pos == -1: if (profit >= max(1, self.stop_win * self.long_roll.sd) and self.if_consider_spread == False) \ or (profit >= max(1, self.stop_win * self.long_roll.sd, fee) and self.if_consider_spread == True): self.long_y(y_qty=1) self.last_long_res = long_res self.tracker.close_with_stop(profit) return # stop long position if pos == 1: if (profit >= max(1, self.stop_win * self.long_roll.sd) and self.if_consider_spread == False) \ or (profit >= max(1, self.stop_win * self.long_roll.sd, fee) and self.if_consider_spread == True): self.short_y(y_qty=1) self.last_short_res = short_res self.tracker.close_with_stop(profit) return # open or close position # action only when unblocked: bock size < rolling queue size if self.long_roll.queue.qsize() > self.block: # long when test long_res > mean+bollinger*sd if (long_res > self.long_autoreg.mean + self.bollinger * self.long_roll.sd \ and self.if_ema == True and self.if_consider_spread == False) \ or (self.long_roll.test_sigma(long_res, self.bollinger) \ and self.if_ema == False and self.if_consider_spread == False) \ or (long_res - self.long_autoreg.mean > max(fee + avg_spread, self.bollinger * self.long_roll.sd) \ and self.if_ema == True and self.if_consider_spread == True) \ or (self.long_roll.test_sigma(long_res, self.bollinger) \ and long_res - self.long_roll.mean > fee + avg_spread \ and self.if_ema == False and self.if_consider_spread == True): \ # only long when position is 0 or -1 if pos <= 0: self.long_y(y_qty=1) self.last_long_res = long_res #tell the tracker if pos == 0: self.tracker.open_position() else: self.tracker.close_with_exit(profit) return # short when test short_res > mean+bollinger*sd elif (short_res > self.short_autoreg.mean + self.bollinger * self.short_roll.sd \ and self.if_ema == True and self.if_consider_spread == False) \ or (self.short_roll.test_sigma(short_res, self.bollinger) \ and self.if_ema == False and self.if_consider_spread == False) \ or (short_res - self.short_autoreg.mean > max(fee + avg_spread, self.bollinger * self.short_roll.sd) \ and self.if_ema == True and self.if_consider_spread == True) \ or (self.short_roll.test_sigma(short_res, self.bollinger) \ and short_res - self.short_roll.mean > fee + avg_spread \ and self.if_ema == False and self.if_consider_spread == True): \ # only short when position is 0 or 1 if pos >= 0: self.short_y(y_qty=1) self.last_short_res = short_res #tell the tracker if pos == 0: self.tracker.open_position() else: self.tracker.close_with_exit(profit) return else: pass # update rolling self.long_roll.add(long_res) self.short_roll.add(short_res) self.long_autoreg.add(long_res) self.short_autoreg.add(short_res) self.spreadx_roll.add(self.pair.get_spread_x()) self.spready_roll.add(self.pair.get_spread_y()) def on_daystart(self, date, info_x, info_y): # recreate rolling at each day start self.long_roll = SimpleMoving(size=self.param['rolling']) self.short_roll = SimpleMoving(size=self.param['rolling']) self.long_autoreg = Autoregressive(alpha=self.param['alpha']) self.short_autoreg = Autoregressive(alpha=self.param['alpha']) self.spreadx_roll = SimpleMoving(size=self.param['rolling']) self.spready_roll = SimpleMoving(size=self.param['rolling']) def on_dayend(self, date, info_x, info_y): #force close on day end pos = self.position_y() # stop short position if pos == -1: self.long_y(y_qty=1) return # stop long position if pos == 1: self.short_y(y_qty=1) return def _update_record(self, long_res, long_mean, long_std, short_res, short_mean, short_std): self.records['timestamp'].append(Clock.timestamp) self.records['longs'].append(long_res) self.records['shorts'].append(short_res) self.records['long_mean'].append(long_mean) self.records['short_mean'].append(short_mean) self.records['long_sd'].append(long_std) self.records['short_sd'].append(short_std)
class SMAAlgo(PairAlgoWrapper): # called when algo param is set def param_updated(self): # make sure parent updates its param super(SMAAlgo, self).param_updated() # create rolling self.long_roll = SimpleMoving(size=self.param['rolling']) self.short_roll = SimpleMoving(size=self.param['rolling']) self.spreadx_roll = SimpleMoving(size = self.param['rolling']) self.spready_roll = SimpleMoving(size = self.param['rolling']) #params self.bollinger = self.param['bollinger'] self.block = self.param['block'] self.stop_win = self.param['stop_win'] #other params self.last_long_res = -999 self.last_short_res = -999 #records self.records = {'timestamp': [], 'longs': [], 'shorts': [], 'long_mean': [], 'short_mean': [], 'long_sd': [], 'short_sd':[]} self.max_profit = 0 #tracker self.tracker = TradeAnalysis(self.pair.x) def on_tick(self, multiple, contract, info): self.tracker.tick_pass_by() # skip if price_table doesnt have both, TODO fix this bug internally if len(self.price_table.table) < 2: return # get residuals and position long_res = self.pair.get_long_residual() short_res = self.pair.get_short_residual() pos = self.position_y() #two spread spreadx = self.spreadx_roll.mean spready = self.spready_roll.mean avg_spread = (spreadx + spready)/2 #fee fee = self.pair.get_fee() #update record # self._update_record(long_res, self.long_roll.mean, self.long_roll.sd,\ # short_res, self.short_roll.mean, self.short_roll.sd) #calculate profit profit = 0 if pos == -1: profit = long_res + self.last_short_res elif pos == 1: profit = short_res + self.last_long_res #trailing stop win if profit > self.max_profit and profit > 0: self.max_profit = profit else: # stop short position if pos == -1: if self.max_profit - profit > max(1,self.stop_win * self.long_roll.sd) and profit > 0: self.long_y(y_qty = 1) self.last_long_res = long_res self.tracker.close_with_stop(profit - fee) return # stop long position if pos == 1: if self.max_profit - profit > max(1,self.stop_win * self.short_roll.sd) and profit > 0: self.short_y(y_qty = 1) self.last_short_res = short_res self.tracker.close_with_stop(profit - fee) return # action only when unblocked: bock size < rolling queue size if self.long_roll.queue.qsize() > self.block: # long when test long_res > mean+bollinger*sd if self.long_roll.test_sigma(long_res, self.bollinger) \ and long_res > self.long_roll.mean + avg_spread + fee/2: # only long when position is 0 or -1 if pos <= 0: self.long_y(y_qty=1) self.last_long_res = long_res self.max_profit = 0 #tell the tracker if pos == 0: self.tracker.open_position() else: self.tracker.close_with_exit(profit - fee) return # short when test short_res > mean+bollinger*sd elif self.short_roll.test_sigma(short_res, self.bollinger) \ and short_res > self.short_roll.mean + avg_spread + fee/2: # only short when position is 0 or 1 if pos >= 0: self.short_y(y_qty=1) self.last_short_res = short_res self.max_profit = 0 #tell the tracker if pos == 0: self.tracker.open_position() else: self.tracker.close_with_exit(profit - fee) return else: pass # update rolling self.long_roll.add(long_res) self.short_roll.add(short_res) self.spreadx_roll.add(self.pair.get_spread_x()) self.spready_roll.add(self.pair.get_spread_y()) def on_daystart(self, date, info_x, info_y): # recreate rolling at each day start self.long_roll = SimpleMoving(size=self.param['rolling']) self.short_roll = SimpleMoving(size=self.param['rolling']) self.spreadx_roll = SimpleMoving(size = self.param['rolling']) self.spready_roll = SimpleMoving(size = self.param['rolling']) def on_dayend(self, date, info_x, info_y): pos = self.position_y() # stop short position if pos == -1: self.long_y(y_qty = 1) return # stop long position if pos == 1: self.short_y(y_qty = 1) return def _update_record(self, long_res, long_mean, long_std, short_res, short_mean, short_std): self.records['timestamp'].append(Clock.timestamp) self.records['longs'].append(long_res) self.records['shorts'].append(short_res) self.records['long_mean'].append(long_mean) self.records['short_mean'].append(short_mean) self.records['long_sd'].append(long_std) self.records['short_sd'].append(short_std)
class OUAlgo(PairAlgoWrapper): # called when algo param is set def param_updated(self): # make sure parent updates its param super(OUAlgo, self).param_updated() # create autoregressive self.long_autoreg = AutoregOU(size = self.param['rolling']) self.short_autoreg = AutoregOU(size = self.param['rolling']) # create rolling self.spreadx_roll = SimpleMoving(size = self.param['rolling']) self.spready_roll = SimpleMoving(size = self.param['rolling']) #params self.bollinger = self.param['bollinger'] self.block = self.param['block'] #other params self.last_long_res = -999 self.last_short_res = -999 #records self.records = {'timestamp': [], 'longs': [], 'shorts': [], 'long_mean': [], 'short_mean': [], 'long_sd': [], 'short_sd':[]} #tracker self.tracker = self.param['tracker'] self.orderfee = 0 def on_tick(self, multiple, contract, info): self.tracker.tick_pass_by() # skip if price_table doesnt have both, TODO fix this bug internally if self.price_table.get_size() < 2: return # get residuals and position long_res = self.pair.get_long_residual() short_res = self.pair.get_short_residual() pos = self.position_y() #two spread spreadx = self.spreadx_roll.mean spready = self.spready_roll.mean avg_spread = (spreadx + spready)/2 #fee fee = self.pair.get_fee() #update record #self._update_record(float(long_res), float(self.long_autoreg.mean), float(self.long_autoreg.sd), float(short_res), float(self.short_autoreg.mean), float(self.short_autoreg.sd)) #calculate profit profit = 0 if pos == -1: profit = long_res + self.last_short_res elif pos == 1: profit = short_res + self.last_long_res # action only when unblocked: bock size < rolling queue size if self.long_autoreg.get_length() > self.block: # long when test long_res > mean+bollinger*sd if self.long_autoreg.test_sigma(long_res, self.bollinger): # only long when position is 0 or -1 if pos <= 0: try: [order1, order2] = self.long_y(y_qty=1) self.last_long_res = long_res #tell the tracker if pos == 0: self.orderfee = order1.fee + order2.fee self.tracker.open_position() else: self.orderfee += order1.fee + order2.fee self.tracker.close_with_exit(profit, self.orderfee) except Exception: pass # short when test short_res > mean + bollinger*sd elif self.short_autoreg.test_sigma(short_res, self.bollinger): # only short when position is 0 or 1 if pos >= 0: try: [order1, order2] = self.short_y(y_qty=1) self.last_short_res = short_res #tell the tracker if pos == 0: self.orderfee = order1.fee + order2.fee self.tracker.open_position() else: self.orderfee += order1.fee + order2.fee self.tracker.close_with_exit(profit, self.orderfee) except Exception: pass # update rolling self.long_autoreg.add(long_res) self.short_autoreg.add(short_res) self.spreadx_roll.add(self.pair.get_spread_x()) self.spready_roll.add(self.pair.get_spread_y()) def on_daystart(self, date, info_x, info_y): # recreate rolling at each day start self.long_autoreg = AutoregOU(size=self.param['rolling']) self.short_autoreg = AutoregOU(size=self.param['rolling']) self.spreadx_roll = SimpleMoving(size = self.param['rolling']) self.spready_roll = SimpleMoving(size = self.param['rolling']) def on_dayend(self, date, info_x, info_y): pos = self.position_y() # stop short position if pos == -1: self.long_y(y_qty = 1) return # stop long position if pos == 1: self.short_y(y_qty = 1) return def on_risk(self, policy, risk_info): print '{} {} @ {}: {} {}/{}'.format(risk_info.action_type, risk_info.contract.name, risk_info.timestamp, risk_info.message, risk_info.value, risk_info.limit) def _update_record(self, long_res, long_mean, long_std, short_res, short_mean, short_std): self.records['timestamp'].append(Clock.timestamp) self.records['longs'].append(long_res) self.records['shorts'].append(short_res) self.records['long_mean'].append(long_mean) self.records['short_mean'].append(short_mean) self.records['long_sd'].append(long_std) self.records['short_sd'].append(short_std)
class StopWinAlgo(PairAlgoWrapper): # called when algo param is set def param_updated(self): # make sure parent updates its param super(StopWinAlgo, self).param_updated() # algo settings self.if_ema = self.param["if_ema"] # if false, use sma self.if_stop_win = self.param["if_stop_win"] # if false, don't stop win self.if_consider_spread = self.param["if_consider_spread"] # if false, don't consider spread and fee # create rolling self.long_roll = SimpleMoving(size=self.param["rolling"]) self.short_roll = SimpleMoving(size=self.param["rolling"]) self.long_autoreg = Autoregressive(alpha=self.param["alpha"]) self.short_autoreg = Autoregressive(alpha=self.param["alpha"]) self.spreadx_roll = SimpleMoving(size=self.param["rolling"]) self.spready_roll = SimpleMoving(size=self.param["rolling"]) self.bollinger = self.param["bollinger"] self.block = self.param["block"] self.stop_win = self.param["stop_win"] # other params self.last_long_res = -999 self.last_short_res = -999 # records self.records = { "timestamp": [], "longs": [], "shorts": [], "long_mean": [], "short_mean": [], "long_sd": [], "short_sd": [], } # tracker self.tracker = TradeAnalysis(self.pair.x) # what to do on every tick def on_tick(self, multiple, contract, info): self.tracker.tick_pass_by() # tell the tracker that one tick passed by # skip if price_table doesnt have both if len(self.price_table.table) < 2: return # get residuals and position long_res = self.pair.get_long_residual() short_res = self.pair.get_short_residual() pos = self.position_y() ## only do this when plotting is neede # update record # if self.if_ema: # self._update_record(long_res, self.autoreg.mean, self.long_roll.sd,\ # short_res, self.autoreg.mean, self.short_roll.sd) # else: # self._update_record(long_res, self.long_roll.mean, self.long_roll.sd,\ # short_res, self.short_roll.mean, self.short_roll.sd) # calculate profit for this round profit = 0 if pos == -1: profit = long_res + self.last_short_res elif pos == 1: profit = short_res + self.last_long_res # two spread spreadx = self.spreadx_roll.mean spready = self.spready_roll.mean avg_spread = (spreadx + spready) / 2 # fee fee = self.pair.get_fee() # stop short position if self.if_stop_win: if pos == -1: if (profit >= max(1, self.stop_win * self.long_roll.sd) and self.if_consider_spread == False) or ( profit >= max(1, self.stop_win * self.long_roll.sd, fee) and self.if_consider_spread == True ): self.long_y(y_qty=1) self.last_long_res = long_res self.tracker.close_with_stop(profit) return # stop long position if pos == 1: if (profit >= max(1, self.stop_win * self.long_roll.sd) and self.if_consider_spread == False) or ( profit >= max(1, self.stop_win * self.long_roll.sd, fee) and self.if_consider_spread == True ): self.short_y(y_qty=1) self.last_short_res = short_res self.tracker.close_with_stop(profit) return # open or close position # action only when unblocked: bock size < rolling queue size if self.long_roll.queue.qsize() > self.block: # long when test long_res > mean+bollinger*sd if ( ( long_res > self.long_autoreg.mean + self.bollinger * self.long_roll.sd and self.if_ema == True and self.if_consider_spread == False ) or ( self.long_roll.test_sigma(long_res, self.bollinger) and self.if_ema == False and self.if_consider_spread == False ) or ( long_res - self.long_autoreg.mean > max(fee + avg_spread, self.bollinger * self.long_roll.sd) and self.if_ema == True and self.if_consider_spread == True ) or ( self.long_roll.test_sigma(long_res, self.bollinger) and long_res - self.long_roll.mean > fee + avg_spread and self.if_ema == False and self.if_consider_spread == True ) ): # only long when position is 0 or -1 if pos <= 0: self.long_y(y_qty=1) self.last_long_res = long_res # tell the tracker if pos == 0: self.tracker.open_position() else: self.tracker.close_with_exit(profit) return # short when test short_res > mean+bollinger*sd elif ( ( short_res > self.short_autoreg.mean + self.bollinger * self.short_roll.sd and self.if_ema == True and self.if_consider_spread == False ) or ( self.short_roll.test_sigma(short_res, self.bollinger) and self.if_ema == False and self.if_consider_spread == False ) or ( short_res - self.short_autoreg.mean > max(fee + avg_spread, self.bollinger * self.short_roll.sd) and self.if_ema == True and self.if_consider_spread == True ) or ( self.short_roll.test_sigma(short_res, self.bollinger) and short_res - self.short_roll.mean > fee + avg_spread and self.if_ema == False and self.if_consider_spread == True ) ): # only short when position is 0 or 1 if pos >= 0: self.short_y(y_qty=1) self.last_short_res = short_res # tell the tracker if pos == 0: self.tracker.open_position() else: self.tracker.close_with_exit(profit) return else: pass # update rolling self.long_roll.add(long_res) self.short_roll.add(short_res) self.long_autoreg.add(long_res) self.short_autoreg.add(short_res) self.spreadx_roll.add(self.pair.get_spread_x()) self.spready_roll.add(self.pair.get_spread_y()) def on_daystart(self, date, info_x, info_y): # recreate rolling at each day start self.long_roll = SimpleMoving(size=self.param["rolling"]) self.short_roll = SimpleMoving(size=self.param["rolling"]) self.long_autoreg = Autoregressive(alpha=self.param["alpha"]) self.short_autoreg = Autoregressive(alpha=self.param["alpha"]) self.spreadx_roll = SimpleMoving(size=self.param["rolling"]) self.spready_roll = SimpleMoving(size=self.param["rolling"]) def on_dayend(self, date, info_x, info_y): # force close on day end pos = self.position_y() # stop short position if pos == -1: self.long_y(y_qty=1) return # stop long position if pos == 1: self.short_y(y_qty=1) return def _update_record(self, long_res, long_mean, long_std, short_res, short_mean, short_std): self.records["timestamp"].append(Clock.timestamp) self.records["longs"].append(long_res) self.records["shorts"].append(short_res) self.records["long_mean"].append(long_mean) self.records["short_mean"].append(short_mean) self.records["long_sd"].append(long_std) self.records["short_sd"].append(short_std)
class OUAlgo(PairAlgoWrapper): # called when algo param is set def param_updated(self): # make sure parent updates its param super(OUAlgo, self).param_updated() # create autoregressive self.long_autoreg = AutoregOU(size=self.param['rolling']) self.short_autoreg = AutoregOU(size=self.param['rolling']) # create rolling self.spreadx_roll = SimpleMoving(size=self.param['rolling']) self.spready_roll = SimpleMoving(size=self.param['rolling']) #params self.bollinger = self.param['bollinger'] self.block = self.param['block'] #other params self.last_long_res = -999 self.last_short_res = -999 #records self.records = { 'timestamp': [], 'longs': [], 'shorts': [], 'long_mean': [], 'short_mean': [], 'long_sd': [], 'short_sd': [] } #tracker self.tracker = self.param['tracker'] def on_tick(self, multiple, contract, info): self.tracker.tick_pass_by() # skip if price_table doesnt have both, TODO fix this bug internally if self.price_table.get_size() < 2: return # get residuals and position long_res = self.pair.get_long_residual() short_res = self.pair.get_short_residual() pos = self.position_y() #two spread spreadx = self.spreadx_roll.mean spready = self.spready_roll.mean avg_spread = (spreadx + spready) / 2 #fee fee = self.pair.get_fee() #update record #self._update_record(float(long_res), float(self.long_autoreg.mean), float(self.long_autoreg.sd),\ # float(short_res), float(self.short_autoreg.mean), float(self.short_autoreg.sd)) #calculate profit profit = 0 if pos == -1: profit = long_res + self.last_short_res elif pos == 1: profit = short_res + self.last_long_res # action only when unblocked: bock size < rolling queue size if self.long_autoreg.get_length() > self.block: # long when test long_res > mean+bollinger*sd if self.long_autoreg.test_sigma(long_res, self.bollinger) \ and long_res > self.long_autoreg.mean + avg_spread + fee/2: # only long when position is 0 or -1 if pos <= 0: self.long_y(y_qty=1) self.last_long_res = long_res #tell the tracker if pos == 0: self.tracker.open_position() else: self.tracker.close_with_exit(profit - fee) # short when test short_res > mean + bollinger*sd elif self.short_autoreg.test_sigma(short_res, self.bollinger) \ and short_res > self.short_autoreg.mean + avg_spread + fee/2: # only short when position is 0 or 1 if pos >= 0: self.short_y(y_qty=1) self.last_short_res = short_res #tell the tracker if pos == 0: self.tracker.open_position() else: self.tracker.close_with_exit(profit - fee) # update rolling self.long_autoreg.add(long_res) self.short_autoreg.add(short_res) self.spreadx_roll.add(self.pair.get_spread_x()) self.spready_roll.add(self.pair.get_spread_y()) def on_daystart(self, date, info_x, info_y): # recreate rolling at each day start self.long_autoreg = AutoregOU(size=self.param['rolling']) self.short_autoreg = AutoregOU(size=self.param['rolling']) self.spreadx_roll = SimpleMoving(size=self.param['rolling']) self.spready_roll = SimpleMoving(size=self.param['rolling']) def on_dayend(self, date, info_x, info_y): pos = self.position_y() # stop short position if pos == -1: self.long_y(y_qty=1) return # stop long position if pos == 1: self.short_y(y_qty=1) return def _update_record(self, long_res, long_mean, long_std, short_res, short_mean, short_std): self.records['timestamp'].append(Clock.timestamp) self.records['longs'].append(long_res) self.records['shorts'].append(short_res) self.records['long_mean'].append(long_mean) self.records['short_mean'].append(short_mean) self.records['long_sd'].append(long_std) self.records['short_sd'].append(short_std)
def on_daystart(self, date, info_x, info_y): # recreate rolling at each day start self.long_roll = SimpleMoving(size=self.param['rolling']) self.short_roll = SimpleMoving(size=self.param['rolling'])
class OUAlgo(PairAlgoWrapper): # called when algo param is set def param_updated(self): # make sure parent updates its param super(OUAlgo, self).param_updated() # create autoregressive self.long_autoreg = AutoregOU(size=self.param["rolling"]) self.short_autoreg = AutoregOU(size=self.param["rolling"]) # create rolling self.spreadx_roll = SimpleMoving(size=self.param["rolling"]) self.spready_roll = SimpleMoving(size=self.param["rolling"]) # params self.bollinger = self.param["bollinger"] self.block = self.param["block"] # other params self.last_long_res = -999 self.last_short_res = -999 # records self.records = { "timestamp": [], "longs": [], "shorts": [], "long_mean": [], "short_mean": [], "long_sd": [], "short_sd": [], } # tracker self.tracker = self.param["tracker"] def on_tick(self, multiple, contract, info): self.tracker.tick_pass_by() # skip if price_table doesnt have both, TODO fix this bug internally if self.price_table.get_size() < 2: return # get residuals and position long_res = self.pair.get_long_residual() short_res = self.pair.get_short_residual() pos = self.position_y() # two spread spreadx = self.spreadx_roll.mean spready = self.spready_roll.mean avg_spread = (spreadx + spready) / 2 # fee fee = self.pair.get_fee() # update record # self._update_record(float(long_res), float(self.long_autoreg.mean), float(self.long_autoreg.sd),\ # float(short_res), float(self.short_autoreg.mean), float(self.short_autoreg.sd)) # calculate profit profit = 0 if pos == -1: profit = long_res + self.last_short_res elif pos == 1: profit = short_res + self.last_long_res # action only when unblocked: bock size < rolling queue size if self.long_autoreg.get_length() > self.block: # long when test long_res > mean+bollinger*sd if ( self.long_autoreg.test_sigma(long_res, self.bollinger) and long_res > self.long_autoreg.mean + avg_spread + fee / 2 ): # only long when position is 0 or -1 if pos <= 0: self.long_y(y_qty=1) self.last_long_res = long_res # tell the tracker if pos == 0: self.tracker.open_position() else: self.tracker.close_with_exit(profit - fee) # short when test short_res > mean + bollinger*sd elif ( self.short_autoreg.test_sigma(short_res, self.bollinger) and short_res > self.short_autoreg.mean + avg_spread + fee / 2 ): # only short when position is 0 or 1 if pos >= 0: self.short_y(y_qty=1) self.last_short_res = short_res # tell the tracker if pos == 0: self.tracker.open_position() else: self.tracker.close_with_exit(profit - fee) # update rolling self.long_autoreg.add(long_res) self.short_autoreg.add(short_res) self.spreadx_roll.add(self.pair.get_spread_x()) self.spready_roll.add(self.pair.get_spread_y()) def on_daystart(self, date, info_x, info_y): # recreate rolling at each day start self.long_autoreg = AutoregOU(size=self.param["rolling"]) self.short_autoreg = AutoregOU(size=self.param["rolling"]) self.spreadx_roll = SimpleMoving(size=self.param["rolling"]) self.spready_roll = SimpleMoving(size=self.param["rolling"]) def on_dayend(self, date, info_x, info_y): pos = self.position_y() # stop short position if pos == -1: self.long_y(y_qty=1) return # stop long position if pos == 1: self.short_y(y_qty=1) return def _update_record(self, long_res, long_mean, long_std, short_res, short_mean, short_std): self.records["timestamp"].append(Clock.timestamp) self.records["longs"].append(long_res) self.records["shorts"].append(short_res) self.records["long_mean"].append(long_mean) self.records["short_mean"].append(short_mean) self.records["long_sd"].append(long_std) self.records["short_sd"].append(short_std)