class Fut_YuePortfolio(Portfolio): #---------------------------------------------------------------------- def __init__(self, engine, symbol_list, signal_param={}): self.name = 'yue' assert len(symbol_list) == 2 self.symbol_a = symbol_list[0] self.symbol_b = symbol_list[1] self.dual_name = self.symbol_a + '_' + self.symbol_b symbol_list.append(self.dual_name) self.got_dict = {} self.got_dict[self.symbol_a] = False self.got_dict[self.symbol_b] = False df = self.load_param() if df is not None: for i, row in df.iterrows(): if row.symbol_a in symbol_list and row.symbol_b in symbol_list: pass Portfolio.__init__(self, Fut_YueSignal, engine, symbol_list, signal_param) self.name_second = 'yue_' + self.dual_name # print(symbol_list, self.dual_name) #---------------------------------------------------------------------- def load_param(self): fn = get_dss() + 'fut/engine/yue/portfolio_yue_param.csv' df = None if os.path.exists(fn): df = pd.read_csv(fn) return df #---------------------------------------------------------------------- def onBar(self, bar, minx='min1'): """引擎新推送过来bar,传递给每个signal""" # 不处理不相关的品种 if bar.vtSymbol not in self.vtSymbolList: return if minx != 'min5': # 本策略为min5 return if self.result.date != bar.date + ' ' + bar.time: previousResult = self.result self.result = DailyResult(bar.date + ' ' + bar.time) self.resultList.append(self.result) if previousResult: self.result.updateClose(previousResult.closeDict) # 将bar推送给signal for signal in self.signalDict[bar.vtSymbol]: signal.onBar(bar, minx) # print(bar.vtSymbol, bar.time) """ 在此实现P层的业务控制逻辑 为每一个品种来检查是否触发下单条件 # 开始处理组合关心的bar , 尤其是品种对价差的加工和处理 """ if self.got_dict[self.symbol_a] == True and self.got_dict[ self.symbol_b] == True: for signal in self.signalDict[self.dual_name]: for s_a in self.signalDict[self.symbol_a]: ask_price_a = float(s_a.bar.AskPrice) # 挂卖价 bid_price_a = float(s_a.bar.BidPrice) # 挂买价 for s_b in self.signalDict[self.symbol_b]: ask_price_b = float(s_b.bar.AskPrice) # 挂卖价 bid_price_b = float(s_b.bar.BidPrice) # 挂买价 long_price = ask_price_a - bid_price_b short_price = bid_price_a - ask_price_b bar_dual = VtBarData() bar_dual.vtSymbol = self.dual_name bar_dual.high = short_price bar_dual.low = long_price bar_dual.date = bar.date bar_dual.time = bar.time bar_dual.datetime = bar.date + ' ' + bar.time # 将bar推送给signal signal.onBar(bar_dual, minx) self.result.updateBar(bar_dual) # print(bar_dual.vtSymbol, bar_dual.datetime ) self.got_dict[self.symbol_a] = False self.got_dict[self.symbol_b] = False self.result.updateBar(bar) self.result.updatePos(self.posDict) #---------------------------------------------------------------------- def _bc_dual_signal(self, direction, offset, volume): for signal in self.signalDict[self.symbol_a]: signal_a = signal for signal in self.signalDict[self.symbol_b]: signal_b = signal # 此处应使用挂买、挂卖价 if direction == DIRECTION_LONG and offset == OFFSET_OPEN: signal_a.buy(float(signal_a.bar.AskPrice), volume) signal_b.short(float(signal_b.bar.BidPrice), volume) if direction == DIRECTION_SHORT and offset == OFFSET_OPEN: signal_a.short(float(signal_a.bar.BidPrice), volume) signal_b.buy(float(signal_b.bar.AskPrice), volume) if direction == DIRECTION_LONG and offset == OFFSET_CLOSE: signal_a.cover(float(signal_a.bar.AskPrice), volume) signal_b.sell(float(signal_b.bar.BidPrice), volume) if direction == DIRECTION_SHORT and offset == OFFSET_CLOSE: signal_a.sell(float(signal_a.bar.BidPrice), volume) signal_b.cover(float(signal_b.bar.AskPrice), volume)
class Fut_Skew_StrdPortfolio(Portfolio): #---------------------------------------------------------------------- def __init__(self, engine, symbol_list, signal_param={}): self.name = 'skew_strd' self.tm = '00:00:00' self.got_dict = {} for symbol in symbol_list: self.got_dict[symbol] = False # self.d_base_dict = {} Portfolio.__init__(self, Fut_Skew_StrdSignal, engine, symbol_list, signal_param) #---------------------------------------------------------------------- def onBar(self, bar, minx='min1'): """引擎新推送过来bar,传递给每个signal""" # 不处理不相关的品种 if bar.vtSymbol not in self.vtSymbolList: return if minx != 'min1': # 本策略为min1 return if self.tm != bar.time: self.tm = bar.time for symbol in self.vtSymbolList: self.got_dict[symbol] = False if self.result.date != bar.date + ' ' + bar.time: previousResult = self.result self.result = DailyResult(bar.date + ' ' + bar.time) self.resultList.append(self.result) if previousResult: self.result.updateClose(previousResult.closeDict) # 将bar推送给signal for signal in self.signalDict[bar.vtSymbol]: signal.onBar(bar, minx) # print(bar.vtSymbol, bar.time) """ 在此实现P层的业务控制逻辑 为每一个品种来检查是否触发下单条件 # 开始处理组合关心的bar , 尤其是品种对价差的加工和处理 """ # print('here') self.control_in_p(bar) # print('here3') self.result.updateBar(bar) self.result.updatePos(self.posDict) #---------------------------------------------------------------------- def control_in_p(self, bar): if (bar.time > '09:31:00' and bar.time < '11:27:00' and bar.vtSymbol[:2] in ['IF','IO']) or \ (bar.time > '13:01:00' and bar.time < '14:57:00' and bar.vtSymbol[:2] in ['IF','IO']) or \ (bar.time > '21:01:00' and bar.time < '24:00:00' and bar.vtSymbol[:2] in ['al']) or \ (bar.time > '00:00:00' and bar.time < '01:00:00' and bar.vtSymbol[:2] in ['al']) or \ (bar.time > '09:01:00' and bar.time < '11:27:00' and bar.vtSymbol[:2] not in ['IF','IO']) or \ (bar.time > '13:31:00' and bar.time < '14:57:00' and bar.vtSymbol[:2] not in ['IF','IO']) or \ (bar.time > '21:01:00' and bar.time < '22:57:00' and bar.vtSymbol[:2] not in ['IF','IO']) : # 因第一根K线的价格为0 # cols = ['tm','basic_m0','basic_m1','strike_m0','strike_m1','fixed_size','profit','state','source','hold_m0','hold_m1','skew_low_open','skew_high_open','price_c_m0','price_p_m0','price_c_m1','price_p_m1','skew_max','dida_max','skew_min','dida_min','profit_m0','profit_m1','profit_o','date'] fn = get_dss( ) + 'fut/engine/skew_strd/portfolio_skew_strd_param.csv' cols_straddle = [ 'tm', 'basic_c', 'strike_c', 'basic_p', 'strike_p', 'num_c', 'num_p', 'direction', 'hold_c', 'hold_p', 'profit', 'state', 'source', 'price_c', 'price_p', 'profit_c', 'profit_p', 'profit_o', 'date' ] fn_straddle = get_dss( ) + 'fut/engine/straddle/portfolio_straddle_param.csv' df = pd.read_csv(fn) df_straddle = pd.read_csv(fn_straddle) symbol_got_list = [] for i, row in df.iterrows(): try: r = [] if row.state == 'stop': continue if row.basic_m0[:2] == 'IO': symbol_obj = 'IF' + row.basic_m0[2:] else: symbol_obj = row.basic_m0 exchangeID = str(get_contract(row.basic_m0).exchangeID) if exchangeID in ['CFFEX', 'DCE']: symbol_c_m0 = row.basic_m0 + '-C-' + str(row.strike_m0) symbol_p_m0 = row.basic_m0 + '-P-' + str(row.strike_m0) symbol_c_m1 = row.basic_m1 + '-C-' + str(row.strike_m1) symbol_p_m1 = row.basic_m1 + '-P-' + str(row.strike_m1) else: symbol_c_m0 = row.basic_m0 + 'C' + str(row.strike_m0) symbol_p_m0 = row.basic_m0 + 'P' + str(row.strike_m0) symbol_c_m1 = row.basic_m1 + 'C' + str(row.strike_m1) symbol_p_m1 = row.basic_m1 + 'P' + str(row.strike_m1) if symbol_obj not in self.got_dict or symbol_c_m0 not in self.got_dict or symbol_p_m0 not in self.got_dict or symbol_c_m1 not in self.got_dict or symbol_p_m1 not in self.got_dict: continue if self.got_dict[symbol_obj] == False or self.got_dict[ symbol_c_m0] == False or self.got_dict[ symbol_p_m0] == False or self.got_dict[ symbol_c_m1] == False or self.got_dict[ symbol_p_m1] == False: continue else: symbol_got_list.append(symbol_obj) symbol_got_list.append(symbol_c_m0) symbol_got_list.append(symbol_p_m0) symbol_got_list.append(symbol_c_m1) symbol_got_list.append(symbol_p_m1) s_obj = self.signalDict[symbol_obj][0] s_c_m0 = self.signalDict[symbol_c_m0][0] s_p_m0 = self.signalDict[symbol_p_m0][0] s_c_m1 = self.signalDict[symbol_c_m1][0] s_p_m1 = self.signalDict[symbol_p_m1][0] df.at[i, 'tm'] = bar.time # 开仓 if row.hold_m0 == 0 and row.hold_m1 == 0: iv_right_c = self.calc_iv(row.basic_m1, 'C', s_obj.bar.close, row.strike_m1, s_c_m1.bar.close) iv_right_p = self.calc_iv(row.basic_m1, 'P', s_obj.bar.close, row.strike_m1, s_p_m1.bar.close) iv_left_c = self.calc_iv(row.basic_m0, 'C', s_obj.bar.close, row.strike_m0, s_c_m0.bar.close) iv_left_p = self.calc_iv(row.basic_m0, 'P', s_obj.bar.close, row.strike_m0, s_p_m0.bar.close) skew = round( 100 * (iv_right_c + iv_right_p - iv_left_c - iv_left_p) / (iv_left_c + iv_left_p), 2) # print(skew) if skew > row.skew_max: df.at[i, 'skew_max'] = skew df.at[i, 'dida_max'] = 0 else: df.at[i, 'dida_max'] = row.dida_max + 1 # print(df.at[i, 'dida_max'], row.dida_max) if skew < row.skew_min: df.at[i, 'skew_min'] = skew df.at[i, 'dida_min'] = 0 else: df.at[i, 'dida_min'] = row.dida_min + 1 # 做空m0,做多m1 if df.at[ i, 'skew_min'] < row.skew_low_open and skew >= row.skew_low_open and df.at[ i, 'dida_min'] > 0: r.append([ '00:00:00', row.basic_m0, row.strike_m0, row.basic_m0, row.strike_m0, row.fixed_size, row.fixed_size, 'kong', 0, 0, 1000, 'run', 'skew_strd', '', '', '', '', '', bar.date ]) r.append([ '00:00:00', row.basic_m1, row.strike_m1, row.basic_m1, row.strike_m1, row.fixed_size, row.fixed_size, 'duo', 0, 0, 1000, 'run', 'skew_strd', '', '', '', '', '', bar.date ]) df.at[i, 'hold_m0'] = -1 df.at[i, 'hold_m1'] = 1 if self.engine.type == 'backtest': df.at[i, 'price_c_m0'] = s_c_m0.bar.close df.at[i, 'price_p_m0'] = s_p_m0.bar.close df.at[i, 'price_c_m1'] = s_c_m1.bar.close df.at[i, 'price_p_m1'] = s_p_m1.bar.close else: df.at[i, 'price_c_m0'] = s_c_m0.bar.BidPrice df.at[i, 'price_p_m0'] = s_p_m0.bar.BidPrice df.at[i, 'price_c_m1'] = s_c_m1.bar.AskPrice df.at[i, 'price_p_m1'] = s_p_m1.bar.AskPrice # 做多m0,做空m1 if df.at[ i, 'skew_max'] > row.skew_high_open and skew <= row.skew_high_open and df.at[ i, 'dida_max'] > 0: r.append([ '00:00:00', row.basic_m0, row.strike_m0, row.basic_m0, row.strike_m0, row.fixed_size, row.fixed_size, 'duo', 0, 0, 1000, 'run', 'skew_strd', '', '', '', '', '', bar.date ]) r.append([ '00:00:00', row.basic_m1, row.strike_m1, row.basic_m1, row.strike_m1, row.fixed_size, row.fixed_size, 'kong', 0, 0, 1000, 'run', 'skew_strd', '', '', '', '', '', bar.date ]) df.at[i, 'hold_m0'] = 1 df.at[i, 'hold_m1'] = -1 if self.engine.type == 'backtest': df.at[i, 'price_c_m0'] = s_c_m0.bar.close df.at[i, 'price_p_m0'] = s_p_m0.bar.close df.at[i, 'price_c_m1'] = s_c_m1.bar.close df.at[i, 'price_p_m1'] = s_p_m1.bar.close else: df.at[i, 'price_c_m0'] = s_c_m0.bar.AskPrice df.at[i, 'price_p_m0'] = s_p_m0.bar.AskPrice df.at[i, 'price_c_m1'] = s_c_m1.bar.BidPrice df.at[i, 'price_p_m1'] = s_p_m1.bar.BidPrice df2_straddle = pd.DataFrame(r, columns=cols_straddle) df_straddle = pd.concat( [df_straddle, df2_straddle], sort=False) # 获利平仓 elif row.hold_m0 == -1 and row.hold_m1 == 1: if self.engine.type == 'backtest': df.at[i, 'profit_m0'] = round( (row.price_c_m0 + row.price_p_m0) - (s_c_m0.bar.close + s_p_m0.bar.close), 2) df.at[i, 'profit_m1'] = round( (s_c_m1.bar.close + s_p_m1.bar.close) - (row.price_c_m1 + row.price_p_m1), 2) df.at[i, 'profit_o'] = round( df.at[i, 'profit_m0'] + df.at[i, 'profit_m1'], 2) else: df.at[i, 'profit_m0'] = round( (row.price_c_m0 + row.price_p_m0) - (s_c_m0.bar.AskPrice + s_p_m0.bar.AskPrice), 2) df.at[i, 'profit_m1'] = round( (s_c_m1.bar.BidPrice + s_p_m1.bar.BidPrice) - (row.price_c_m1 + row.price_p_m1), 2) df.at[i, 'profit_o'] = round( df.at[i, 'profit_m0'] + df.at[i, 'profit_m1'], 2) # print(df.at[i, 'profit_o']) if df.at[i, 'profit_o'] >= row.profit: df.at[i, 'hold_m0'] = 0 df.at[i, 'hold_m1'] = 0 df.at[i, 'state'] = 'stop' for j, jow in df_straddle.iterrows(): if jow.basic == row.basic_m0 and jow.strike == row.strike_m0 and jow.direction == 'kong' and jow.source == 'skew_strd': df_straddle.at[j, 'profit'] = -1000 if jow.basic == row.basic_m1 and jow.strike == row.strike_m1 and jow.direction == 'duo' and jow.source == 'skew_strd': df_straddle.at[j, 'profit'] = -1000 # 获利平仓 elif row.hold_m0 == 1 and row.hold_m1 == -1: if self.engine.type == 'backtest': df.at[i, 'profit_m0'] = round( (s_c_m0.bar.close + s_p_m0.bar.close) - (row.price_c_m0 + row.price_p_m0), 2) df.at[i, 'profit_m1'] = round( (row.price_c_m1 + row.price_p_m1) - (s_c_m1.bar.close + s_p_m1.bar.close), 2) df.at[i, 'profit_o'] = round( df.at[i, 'profit_m0'] + df.at[i, 'profit_m1'], 2) else: df.at[i, 'profit_m0'] = round( (s_c_m0.bar.BidPrice + s_p_m0.bar.BidPrice) - (row.price_c_m0 + row.price_p_m0), 2) df.at[i, 'profit_m1'] = round( (row.price_c_m1 + row.price_p_m1) - (s_c_m1.bar.AskPrice + s_p_m1.bar.AskPrice), 2) df.at[i, 'profit_o'] = round( df.at[i, 'profit_m0'] + df.at[i, 'profit_m1'], 2) # print(df.at[i, 'profit_o']) if df.at[i, 'profit_o'] >= row.profit: df.at[i, 'hold_m0'] = 0 df.at[i, 'hold_m1'] = 0 df.at[i, 'state'] = 'stop' for j, jow in df_straddle.iterrows(): if jow.basic == row.basic_m0 and jow.strike == row.strike_m0 and jow.direction == 'duo' and jow.source == 'skew_strd': df_straddle.at[j, 'profit'] = -1000 if jow.basic == row.basic_m1 and jow.strike == row.strike_m1 and jow.direction == 'kong' and jow.source == 'skew_strd': df_straddle.at[j, 'profit'] = -1000 except Exception as e: s = traceback.format_exc() to_log(s) df_straddle.to_csv(fn_straddle, index=False) df.to_csv(fn, index=False) for symbol in symbol_got_list: self.got_dict[symbol] = False #---------------------------------------------------------------------- def calc_iv(self, basic, flag, S0, K, C0): r = 0.03 fn = get_dss() + 'fut/cfg/opt_mature.csv' df2 = pd.read_csv(fn) df2 = df2[df2.pz == df2.pz] # 筛选出不为空的记录 df2 = df2.set_index('symbol') mature_dict = dict(df2.mature) date_mature = mature_dict[basic] date_mature = datetime.strptime(date_mature, '%Y-%m-%d') td = datetime.now() T = float((date_mature - td).days) / 365 # 剩余期限 skew = 0 if flag == 'C': skew = bsm_call_imp_vol(S0, K, T, r, C0) if flag == 'P': skew = bsm_put_imp_vol(S0, K, T, r, C0) return skew #---------------------------------------------------------------------- def daily_open(self): Portfolio.daily_open(self) #---------------------------------------------------------------------- def daily_close(self): Portfolio.daily_close(self)
class Fut_FollowPortfolio(Portfolio): #---------------------------------------------------------------------- def __init__(self, engine, symbol_list, signal_param={}): self.name = 'follow' self.symbol_o = '' self.symbol_c = '' self.symbol_p = '' for symbol in symbol_list: if symbol[:2] == 'IF': self.symbol_o = symbol break self.got_dict = {} self.strike_high = 0 self.strike_low = 0 self.price_o = 0 self.price_o_high = 0 self.price_o_low = 0 self.price_c = 0 self.price_p = 0 self.hold_o = 0 self.hold_c = 0 self.hold_p = 0 self.profit_o = 0 self.profit_c = 0 self.profit_p = 0 self.switch_state = 'off' fn = get_dss() + 'fut/engine/follow/follow_switch.csv' if os.path.exists(fn): df = pd.read_csv(fn) if len(df) > 0: rec = df.iloc[-1, :] if rec.state == 'on': self.switch_state = 'on' Portfolio.__init__(self, Fut_FollowSignal, engine, symbol_list, signal_param) #---------------------------------------------------------------------- def rec_profit(self, dt, tm, price_o, price_c, price_p, note): r = [[ dt, tm, price_o, price_c, self.hold_c, self.price_c, self.profit_c, price_p, self.hold_p, self.price_p, self.profit_p, note, 60, self.profit_c + self.profit_p ]] df = pd.DataFrame(r, columns=[ 'date', 'time', 'price_o', 'price_c', 'hold_c', 'cost_c', 'profit_c', 'price_p', 'hold_p', 'cost_p', 'profit_p', 'note', 'commission', 'profit' ]) pz = str(get_contract(self.symbol_c).pz) fn = get_dss() + 'fut/engine/follow/portfolio_profit_' + pz + '.csv' if os.path.exists(fn): df.to_csv(fn, index=False, mode='a', header=False) else: df.to_csv(fn, index=False) #---------------------------------------------------------------------- def get_open_signal(self): return True #---------------------------------------------------------------------- def onBar(self, bar, minx='min1'): """引擎新推送过来bar,传递给每个signal""" # 不处理不相关的品种 if bar.vtSymbol not in self.vtSymbolList: return if minx != 'min1': # 本策略为min1 return if self.result.date != bar.date + ' ' + bar.time: previousResult = self.result self.result = DailyResult(bar.date + ' ' + bar.time) self.resultList.append(self.result) if previousResult: self.result.updateClose(previousResult.closeDict) # 将bar推送给signal for signal in self.signalDict[bar.vtSymbol]: signal.onBar(bar, minx) # print(bar.vtSymbol, bar.time) """ 在此实现P层的业务控制逻辑 为每一个品种来检查是否触发下单条件 # 开始处理组合关心的bar , 尤其是品种对价差的加工和处理 """ if bar.time > '09:35:00': # 因第一根K线的价格为0 if self.switch_state == 'on' and self.get_open_signal() == True: s_o = self.signalDict[self.symbol_o][0] self.price_o = s_o.bar.close self.price_o_high = 1.04 * self.price_o self.price_o_low = 0.96 * self.price_o strike_mid = int(round(self.price_o / 100, 0) * 100) self.strike_high = strike_mid + 300 self.strike_low = strike_mid - 300 self.symbol_c = 'IO' + self.symbol_o[2:6] + '-C-' + str( self.strike_high) self.symbol_p = 'IO' + self.symbol_o[2:6] + '-P-' + str( self.strike_low) s_c = self.signalDict[self.symbol_c][0] s_p = self.signalDict[self.symbol_p][0] if self.engine.type == 'backtest': s_c.short(s_c.bar.close, 1) s_p.short(s_p.bar.close, 1) else: s_c.short(s_c.bar.BidPrice, 1) # 挂买价 s_p.short(s_p.bar.BidPrice, 1) # 挂买价 self.got_dict[self.symbol_o] = False self.got_dict[self.symbol_c] = False self.got_dict[self.symbol_p] = False if self.engine.type == 'backtest': self.price_c = s_c.bar.close self.price_p = s_p.bar.close else: self.price_c = s_c.bar.BidPrice self.price_p = s_p.bar.BidPrice self.hold_c = -1 self.hold_p = -1 self.profit_o = self.price_c + self.price_p # 止盈止损点 self.switch_state = 'off' # 不再开仓 df2 = pd.DataFrame([{'state': 'off'}]) fn = get_dss() + 'fut/engine/follow/follow_switch.csv' df2.to_csv(fn, index=False) # 回写文件 self.rec_profit(bar.date, bar.time, s_o.bar.close, s_c.bar.close, s_p.bar.close, '开仓') if self.hold_c == -1 and self.hold_p == -1: if self.got_dict[self.symbol_o] == True and self.got_dict[ self.symbol_c] == True and self.got_dict[ self.symbol_p] == True: self.got_dict[self.symbol_o] = False self.got_dict[self.symbol_c] = False self.got_dict[self.symbol_p] = False s_o = self.signalDict[self.symbol_o][0] s_c = self.signalDict[self.symbol_c][0] s_p = self.signalDict[self.symbol_p][0] # 盈亏离场 或 无剩余价值离场 if self.profit_c + self.profit_p > 0.5 * self.profit_o or self.profit_c + self.profit_p < -0.3 * self.profit_o or abs( self.hold_c * s_c.bar.close + self.hold_p * s_p.bar.close) <= 3: if self.engine.type == 'backtest': s_c.cover(s_c.bar.close, 1) s_p.cover(s_p.bar.close, 1) else: s_c.cover(s_c.bar.AskPrice, 1) # 挂卖价 s_p.cover(s_p.bar.AskPrice, 1) # 挂卖价 self.hold_c = 0 self.hold_p = 0 self.rec_profit(bar.date, bar.time, s_o.bar.close, s_c.bar.close, s_p.bar.close, '清仓') # 已持仓 elif self.hold_c == -1 or self.hold_p == -1: # 上涨2% 或 离行权价小于50点时 if s_o.bar.close > self.price_o_high or self.strike_high - s_o.bar.close < 50: if self.engine.type == 'backtest': s_c.cover(s_c.bar.close, 1) s_p.cover(s_p.bar.close, 1) else: s_c.cover(s_c.bar.AskPrice, 1) # 挂卖价 s_p.cover(s_p.bar.AskPrice, 1) # 挂卖价 if self.engine.type == 'backtest': self.price_c = self.price_c - s_c.bar.close self.price_p = self.price_p - s_p.bar.close else: self.price_c = self.price_c - s_c.bar.AskPrice self.price_p = self.price_p - s_p.bar.AskPrice self.hold_c = 0 self.hold_p = 0 self.rec_profit(bar.date, bar.time, s_o.bar.close, s_c.bar.close, s_p.bar.close, '移仓') self.price_o = s_o.bar.close self.price_o_high = 1.04 * self.price_o self.price_o_low = 0.96 * self.price_o self.strike_high += 100 self.strike_low += 100 self.symbol_c = 'IO' + self.symbol_o[ 2:6] + '-C-' + str(self.strike_high) self.symbol_p = 'IO' + self.symbol_o[ 2:6] + '-P-' + str(self.strike_low) s_c = self.signalDict[self.symbol_c][0] s_p = self.signalDict[self.symbol_p][0] if self.engine.type == 'backtest': s_c.short(s_c.bar.close, 1) s_p.short(s_p.bar.close, 1) else: s_c.short(s_c.bar.BidPrice, 1) # 挂买价 s_p.short(s_p.bar.BidPrice, 1) # 挂买价 self.got_dict[self.symbol_o] = False self.got_dict[self.symbol_c] = False self.got_dict[self.symbol_p] = False if self.engine.type == 'backtest': self.price_c += s_c.bar.close self.price_p += s_p.bar.close else: self.price_c += s_c.bar.BidPrice self.price_p += s_p.bar.BidPrice self.hold_c = -1 self.hold_p = -1 self.rec_profit(bar.date, bar.time, s_o.bar.close, s_c.bar.close, s_p.bar.close, '移仓') # 下跌2% 或 离行权价小于50点时 if s_o.bar.close < self.price_o_low or s_o.bar.close - self.strike_low < 50: if self.engine.type == 'backtest': s_c.cover(s_c.bar.close, 1) s_p.cover(s_p.bar.close, 1) else: s_c.cover(s_c.bar.AskPrice, 1) # 挂卖价 s_p.cover(s_p.bar.AskPrice, 1) # 挂卖价 if self.engine.type == 'backtest': self.price_c = self.price_c - s_c.bar.close self.price_p = self.price_p - s_p.bar.close else: self.price_c = self.price_c - s_c.bar.AskPrice self.price_p = self.price_p - s_p.bar.AskPrice self.hold_c = 0 self.hold_p = 0 self.rec_profit(bar.date, bar.time, s_o.bar.close, s_c.bar.close, s_p.bar.close, '移仓') self.price_o = s_o.bar.close self.price_o_high = 1.04 * self.price_o self.price_o_low = 0.96 * self.price_o self.strike_high -= 100 self.strike_low -= 100 self.symbol_c = 'IO' + self.symbol_o[ 2:6] + '-C-' + str(self.strike_high) self.symbol_p = 'IO' + self.symbol_o[ 2:6] + '-P-' + str(self.strike_low) s_c = self.signalDict[self.symbol_c][0] s_p = self.signalDict[self.symbol_p][0] if self.engine.type == 'backtest': s_c.short(s_c.bar.close, 1) s_p.short(s_p.bar.close, 1) else: s_c.short(s_c.bar.BidPrice, 1) # 挂买价 s_p.short(s_p.bar.BidPrice, 1) # 挂买价 self.got_dict[self.symbol_o] = False self.got_dict[self.symbol_c] = False self.got_dict[self.symbol_p] = False if self.engine.type == 'backtest': self.price_c += s_c.bar.close self.price_p += s_p.bar.close else: self.price_c += s_c.bar.BidPrice self.price_p += s_p.bar.BidPrice self.hold_c = -1 self.hold_p = -1 self.rec_profit(bar.date, bar.time, s_o.bar.close, s_c.bar.close, s_p.bar.close, '移仓') self.result.updateBar(bar) self.result.updatePos(self.posDict) #---------------------------------------------------------------------- def daily_open(self): Portfolio.daily_open(self) fn = get_dss() + 'fut/engine/follow/portfolio_follow_param.csv' if os.path.exists(fn): df = pd.read_csv(fn) if len(df) > 0: rec = df.iloc[-1, :] # 取最近日期的记录 self.symbol_c = rec.symbol_c self.symbol_p = rec.symbol_p self.strike_high = rec.strike_high self.strike_low = rec.strike_low self.profit_o = rec.profit_o self.price_o = rec.price_o self.price_o_high = 1.04 * self.price_o self.price_o_low = 0.96 * self.price_o self.price_c = rec.price_c self.price_p = rec.price_p self.hold_c = rec.hold_c self.hold_p = rec.hold_p #---------------------------------------------------------------------- def daily_close(self): Portfolio.daily_close(self) r = [ [self.result.date, self.symbol_c, self.symbol_p, self.strike_high, self.strike_low, \ self.profit_o, self.price_o, self.price_c, self.price_p, self.hold_c, self.hold_p] ] df = pd.DataFrame(r, columns=[ 'datetime', 'symbol_c', 'symbol_p', 'strike_high', 'strike_low', 'profit_o', 'price_o', 'price_c', 'price_p', 'hold_c', 'hold_p' ]) fn = get_dss() + 'fut/engine/follow/portfolio_follow_param.csv' if os.path.exists(fn): df.to_csv(fn, index=False, mode='a', header=False) else: df.to_csv(fn, index=False)
class Fut_FollowPortfolio(Portfolio): #---------------------------------------------------------------------- def __init__(self, engine, symbol_list, signal_param={}): self.name = 'follow' assert len(symbol_list) == 3 self.symbol_o = symbol_list[0] self.symbol_c = symbol_list[1] self.symbol_p = symbol_list[2] if self.symbol_o[:2] == 'IF': self.symbol_future = 'IO' + self.symbol_o[2:] else: self.symbol_future = self.symbol_o self.dual_name = self.symbol_future self.got_dict = {} self.got_dict[self.symbol_o] = False self.got_dict[self.symbol_c] = False self.got_dict[self.symbol_p] = False self.price_o = 0 self.price_o_high = 0 self.price_o_low = 0 self.price_c = 0 self.price_p = 0 self.hold_o = 0 self.hold_c = 0 self.hold_p = 0 self.profit_o = 0 self.profit_c = 0 self.profit_p = 0 self.flag_c, self.flag_p, self.strike_high, self.strike_low, self.fixed_size, self.switch_state, self.percent, self.gap = self.load_param(self.symbol_c, self.symbol_p) Portfolio.__init__(self, Fut_FollowSignal, engine, symbol_list, signal_param) self.name_second = 'follow_' + self.dual_name #---------------------------------------------------------------------- def load_param(self, s_c, s_p): fn = get_dss() + 'fut/engine/follow/portfolio_follow_param.csv' df = pd.read_csv(fn) df = df[(df.symbol_c == s_c) & (df.symbol_p == s_p)] row = df.iloc[-1,:] return row.flag_c, row.flag_p, int(row.strike_high), int(row.strike_low), int(row.fixed_size), row.switch_state, float(row.percent), int(row.gap) #---------------------------------------------------------------------- def set_param(self, rec): fn = get_dss() + 'fut/engine/follow/portfolio_follow_param.csv' df = pd.read_csv(fn) df = df[(df.symbol_c != rec[1]) & (df.symbol_p != rec[2])] df.to_csv(fn, index=False) df = pd.DataFrame([rec], columns=['symbol_o','symbol_c','symbol_p','flag_c','flag_p','strike_high','strike_low','fixed_size','switch_state','percent','gap']) df.to_csv(fn, index=False, mode='a', header=False) #---------------------------------------------------------------------- def rec_profit(self, dt, tm, price_o, price_c, price_p, note): r = [[dt, tm, price_o, price_c, self.hold_c, self.price_c, self.profit_c, price_p, self.hold_p, self.price_p, self.profit_p, note, 60, self.profit_c + self.profit_p]] df = pd.DataFrame(r, columns=['date','time','price_o','price_c','hold_c','cost_c','profit_c','price_p','hold_p','cost_p','profit_p','note','commission','profit']) pz = str(get_contract(self.symbol_c).pz) fn = get_dss() + 'fut/engine/follow/portfolio_' + self.name_second + '_profit.csv' if os.path.exists(fn): df.to_csv(fn, index=False, mode='a', header=False) else: df.to_csv(fn, index=False) #---------------------------------------------------------------------- def onBar(self, bar, minx='min1'): """引擎新推送过来bar,传递给每个signal""" # 不处理不相关的品种 if bar.vtSymbol not in self.vtSymbolList: return if minx != 'min1': # 本策略为min1 return if self.result.date != bar.date + ' ' + bar.time: previousResult = self.result self.result = DailyResult(bar.date + ' ' + bar.time) self.resultList.append(self.result) if previousResult: self.result.updateClose(previousResult.closeDict) # 将bar推送给signal for signal in self.signalDict[bar.vtSymbol]: signal.onBar(bar, minx) # print(bar.vtSymbol, bar.time) """ 在此实现P层的业务控制逻辑 为每一个品种来检查是否触发下单条件 # 开始处理组合关心的bar , 尤其是品种对价差的加工和处理 """ if (bar.time > '09:35:00' and bar.time < '11:25:00' and bar.vtSymbol[:2] in ['IF','IO']) or \ (bar.time > '13:05:00' and bar.time < '14:55:00' and bar.vtSymbol[:2] in ['IF','IO']) or \ (bar.time > '09:05:00' and bar.time < '11:25:00' and bar.vtSymbol[:2] not in ['IF','IO']) or \ (bar.time > '13:35:00' and bar.time < '14:55:00' and bar.vtSymbol[:2] not in ['IF','IO']) or \ (bar.time > '21:05:00' and bar.time < '22:55:00' and bar.vtSymbol[:2] not in ['IF','IO']) : # 因第一根K线的价格为0 # 开仓 if self.switch_state == 'on' and self.hold_c == 0 and self.hold_p == 0: if self.got_dict[self.symbol_o] == True and self.got_dict[self.symbol_c] == True and self.got_dict[self.symbol_p] == True: self.got_dict[self.symbol_o] = False self.got_dict[self.symbol_c] = False self.got_dict[self.symbol_p] = False s_o = self.signalDict[self.symbol_o][0] s_c = self.signalDict[self.symbol_c][0] s_p = self.signalDict[self.symbol_p][0] self.price_o = s_o.bar.close self.price_o_high = (1+self.percent) * self.price_o self.price_o_low = (1-self.percent) * self.price_o if self.engine.type == 'backtest': s_c.short(s_c.bar.close, self.fixed_size) s_p.short(s_p.bar.close, self.fixed_size) else: s_c.short(s_c.bar.BidPrice, self.fixed_size) # 挂买价 s_p.short(s_p.bar.BidPrice, self.fixed_size) # 挂买价 if self.engine.type == 'backtest': self.price_c = s_c.bar.close self.price_p = s_p.bar.close else: self.price_c = s_c.bar.BidPrice self.price_p = s_p.bar.BidPrice self.hold_c = -1 self.hold_p = -1 self.profit_o = self.price_c + self.price_p # 止盈止损点 self.switch_state = 'off' # 不再开仓 self.set_param([self.symbol_o,self.symbol_c,self.symbol_p,self.flag_c,self.flag_p,self.strike_high,self.strike_low,self.fixed_size,self.switch_state,self.percent,self.gap]) self.rec_profit(bar.date, bar.time, s_o.bar.close, s_c.bar.close, s_p.bar.close, '开仓') if self.hold_c == -1 and self.hold_p == -1 : if self.got_dict[self.symbol_o] == True and self.got_dict[self.symbol_c] == True and self.got_dict[self.symbol_p] == True: s_o = self.signalDict[self.symbol_o][0] s_c = self.signalDict[self.symbol_c][0] s_p = self.signalDict[self.symbol_p][0] # 盈亏离场 或 无剩余价值离场 if self.profit_c + self.profit_p > 0.5*self.profit_o or self.profit_c + self.profit_p < -0.3*self.profit_o or abs(s_c.bar.close + s_p.bar.close) <= 3: if self.engine.type == 'backtest': s_c.cover(s_c.bar.close, self.fixed_size) s_p.cover(s_p.bar.close, self.fixed_size) else: s_c.cover(s_c.bar.AskPrice, self.fixed_size) # 挂卖价 s_p.cover(s_p.bar.AskPrice, self.fixed_size) # 挂卖价 self.hold_c = 0 self.hold_p = 0 self.rec_profit(bar.date, bar.time, s_o.bar.close, s_c.bar.close, s_p.bar.close, '清仓') # 已持仓 elif self.hold_c == -1 or self.hold_p == -1: # 上涨4% 或 离行权价小于50点时 if s_o.bar.close > self.price_o_high or self.strike_high - s_o.bar.close < self.gap: if self.engine.type == 'backtest': s_c.cover(s_c.bar.close, self.fixed_size) s_p.cover(s_p.bar.close, self.fixed_size) else: s_c.cover(s_c.bar.AskPrice, self.fixed_size) # 挂卖价 s_p.cover(s_p.bar.AskPrice, self.fixed_size) # 挂卖价 if self.engine.type == 'backtest': self.price_c = self.price_c - s_c.bar.close self.price_p = self.price_p - s_p.bar.close else: self.price_c = self.price_c - s_c.bar.AskPrice self.price_p = self.price_p - s_p.bar.AskPrice self.hold_c = 0 self.hold_p = 0 self.rec_profit(bar.date, bar.time, s_o.bar.close, s_c.bar.close, s_p.bar.close, '移仓') self.price_o = s_o.bar.close self.price_o_high = (1+self.percent) * self.price_o self.price_o_low = (1-self.percent) * self.price_o self.strike_high += 2*self.gap self.strike_low += 2*self.gap self.symbol_c = self.symbol_future + self.flag_c + str(self.strike_high) self.symbol_p = self.symbol_future + self.flag_p + str(self.strike_low) self.set_param([self.symbol_o,self.symbol_c,self.symbol_p,self.flag_c,self.flag_p,self.strike_high,self.strike_low,self.fixed_size,self.switch_state,self.percent,self.gap]) self.switch_state = 'on' self.vtSymbolList = [self.symbol_o,self.symbol_c,self.symbol_p] for s in [self.symbol_c,self.symbol_p]: self.posDict[s] = 0 signal1 = Fut_FollowSignal(self, s) l = self.signalDict[s] l.append(signal1) # 下跌4% 或 离行权价小于50点时 elif s_o.bar.close < self.price_o_low or s_o.bar.close - self.strike_low < self.gap: if self.engine.type == 'backtest': s_c.cover(s_c.bar.close, self.fixed_size) s_p.cover(s_p.bar.close, self.fixed_size) else: s_c.cover(s_c.bar.AskPrice, self.fixed_size) # 挂卖价 s_p.cover(s_p.bar.AskPrice, self.fixed_size) # 挂卖价 if self.engine.type == 'backtest': self.price_c = self.price_c - s_c.bar.close self.price_p = self.price_p - s_p.bar.close else: self.price_c = self.price_c - s_c.bar.AskPrice self.price_p = self.price_p - s_p.bar.AskPrice self.hold_c = 0 self.hold_p = 0 self.rec_profit(bar.date, bar.time, s_o.bar.close, s_c.bar.close, s_p.bar.close, '移仓') self.price_o = s_o.bar.close self.price_o_high = (1+self.percent) * self.price_o self.price_o_low = (1-self.percent) * self.price_o self.strike_high -= 2*self.gap self.strike_low -= 2*self.gap self.symbol_c = self.symbol_future + self.flag_c + str(self.strike_high) self.symbol_p = self.symbol_future + self.flag_p + str(self.strike_low) self.set_param([self.symbol_o,self.symbol_c,self.symbol_p,self.flag_c,self.flag_p,self.strike_high,self.strike_low,self.fixed_size,self.switch_state,self.percent,self.gap]) self.switch_state = 'on' self.vtSymbolList = [self.symbol_o,self.symbol_c,self.symbol_p] for s in [self.symbol_c, self.symbol_p]: self.posDict[s] = 0 signal1 = Fut_FollowSignal(self, s) l = self.signalDict[s] l.append(signal1) self.got_dict[self.symbol_o] = False self.got_dict[self.symbol_c] = False self.got_dict[self.symbol_p] = False self.result.updateBar(bar) self.result.updatePos(self.posDict) #---------------------------------------------------------------------- def daily_open(self): Portfolio.daily_open(self) fn = get_dss() + 'fut/engine/follow/portfolio_' + self.name_second + '_save.csv' if os.path.exists(fn): df = pd.read_csv(fn) if len(df) > 0: rec = df.iloc[-1,:] # 取最近日期的记录 self.profit_o = rec.profit_o self.price_o = rec.price_o self.price_o_high = (1+self.percent) * self.price_o self.price_o_low = (1-self.percent) * self.price_o self.price_c = rec.price_c self.price_p = rec.price_p self.hold_c = rec.hold_c self.hold_p = rec.hold_p #---------------------------------------------------------------------- def daily_close(self): Portfolio.daily_close(self) r = [ [self.result.date, self.profit_o, self.price_o, self.price_c, self.price_p, self.hold_c, self.hold_p] ] df = pd.DataFrame(r, columns=['datetime', 'profit_o','price_o', 'price_c', 'price_p', 'hold_c', 'hold_p']) fn = get_dss() + 'fut/engine/follow/portfolio_' + self.name_second + '_save.csv' if os.path.exists(fn): df.to_csv(fn, index=False, mode='a', header=False) else: df.to_csv(fn, index=False)
class Fut_Skew_BiliPortfolio(Portfolio): #---------------------------------------------------------------------- def __init__(self, engine, symbol_list, signal_param={}): self.name = 'skew_bili' self.tm = '00:00:00' self.got_dict = {} for symbol in symbol_list: self.got_dict[symbol] = False # self.d_base_dict = {} Portfolio.__init__(self, Fut_Skew_BiliSignal, engine, symbol_list, signal_param) #---------------------------------------------------------------------- def onBar(self, bar, minx='min1'): """引擎新推送过来bar,传递给每个signal""" # 不处理不相关的品种 if bar.vtSymbol not in self.vtSymbolList: return if minx != 'min1': # 本策略为min1 return if self.tm != bar.time: self.tm = bar.time for symbol in self.vtSymbolList: self.got_dict[symbol] = False if self.result.date != bar.date + ' ' + bar.time: previousResult = self.result self.result = DailyResult(bar.date + ' ' + bar.time) self.resultList.append(self.result) if previousResult: self.result.updateClose(previousResult.closeDict) # 将bar推送给signal for signal in self.signalDict[bar.vtSymbol]: signal.onBar(bar, minx) # print(bar.vtSymbol, bar.time) """ 在此实现P层的业务控制逻辑 为每一个品种来检查是否触发下单条件 # 开始处理组合关心的bar , 尤其是品种对价差的加工和处理 """ # print('here') self.control_in_p(bar) # print('here3') self.result.updateBar(bar) self.result.updatePos(self.posDict) #---------------------------------------------------------------------- def control_in_p(self, bar): if (bar.time > '09:31:00' and bar.time < '11:27:00' and bar.vtSymbol[:2] in ['IF','IO']) or \ (bar.time > '13:01:00' and bar.time < '14:57:00' and bar.vtSymbol[:2] in ['IF','IO']) or \ (bar.time > '21:01:00' and bar.time < '24:00:00' and bar.vtSymbol[:2] in ['al']) or \ (bar.time > '00:00:00' and bar.time < '01:00:00' and bar.vtSymbol[:2] in ['al']) or \ (bar.time > '09:01:00' and bar.time < '11:27:00' and bar.vtSymbol[:2] not in ['IF','IO']) or \ (bar.time > '13:31:00' and bar.time < '14:57:00' and bar.vtSymbol[:2] not in ['IF','IO']) or \ (bar.time > '21:01:00' and bar.time < '22:57:00' and bar.vtSymbol[:2] not in ['IF','IO']) : # 因第一根K线的价格为0 fn = get_dss( ) + 'fut/engine/skew_bili/portfolio_skew_bili_param.csv' cols_ratio = [ 'tm', 'symbol_b', 'symbol_s', 'num_b', 'num_s', 'gap', 'profit', 'hold_b', 'hold_s', 'state', 'source', 'price_b', 'price_s', 'gap_open', 'profit_b', 'profit_s', 'profit_o', 'date', 'delta', 'theta' ] fn_ratio = get_dss() + 'fut/engine/ratio/portfolio_ratio_param.csv' df = pd.read_csv(fn) df_ratio = pd.read_csv(fn_ratio) symbol_got_list = [] for i, row in df.iterrows(): try: r = [] if row.state == 'stop': continue basic_b = get_contract(row.symbol_b).basic basic_s = get_contract(row.symbol_s).basic if basic_b[:2] == 'IO': symbol_obj = 'IF' + basic_b[2:] else: symbol_obj = basic_b if symbol_obj not in self.got_dict or row.symbol_b not in self.got_dict or row.symbol_s not in self.got_dict: continue if self.got_dict[symbol_obj] == False or self.got_dict[ row.symbol_b] == False or self.got_dict[ row.symbol_s] == False: continue else: symbol_got_list.append(symbol_obj) symbol_got_list.append(row.symbol_b) symbol_got_list.append(row.symbol_s) s_obj = self.signalDict[symbol_obj][0] s_b = self.signalDict[row.symbol_b][0] s_s = self.signalDict[row.symbol_s][0] df.at[i, 'tm'] = bar.time # 开仓 if row.hold_b == 0 and row.hold_s == 0: opt_flag = get_contract(row.symbol_b).opt_flag strike_b = get_contract(row.symbol_b).strike strike_s = get_contract(row.symbol_s).strike if opt_flag == 'C': iv_b = self.calc_iv(basic_b, 'C', s_obj.bar.close, strike_b, s_b.bar.close) iv_s = self.calc_iv(basic_s, 'C', s_obj.bar.close, strike_s, s_s.bar.close) else: iv_b = self.calc_iv(basic_b, 'P', s_obj.bar.close, strike_b, s_b.bar.close) iv_s = self.calc_iv(basic_s, 'P', s_obj.bar.close, strike_s, s_s.bar.close) skew = round(100 * (iv_s / iv_b - 1), 2) print(skew) if skew > row.skew_max: df.at[i, 'skew_max'] = skew df.at[i, 'dida_max'] = 0 else: df.at[i, 'dida_max'] = row.dida_max + 1 # print(df.at[i, 'dida_max'], row.dida_max) if skew < row.skew_min: df.at[i, 'skew_min'] = skew df.at[i, 'dida_min'] = 0 else: df.at[i, 'dida_min'] = row.dida_min + 1 # 做多symbol_s,做空symbol_b if df.at[ i, 'skew_min'] < row.skew_low_open and skew >= row.skew_low_open and df.at[ i, 'dida_min'] > 0: r.append([ '00:00:00', row.symbol_s, row.symbol_b, row.num_s, row.num_b, -1000, row.profit, 0, 0, 'run', 'skew_bili', 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, bar.date, 0.0, 0.0 ]) df.at[i, 'hold_b'] = -row.num_b df.at[i, 'hold_s'] = row.num_s if self.engine.type == 'backtest': df.at[i, 'price_b'] = s_b.bar.close df.at[i, 'price_s'] = s_s.bar.close else: df.at[i, 'price_b'] = s_b.bar.BidPrice df.at[i, 'price_s'] = s_s.bar.AskPrice # 做多symbol_b,做空symbol_s if df.at[ i, 'skew_max'] > row.skew_high_open and skew <= row.skew_high_open and df.at[ i, 'dida_max'] > 0: r.append([ '00:00:00', row.symbol_b, row.symbol_s, row.num_b, row.num_s, -1000, row.profit, 0, 0, 'run', 'skew_bili', 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, bar.date, 0.0, 0.0 ]) df.at[i, 'hold_b'] = row.num_b df.at[i, 'hold_s'] = -row.num_s if self.engine.type == 'backtest': df.at[i, 'price_b'] = s_b.bar.close df.at[i, 'price_s'] = s_s.bar.close else: df.at[i, 'price_b'] = s_b.bar.AskPrice df.at[i, 'price_s'] = s_s.bar.BidPrice df2_ratio = pd.DataFrame(r, columns=cols_ratio) df_ratio = pd.concat([df_ratio, df2_ratio], sort=False) # 获利平仓 elif row.hold_b <= -1 and row.hold_s >= 1: if self.engine.type == 'backtest': df.at[i, 'profit_b'] = round( (s_b.bar.close - row.price_b) * row.hold_b, 2) df.at[i, 'profit_s'] = round( (s_s.bar.close - row.price_s) * row.hold_s, 2) df.at[i, 'profit_o'] = round( df.at[i, 'profit_b'] + df.at[i, 'profit_s'], 2) else: df.at[i, 'profit_b'] = round( (s_b.bar.AskPrice - row.price_b) * row.hold_b, 2) df.at[i, 'profit_s'] = round( (s_s.bar.BidPrice - row.price_s) * row.hold_s, 2) df.at[i, 'profit_o'] = round( df.at[i, 'profit_b'] + df.at[i, 'profit_s'], 2) # print(df.at[i, 'profit_o']) if df.at[i, 'profit_o'] >= row.profit: df.at[i, 'hold_m0'] = 0 df.at[i, 'hold_m1'] = 0 df.at[i, 'state'] = 'stop' for j, jow in df_ratio.iterrows(): if jow.symbol_b == row.symbol_s and jow.symbol_s == row.symbol_b and jow.num_b == row.num_s and jow.num_s == row.num_b and jow.source == 'skew_bili': df_ratio.at[j, 'profit'] = -1000 # 获利平仓 elif row.hold_b >= 1 and row.hold_s <= -1: if self.engine.type == 'backtest': df.at[i, 'profit_b'] = round( (s_b.bar.close - row.price_b) * row.hold_b, 2) df.at[i, 'profit_s'] = round( (s_s.bar.close - row.price_s) * row.hold_s, 2) df.at[i, 'profit_o'] = round( df.at[i, 'profit_b'] + df.at[i, 'profit_s'], 2) else: df.at[i, 'profit_b'] = round( (s_b.bar.BidPrice - row.price_b) * row.hold_b, 2) df.at[i, 'profit_s'] = round( (s_s.bar.AskPrice - row.price_s) * row.hold_s, 2) df.at[i, 'profit_o'] = round( df.at[i, 'profit_b'] + df.at[i, 'profit_s'], 2) # print(df.at[i, 'profit_o']) if df.at[i, 'profit_o'] >= row.profit: df.at[i, 'hold_b'] = 0 df.at[i, 'hold_s'] = 0 df.at[i, 'state'] = 'stop' for j, jow in df_ratio.iterrows(): if jow.symbol_b == row.symbol_b and jow.symbol_s == row.symbol_s and jow.num_b == row.num_b and jow.num_s == row.num_s and jow.source == 'skew_bili': df_ratio.at[j, 'profit'] = -1000 except Exception as e: s = traceback.format_exc() to_log(s) df_ratio.to_csv(fn_ratio, index=False) df.to_csv(fn, index=False) for symbol in symbol_got_list: self.got_dict[symbol] = False #---------------------------------------------------------------------- def calc_iv(self, basic, flag, S0, K, C0): r = 0.03 fn = get_dss() + 'fut/cfg/opt_mature.csv' df2 = pd.read_csv(fn) df2 = df2[df2.pz == df2.pz] # 筛选出不为空的记录 df2 = df2.set_index('symbol') mature_dict = dict(df2.mature) date_mature = mature_dict[basic] date_mature = datetime.strptime(date_mature, '%Y-%m-%d') td = datetime.now() T = float((date_mature - td).days) / 365 # 剩余期限 skew = 0 if flag == 'C': skew = bsm_call_imp_vol(S0, K, T, r, C0) if flag == 'P': skew = bsm_put_imp_vol(S0, K, T, r, C0) return skew #---------------------------------------------------------------------- def daily_open(self): Portfolio.daily_open(self) #---------------------------------------------------------------------- def daily_close(self): Portfolio.daily_close(self)
class Fut_SwapPortfolio(Portfolio): #---------------------------------------------------------------------- def __init__(self, engine, symbol_list, signal_param={}): self.name = 'swap' self.symbol_o = '' self.symbol_a = '' for symbol in symbol_list: if len(symbol) == 6: self.symbol_o = symbol break assert self.symbol_o != '' self.got_dict = {} self.price_o = 0 self.price_a = 0 self.hold_o = 0 self.hold_a = 0 self.profit_o = 0 self.profit_a = 0 self.can_duo = False self.can_kong = False self.switch_state = 'on' pz = str(get_contract(self.symbol_c).pz) fn = get_dss() + 'fut/engine/swap/swap_switch_' + pz + '.csv' if os.path.exists(fn): df = pd.read_csv(fn) if len(df) > 0: rec = df.iloc[-1, :] if rec.state == 'off': self.switch_state = 'off' Portfolio.__init__(self, Fut_SwapSignal, engine, symbol_list, signal_param) #---------------------------------------------------------------------- def rec_profit(self, dt, tm, price_o, price_c, price_p, note): r = [[ dt, tm, price_o, price_c, self.hold_c, self.price_c, self.profit_c, price_p, self.hold_p, self.price_p, self.profit_p, note, 60, self.profit_c + self.profit_p ]] df = pd.DataFrame(r, columns=[ 'date', 'time', 'price_o', 'price_c', 'hold_c', 'cost_c', 'profit_c', 'price_p', 'hold_p', 'cost_p', 'profit_p', 'note', 'commission', 'profit' ]) pz = str(get_contract(self.symbol_c).pz) fn = get_dss() + 'fut/engine/swap/portfolio_profit_' + pz + '.csv' if os.path.exists(fn): df.to_csv(fn, index=False, mode='a', header=False) else: df.to_csv(fn, index=False) #---------------------------------------------------------------------- def got_all_bar(self): for symbol in self.vtSymbolList: if symbol not in self.got_dict: return False if self.got_dict[symbol] == False: return False for symbol in self.vtSymbolList: self.got_dict[symbol] = False return True #---------------------------------------------------------------------- def onBar(self, bar, minx='min1'): """引擎新推送过来bar,传递给每个signal""" # 策略未启用 if self.switch_state == 'off': return # 不处理不相关的品种 if bar.vtSymbol not in self.vtSymbolList: return if minx != 'min30': # 本策略为min30 return if self.result.date != bar.date + ' ' + bar.time: previousResult = self.result self.result = DailyResult(bar.date + ' ' + bar.time) self.resultList.append(self.result) if previousResult: self.result.updateClose(previousResult.closeDict) # 将bar推送给signal for signal in self.signalDict[bar.vtSymbol]: signal.onBar(bar, minx) """ 在此实现P层的业务控制逻辑 为每一个品种来检查是否触发下单条件 # 开始处理组合关心的bar , 尤其是品种对价差的加工和处理 """ if bar.time > '09:35:00' and self.got_all_bar() == True: s_o = self.signalDict[self.symbol_o][0] # 做多 if self.can_duo == True: if self.hold_a == -1: s_a = self.signalDict[self.symbol_a][0] s_a.cover(s_a.bar.close, 1) # s_a.cover(s_a.bar.AskPrice, 1) # 挂卖价 self.hold_a = 0 self.rec_profit(bar.date, bar.time, s_o.bar.close, s_c.bar.close, s_p.bar.close, '平仓') strike = int(round((self.price_o - 150) / 100, 0) * 100) self.symbol_a = 'IO' + self.symbol_o[2:6] + '-P-' + str(strike) s_a = self.signalDict[self.symbol_a][0] s_a.short(s_a.bar.close, 1) # s_a.short(s_a.bar.BidPrice, 1) # 挂买价 self.price_o = s_o.bar.close self.price_a = s_a.bar.close # self.price_a = s_a.bar.BidPrice self.hold_a = -1 self.rec_profit(bar.date, bar.time, s_o.bar.close, s_c.bar.close, s_p.bar.close, '做多开仓') self.can_duo = False # 做空 elif self.can_kong == True: if self.hold_a == -1: s_a = self.signalDict[self.symbol_a][0] s_a.cover(s_a.bar.close, 1) # s_a.cover(s_a.bar.AskPrice, 1) # 挂卖价 self.hold_a = 0 self.rec_profit(bar.date, bar.time, s_o.bar.close, s_c.bar.close, s_p.bar.close, '平仓') strike = int(round((self.price_o + 150) / 100, 0) * 100) self.symbol_a = 'IO' + self.symbol_o[2:6] + '-C-' + str(strike) s_a = self.signalDict[self.symbol_a][0] s_a.short(s_a.bar.close, 1) # s_a.short(s_a.bar.BidPrice, 1) # 挂买价 self.price_o = s_o.bar.close self.price_a = s_a.bar.close # self.price_a = s_a.bar.BidPrice self.hold_a = -1 self.rec_profit(bar.date, bar.time, s_o.bar.close, s_c.bar.close, s_p.bar.close, '做空开仓') self.can_kong = False self.result.updateBar(bar) self.result.updatePos(self.posDict)
class Fut_AvengerPortfolio(Portfolio): #---------------------------------------------------------------------- def __init__(self, engine, symbol_list, signal_param={}): self.name = 'avenger' assert len(symbol_list) == 3 self.symbol_o = symbol_list[0] self.symbol_c = symbol_list[1] self.symbol_p = symbol_list[2] self.got_dict = {} self.got_dict[self.symbol_o] = False self.got_dict[self.symbol_c] = False self.got_dict[self.symbol_p] = False self.price_o = 0 self.price_o_high = 0 self.price_o_low = 0 self.price_c = 0 self.price_p = 0 self.hold_o = 0 self.hold_c = 0 self.hold_p = 0 self.profit_o = 0 self.profit_c = 0 self.profit_p = 0 self.switch_state = 'off' pz = str(get_contract(self.symbol_c).pz) fn = get_dss() + 'fut/engine/avenger/avenger_switch_' + pz + '.csv' if os.path.exists(fn): df = pd.read_csv(fn) if len(df) > 0: rec = df.iloc[-1, :] if rec.state == 'on': self.switch_state = 'on' rec.state = 'off' df2 = pd.DataFrame([rec]) df2.to_csv(fn, index=False) # 回写文件 Portfolio.__init__(self, Fut_AvengerSignal, engine, symbol_list, signal_param) #---------------------------------------------------------------------- def rec_profit(self, dt, tm, price_o, price_c, price_p, note): r = [[ dt, tm, price_o, price_c, self.hold_c, self.price_c, self.profit_c, price_p, self.hold_p, self.price_p, self.profit_p, note, 60, self.profit_c + self.profit_p ]] df = pd.DataFrame(r, columns=[ 'date', 'time', 'price_o', 'price_c', 'hold_c', 'cost_c', 'profit_c', 'price_p', 'hold_p', 'cost_p', 'profit_p', 'note', 'commission', 'profit' ]) pz = str(get_contract(self.symbol_c).pz) fn = get_dss() + 'fut/engine/avenger/portfolio_profit_' + pz + '.csv' if os.path.exists(fn): df.to_csv(fn, index=False, mode='a', header=False) else: df.to_csv(fn, index=False) #---------------------------------------------------------------------- def onBar(self, bar, minx='min1'): """引擎新推送过来bar,传递给每个signal""" # 不处理不相关的品种 if bar.vtSymbol not in self.vtSymbolList: return if minx != 'min1': # 本策略为min1 return if self.result.date != bar.date + ' ' + bar.time: previousResult = self.result self.result = DailyResult(bar.date + ' ' + bar.time) self.resultList.append(self.result) if previousResult: self.result.updateClose(previousResult.closeDict) # 将bar推送给signal for signal in self.signalDict[bar.vtSymbol]: signal.onBar(bar, minx) # print(bar.vtSymbol, bar.time) """ 在此实现P层的业务控制逻辑 为每一个品种来检查是否触发下单条件 # 开始处理组合关心的bar , 尤其是品种对价差的加工和处理 """ if bar.time > '09:35:00' and self.got_dict[ self.symbol_o] == True and self.got_dict[ self.symbol_c] == True and self.got_dict[ self.symbol_p] == True: s_o = self.signalDict[self.symbol_o][0] s_c = self.signalDict[self.symbol_c][0] s_p = self.signalDict[self.symbol_p][0] # 开仓 if self.switch_state == 'on': s_c.short(s_c.bar.BidPrice, 1) # 挂买价 s_p.short(s_p.bar.BidPrice, 1) # 挂买价 self.price_o = s_o.bar.close self.price_o_high = 1.01 * self.price_o self.price_o_low = 0.99 * self.price_o self.price_c = s_c.bar.BidPrice self.price_p = s_p.bar.BidPrice self.hold_c = -1 self.hold_p = -1 self.profit_o = self.price_c + self.price_p # 止盈止损点 self.switch_state = 'off' # 不再开仓 self.rec_profit(bar.date, bar.time, s_o.bar.close, s_c.bar.close, s_p.bar.close, '开仓') # 已持仓 elif self.hold_c != 0 or self.hold_p != 0: # 盈亏离场 或 无剩余价值离场 if abs(self.profit_c + self.profit_p) > 0.5 * self.profit_o or abs( self.hold_c * s_c.bar.close + self.hold_p * s_p.bar.close) <= 3: if self.hold_c == -1 and self.hold_p == -1: s_c.cover(s_c.bar.AskPrice, 1) # 挂卖价 s_p.cover(s_p.bar.AskPrice, 1) # 挂卖价 self.hold_c = 0 self.hold_p = 0 if self.hold_c == 0 and self.hold_p == -2: s_p.cover(s_p.bar.AskPrice, 2) # 挂卖价 self.hold_p = 0 if self.hold_c == -2 and self.hold_p == 0: s_c.cover(s_c.bar.AskPrice, 2) # 挂卖价 self.hold_c = 0 self.rec_profit(bar.date, bar.time, s_o.bar.close, s_c.bar.close, s_p.bar.close, '清仓') # 复仇 if self.hold_c == -1 and self.hold_p == -1: # 上涨1% if s_o.bar.close > self.price_o_high: s_c.cover(s_c.bar.AskPrice, 1) # 挂卖价 s_p.short(s_p.bar.BidPrice, 1) # 挂买价 self.price_c = self.price_c - s_c.bar.AskPrice self.price_p = (s_p.bar.BidPrice + self.price_p) / 2 self.hold_c = 0 self.hold_p = -2 self.rec_profit(bar.date, bar.time, s_o.bar.close, s_c.bar.close, s_p.bar.close, '上涨复仇') # 下跌1% if s_o.bar.close < self.price_o_low: s_p.cover(s_p.bar.AskPrice, 1) # 挂卖价 s_c.short(s_c.bar.BidPrice, 1) # 挂买价 self.price_p = self.price_p - s_p.bar.AskPrice self.price_c = (s_c.bar.BidPrice + self.price_c) / 2 self.hold_p = 0 self.hold_c = -2 self.rec_profit(bar.date, bar.time, s_o.bar.close, s_c.bar.close, s_p.bar.close, '下跌复仇') # 复仇失败,上涨后又回原点 if self.hold_c == 0 and self.hold_p == -2 and s_o.bar.close < self.price_o: s_c.short(s_c.bar.BidPrice, 1) # 挂买价 s_p.cover(s_p.bar.AskPrice, 1) # 挂卖价 self.price_c = s_c.bar.BidPrice + self.price_c self.price_p = 2 * self.price_p - s_p.bar.AskPrice self.hold_p = -1 self.hold_c = -1 self.profit_c = self.hold_c * (s_c.bar.close - self.price_c) self.rec_profit(bar.date, bar.time, s_o.bar.close, s_c.bar.close, s_p.bar.close, '复仇失败') # 复仇失败,下跌后又回原点 if self.hold_c == -2 and self.hold_p == 0 and s_o.bar.close > self.price_o: s_p.short(s_p.bar.BidPrice, 1) # 挂买价 s_c.cover(s_c.bar.AskPrice, 1) # 挂卖价 self.price_p = s_p.bar.BidPrice + self.price_p self.price_c = 2 * self.price_c - s_c.bar.AskPrice self.hold_p = -1 self.hold_c = -1 self.profit_p = self.hold_p * (s_p.bar.close - self.price_p) self.rec_profit(bar.date, bar.time, s_o.bar.close, s_c.bar.close, s_p.bar.close, '复仇失败') self.got_dict[self.symbol_o] = False self.got_dict[self.symbol_c] = False self.got_dict[self.symbol_p] = False self.result.updateBar(bar) self.result.updatePos(self.posDict)
class Fut_SdifferPortfolio(Portfolio): #---------------------------------------------------------------------- def __init__(self, engine, symbol_list, signal_param={}): self.name = 'sdiffer' self.tm = '00:00:00' self.got_dict = {} for symbol in symbol_list: self.got_dict[symbol] = False self.be_run = 'stop' self.d_low_open = -100.0 self.d_high_open = 100.0 self.d_low_mail = -100.0 self.d_high_mail = 100.0 self.mailed_low = False self.mailed_high = False self.load_switch() self.stop = False self.basic_m0 = None self.basic_m1 = None self.cacl_vars() self.symbol_obj = None self.d_base_dict = {} Portfolio.__init__(self, Fut_SdifferSignal, engine, symbol_list, signal_param) #---------------------------------------------------------------------- def load_switch(self): pass fn = get_dss() + 'fut/engine/sdiffer/portfolio_sdiffer_switch.csv' if os.path.exists(fn): df = pd.read_csv(fn) rec = df.iloc[0] self.be_run = rec.be_run self.d_low_open = rec.d_low_open self.d_high_open = rec.d_high_open self.d_low_mail = rec.d_low_mail self.d_high_mail = rec.d_high_mail # print(self.be_run, self.d_low_open, self.d_high_open) #---------------------------------------------------------------------- def cacl_vars(self): now = datetime.now() next_day = now + timedelta(days=10) next_day = next_day.strftime('%Y-%m-%d') fn = get_dss() + 'fut/cfg/opt_mature.csv' df_opt = pd.read_csv(fn) df = df_opt[(df_opt.pz == 'IO') & (df_opt.flag == 'm0')] self.basic_m0 = df.iat[0, 1] mature = df.iat[0, 2] df = df_opt[(df_opt.pz == 'IO') & (df_opt.flag == 'm1')] self.basic_m1 = df.iat[0, 1] if next_day >= mature: self.stop = True # fn = get_dss() + 'opt/straddle_differ.csv' # df = pd.read_csv(fn) # df = df[(df.basic_m0 == self.basic_m0) & (df.basic_m1 == self.basic_m1) & (df.stat == 'y')] # if len(df) >= 480: # df = df.iloc[-480:, :] # self.per_10 = df.differ.quantile(0.01) # self.per_50 = df.differ.quantile(0.5) # self.per_90 = df.differ.quantile(0.99) # else: # self.per_10 = -100 # self.per_50 = 0 # self.per_90 = 100 #---------------------------------------------------------------------- def onBar(self, bar, minx='min1'): """引擎新推送过来bar,传递给每个signal""" # 不处理不相关的品种 if bar.vtSymbol not in self.vtSymbolList: return if minx != 'min1': # 本策略为min1 return if self.tm != bar.time: self.tm = bar.time for symbol in self.vtSymbolList: self.got_dict[symbol] = False if self.result.date != bar.date + ' ' + bar.time: previousResult = self.result self.result = DailyResult(bar.date + ' ' + bar.time) self.resultList.append(self.result) if previousResult: self.result.updateClose(previousResult.closeDict) # 将bar推送给signal for signal in self.signalDict[bar.vtSymbol]: signal.onBar(bar, minx) # print(bar.vtSymbol, bar.time) """ 在此实现P层的业务控制逻辑 为每一个品种来检查是否触发下单条件 # 开始处理组合关心的bar , 尤其是品种对价差的加工和处理 """ # print('here') self.control_in_p(bar) # print('here3') self.result.updateBar(bar) self.result.updatePos(self.posDict) #---------------------------------------------------------------------- def control_in_p(self, bar): if (bar.time > '09:31:00' and bar.time < '11:27:00' and bar.vtSymbol[:2] in ['IF','IO']) or \ (bar.time > '13:01:00' and bar.time < '14:57:00' and bar.vtSymbol[:2] in ['IF','IO']) or \ (bar.time > '21:01:00' and bar.time < '24:00:00' and bar.vtSymbol[:2] in ['al']) or \ (bar.time > '00:00:00' and bar.time < '01:00:00' and bar.vtSymbol[:2] in ['al']) or \ (bar.time > '09:01:00' and bar.time < '11:27:00' and bar.vtSymbol[:2] not in ['IF','IO']) or \ (bar.time > '13:31:00' and bar.time < '14:57:00' and bar.vtSymbol[:2] not in ['IF','IO']) or \ (bar.time > '21:01:00' and bar.time < '22:57:00' and bar.vtSymbol[:2] not in ['IF','IO']) : # 因第一根K线的价格为0 cols = [ 'date', 'basic_m0', 'basic_m1', 'strike', 'fixed_size', 'hold_m0', 'hold_m1', 'price_c_m0', 'price_p_m0', 'price_c_m1', 'price_p_m1', 'd_low_open', 'd_high_open', 'd_max', 'dida_max', 'd_min', 'dida_min', 'profit', 'state', 'source', 'profit_m0', 'profit_m1', 'profit_o' ] fn = get_dss() + 'fut/engine/sdiffer/portfolio_sdiffer_param.csv' # while get_file_lock(fn) == False: # time.sleep(0.01) cols_straddle = [ 'tm', 'basic_c', 'strike_c', 'basic_p', 'strike_p', 'num_c', 'num_p', 'direction', 'hold_c', 'hold_p', 'profit', 'state', 'source', 'price_c', 'price_p', 'profit_c', 'profit_p', 'profit_o', 'date' ] fn_straddle = get_dss( ) + 'fut/engine/straddle/portfolio_straddle_param.csv' # while get_file_lock(fn_straddle) == False: # time.sleep(0.01) df = pd.read_csv(fn) df_straddle = pd.read_csv(fn_straddle) symbol_got_list = [] # 先确定当日要交易的合约,生成当日交易记录 if self.symbol_obj is None: try: temp1 = 'IF' + self.basic_m0[2:] # print(temp1) if self.got_dict[temp1]: self.symbol_obj = temp1 # 临近到期日,暂停自动交易,否则,发出条件单 if self.stop == False: s_obj = self.signalDict[self.symbol_obj][0] obj = s_obj.bar.close gap = 50 atm = int( round( round(obj * (100 / gap) / 1E4, 2) * 1E4 / (100 / gap), 0)) # 获得平值 r = [[bar.date, self.basic_m0, self.basic_m1, atm, 1, \ 0, 0, '','','','', \ self.d_low_open, self.d_high_open, 0.0,0,0.0,0, \ 13,self.be_run,'sdiffer','','',''] ] df2 = pd.DataFrame(r, columns=cols) df = pd.concat([df, df2], sort=False) # print(df) except Exception as e: s = traceback.format_exc() to_log(s) else: for i, row in df.iterrows(): try: r = [] if row.state == 'stop': continue symbol_c_m0 = row.basic_m0 + '-C-' + str(row.strike) symbol_p_m0 = row.basic_m0 + '-P-' + str(row.strike) symbol_c_m1 = row.basic_m1 + '-C-' + str(row.strike) symbol_p_m1 = row.basic_m1 + '-P-' + str(row.strike) if symbol_c_m0 not in self.got_dict or symbol_p_m0 not in self.got_dict or symbol_c_m1 not in self.got_dict or symbol_p_m1 not in self.got_dict: continue if self.got_dict[symbol_c_m0] == False or self.got_dict[ symbol_p_m0] == False or self.got_dict[ symbol_c_m1] == False or self.got_dict[ symbol_p_m1] == False: continue else: symbol_got_list.append(symbol_c_m0) symbol_got_list.append(symbol_p_m0) symbol_got_list.append(symbol_c_m1) symbol_got_list.append(symbol_p_m1) s_c_m0 = self.signalDict[symbol_c_m0][0] s_p_m0 = self.signalDict[symbol_p_m0][0] s_c_m1 = self.signalDict[symbol_c_m1][0] s_p_m1 = self.signalDict[symbol_p_m1][0] d_base_m0 = self.d_base_dict[row.basic_m0 + '_' + str(row.strike)] d_base_m1 = self.d_base_dict[row.basic_m1 + '_' + str(row.strike)] # 开仓 if row.hold_m0 == 0 and row.hold_m1 == 0: diff_m0 = 0.5 * ( s_c_m0.bar.AskPrice + s_c_m0.bar.BidPrice ) + 0.5 * (s_p_m0.bar.AskPrice + s_p_m0.bar.BidPrice) - d_base_m0 diff_m1 = 0.5 * ( s_c_m1.bar.AskPrice + s_c_m1.bar.BidPrice ) + 0.5 * (s_p_m1.bar.AskPrice + s_p_m1.bar.BidPrice) - d_base_m1 differ = diff_m1 - diff_m0 print('differ: ', differ) if differ <= self.d_low_mail and self.mailed_low == False: self.mailed_low = True send_email(get_dss(), 'differ: ' + str(differ), '') if differ >= self.d_high_mail and self.mailed_high == False: self.mailed_high = True send_email(get_dss(), 'differ: ' + str(differ), '') if differ >= row.d_max: df.at[i, 'd_max'] = differ df.at[i, 'dida_max'] = 0 else: df.at[i, 'dida_max'] = row.dida_max + 1 # print(df.at[i, 'dida_max'], row.dida_max) if differ <= row.d_min: df.at[i, 'd_min'] = differ df.at[i, 'dida_min'] = 0 else: df.at[i, 'dida_min'] = row.dida_min + 1 # print(df.at[i, 'dida_min'], row.dida_min) # 做多 # if differ < 9: if df.at[ i, 'd_min'] <= row.d_low_open and differ >= row.d_low_open and df.at[ i, 'dida_min'] > 0: r.append([ '00:00:00', row.basic_m0, row.strike, row.basic_m0, row.strike, 1, 1, 'kong', 0, 0, 1000, 'run', 'sdiffer', '', '', '', '', '', bar.date ]) r.append([ '00:00:00', row.basic_m1, row.strike, row.basic_m1, row.strike, 1, 1, 'duo', 0, 0, 1000, 'run', 'sdiffer', '', '', '', '', '', bar.date ]) df.at[i, 'hold_m0'] = -1 df.at[i, 'hold_m1'] = 1 df.at[i, 'price_c_m0'] = s_c_m0.bar.BidPrice df.at[i, 'price_p_m0'] = s_p_m0.bar.BidPrice df.at[i, 'price_c_m1'] = s_c_m1.bar.AskPrice df.at[i, 'price_p_m1'] = s_p_m1.bar.AskPrice # 做空 # if differ > 9: if df.at[ i, 'd_max'] >= row.d_high_open and differ <= row.d_high_open and df.at[ i, 'dida_max'] > 0: r.append([ '00:00:00', row.basic_m1, row.strike, row.basic_m1, row.strike, 1, 1, 'kong', 0, 0, 1000, 'run', 'sdiffer', '', '', '', '', '', bar.date ]) r.append([ '00:00:00', row.basic_m0, row.strike, row.basic_m0, row.strike, 1, 1, 'duo', 0, 0, 1000, 'run', 'sdiffer', '', '', '', '', '', bar.date ]) df.at[i, 'hold_m0'] = 1 df.at[i, 'hold_m1'] = -1 df.at[i, 'price_c_m0'] = s_c_m0.bar.AskPrice df.at[i, 'price_p_m0'] = s_p_m0.bar.AskPrice df.at[i, 'price_c_m1'] = s_c_m1.bar.BidPrice df.at[i, 'price_p_m1'] = s_p_m1.bar.BidPrice df2_straddle = pd.DataFrame( r, columns=cols_straddle) df_straddle = pd.concat( [df_straddle, df2_straddle], sort=False) # 多单获利平仓 elif row.hold_m0 == -1 and row.hold_m1 == 1: df.at[i, 'profit_m0'] = round( (row.price_c_m0 + row.price_p_m0) - (s_c_m0.bar.AskPrice + s_p_m0.bar.AskPrice), 2) df.at[i, 'profit_m1'] = round( (s_c_m1.bar.BidPrice + s_p_m1.bar.BidPrice) - (row.price_c_m1 + row.price_p_m1), 2) df.at[i, 'profit_o'] = round( df.at[i, 'profit_m0'] + df.at[i, 'profit_m1'], 2) if df.at[i, 'profit_o'] >= row.profit: df.at[i, 'hold_m0'] = 0 df.at[i, 'hold_m1'] = 0 df.at[i, 'state'] = 'stop' for j, jow in df_straddle.iterrows(): if jow.basic == row.basic_m0 and jow.strike == row.strike and jow.direction == 'kong' and jow.source == 'sdiffer': df_straddle.at[j, 'profit'] = -1000 if jow.basic == row.basic_m1 and jow.strike == row.strike and jow.direction == 'duo' and jow.source == 'sdiffer': df_straddle.at[j, 'profit'] = -1000 # 空单获利平仓 elif row.hold_m0 == 1 and row.hold_m1 == -1: df.at[i, 'profit_m0'] = round( (s_c_m0.bar.BidPrice + s_p_m0.bar.BidPrice) - (row.price_c_m0 + row.price_p_m0), 2) df.at[i, 'profit_m1'] = round( (row.price_c_m1 + row.price_p_m1) - (s_c_m1.bar.AskPrice + s_p_m1.bar.AskPrice), 2) df.at[i, 'profit_o'] = round( df.at[i, 'profit_m0'] + df.at[i, 'profit_m1'], 2) if df.at[i, 'profit_o'] >= row.profit: df.at[i, 'hold_m0'] = 0 df.at[i, 'hold_m1'] = 0 df.at[i, 'state'] = 'stop' for j, jow in df_straddle.iterrows(): if jow.basic == row.basic_m0 and jow.strike == row.strike and jow.direction == 'duo' and jow.source == 'sdiffer': df_straddle.at[j, 'profit'] = -1000 if jow.basic == row.basic_m1 and jow.strike == row.strike and jow.direction == 'kong' and jow.source == 'sdiffer': df_straddle.at[j, 'profit'] = -1000 except Exception as e: s = traceback.format_exc() to_log(s) df_straddle.to_csv(fn_straddle, index=False) # release_file_lock(fn_straddle) df.to_csv(fn, index=False) # release_file_lock(fn) for symbol in symbol_got_list: self.got_dict[symbol] = False #---------------------------------------------------------------------- def daily_open(self): Portfolio.daily_open(self) fn = get_dss() + 'opt/sdiffer_d_base.csv' df = pd.read_csv(fn) date_list = sorted(list(set(df.date))) # print(date_list) date = date_list[-1] df = df[df.date == date] for i, row in df.iterrows(): self.d_base_dict[row.basic + '_' + str(row.strike)] = row.d_base #---------------------------------------------------------------------- def daily_close(self): Portfolio.daily_close(self) fn = get_dss() + 'fut/engine/sdiffer/portfolio_sdiffer_param.csv' df = pd.read_csv(fn) for i, row in df.iterrows(): if row.date == self.result.date[: 10] and row.source == 'sdiffer' and row.hold_m0 == 0: df.at[i, 'state'] = 'stop' df = df[(df.state == 'run') | (df.date == self.result.date[:10])] df.to_csv(fn, index=False)
class Fut_IcPortfolio(Portfolio): #---------------------------------------------------------------------- def __init__(self, engine, symbol_list, signal_param={}): self.name = 'ic' assert len(symbol_list) == 2 self.symbol_g = symbol_list[0] self.symbol_d = symbol_list[1] self.dual_name = self.symbol_g + '_' + self.symbol_d symbol_list.append(self.dual_name) self.direction_g = 'direction_g' self.num_g = 0 self.direction_d = 'direction_d' self.num_d = 0 self.got_dict = {} self.got_dict[self.symbol_g] = False self.got_dict[self.symbol_d] = False df = self.load_param() if df is not None: for i, row in df.iterrows(): if row.symbol_g in symbol_list and row.symbol_d in symbol_list: self.direction_g = row.symbol_g self.num_g = row.direction_g self.direction_d = row.num_g self.num_d = row.num_d Portfolio.__init__(self, Fut_IcSignal, engine, symbol_list, signal_param) self.name_second = 'ic_' + self.dual_name # print(symbol_list, self.dual_name) #---------------------------------------------------------------------- def load_param(self): fn = get_dss() + 'fut/engine/ic/portfolio_ic_param.csv' df = None if os.path.exists(fn): df = pd.read_csv(fn) return df #---------------------------------------------------------------------- def onBar(self, bar, minx='min1'): """引擎新推送过来bar,传递给每个signal""" # 不处理不相关的品种 if bar.vtSymbol not in self.vtSymbolList: return if minx != 'min15': # 本策略为min15 return if self.result.date != bar.date + ' ' + bar.time: previousResult = self.result self.result = DailyResult(bar.date + ' ' + bar.time) self.resultList.append(self.result) if previousResult: self.result.updateClose(previousResult.closeDict) # 将bar推送给signal for signal in self.signalDict[bar.vtSymbol]: signal.onBar(bar, minx) # print(bar.vtSymbol, bar.time) """ 在此实现P层的业务控制逻辑 为每一个品种来检查是否触发下单条件 # 开始处理组合关心的bar , 尤其是品种对价差的加工和处理 """ if self.got_dict[self.symbol_g] == True and self.got_dict[self.symbol_d] == True: for signal in self.signalDict[self.dual_name]: for s_g in self.signalDict[self.symbol_g]: price_g = s_g.bar.close for s_d in self.signalDict[self.symbol_d]: price_d = s_d.bar.close price_gap = price_g - price_d bar_dual = VtBarData() bar_dual.vtSymbol = self.dual_name bar_dual.open = price_gap bar_dual.high = price_gap bar_dual.low = price_gap bar_dual.close = price_gap bar_dual.date = bar.date bar_dual.time = bar.time bar_dual.datetime = bar.date + ' ' + bar.time # 将bar推送给signal signal.onBar(bar_dual, minx) self.result.updateBar(bar_dual) # print(bar_dual.vtSymbol, bar_dual.datetime ) self.got_dict[self.symbol_g] = False self.got_dict[self.symbol_d] = False self.result.updateBar(bar) self.result.updatePos(self.posDict) #---------------------------------------------------------------------- def _bc_dual_signal(self, direction, offset, volume_g, volume_d): for signal in self.signalDict[self.symbol_g]: signal_g = signal for signal in self.signalDict[self.symbol_d]: signal_d = signal if direction == DIRECTION_LONG and offset == OFFSET_OPEN: signal_g.buy(signal_g.bar.close, volume_g) signal_d.short(signal_d.bar.close, volume_d) if direction == DIRECTION_SHORT and offset == OFFSET_OPEN: signal_g.short(signal_g.bar.close, volume_g) signal_d.buy(signal_d.bar.close, volume_d) if direction == DIRECTION_LONG and offset == OFFSET_CLOSE: signal_g.cover(signal_g.bar.close, volume_g) signal_d.sell(signal_d.bar.close, volume_d) if direction == DIRECTION_SHORT and offset == OFFSET_CLOSE: signal_g.sell(signal_g.bar.close, volume_g) signal_d.cover(signal_d.bar.close, volume_d)
class Fut_RatioPortfolio(Portfolio): #---------------------------------------------------------------------- def __init__(self, engine, symbol_list, signal_param={}): self.name = 'ratio' self.tm = '00:00:00' self.got_dict = {} for symbol in symbol_list: self.got_dict[symbol] = False Portfolio.__init__(self, Fut_RatioSignal, engine, symbol_list, signal_param) # self.promote = True #---------------------------------------------------------------------- def onBar(self, bar, minx='min1'): """引擎新推送过来bar,传递给每个signal""" # 不处理不相关的品种 if bar.vtSymbol not in self.vtSymbolList: return if minx != 'min1': # 本策略为min1 return # 动态加载新维护的symbol config = open(get_dss() + 'fut/cfg/config.json') setting = json.load(config) symbols = setting['symbols_ratio'] symbols_list = symbols.split(',') for vtSymbol in symbols_list: if vtSymbol not in self.vtSymbolList: self.vtSymbolList.append(vtSymbol) self.posDict[vtSymbol] = 0 self.got_dict[vtSymbol] = False signal1 = Fut_RatioSignal(self, vtSymbol) l = self.signalDict[vtSymbol] l.append(signal1) if self.tm != bar.time: self.tm = bar.time for symbol in self.vtSymbolList: self.got_dict[symbol] = False if self.result.date != bar.date + ' ' + bar.time: previousResult = self.result self.result = DailyResult(bar.date + ' ' + bar.time) self.resultList.append(self.result) if previousResult: self.result.updateClose(previousResult.closeDict) # 将bar推送给signal for signal in self.signalDict[bar.vtSymbol]: signal.onBar(bar, minx) # print(bar.vtSymbol, bar.time) """ 在此实现P层的业务控制逻辑 为每一个品种来检查是否触发下单条件 # 开始处理组合关心的bar , 尤其是品种对价差的加工和处理 """ self.control_in_p(bar) self.result.updateBar(bar) self.result.updatePos(self.posDict) #---------------------------------------------------------------------- def control_in_p(self, bar): if (bar.time > '09:31:00' and bar.time < '11:27:00' and bar.vtSymbol[:2] in ['IF','IO']) or \ (bar.time > '13:01:00' and bar.time < '14:57:00' and bar.vtSymbol[:2] in ['IF','IO']) or \ (bar.time > '21:01:00' and bar.time < '24:00:00' and bar.vtSymbol[:2] in ['al']) or \ (bar.time > '00:00:00' and bar.time < '01:00:00' and bar.vtSymbol[:2] in ['al']) or \ (bar.time > '09:01:00' and bar.time < '11:27:00' and bar.vtSymbol[:2] not in ['IF','IO']) or \ (bar.time > '13:31:00' and bar.time < '14:57:00' and bar.vtSymbol[:2] not in ['IF','IO']) or \ (bar.time > '21:01:00' and bar.time < '22:57:00' and bar.vtSymbol[:2] not in ['IF','IO']) : # 因第一根K线的价格为0 symbol_got_list = [] fn = get_dss() + 'fut/engine/ratio/portfolio_ratio_param.csv' df = pd.read_csv(fn) # 加载最新参数 for i, row in df.iterrows(): try: if row.state == 'stop': continue if row.symbol_b not in self.got_dict or row.symbol_s not in self.got_dict: continue if self.got_dict[row.symbol_b] == False or self.got_dict[ row.symbol_s] == False: continue else: df.at[i, 'tm'] = bar.time symbol_got_list.append(row.symbol_b) symbol_got_list.append(row.symbol_s) s_b = self.signalDict[row.symbol_b][0] s_s = self.signalDict[row.symbol_s][0] # 开仓 if row.hold_b == 0 and row.hold_s == 0: if self.engine.type == 'backtest': if row.num_s * s_s.bar.close - row.num_b * s_b.bar.close >= row.gap: s_b.buy(s_b.bar.close, row.num_b) s_s.short(s_s.bar.close, row.num_s) df.at[i, 'price_b'] = s_b.bar.close df.at[i, 'price_s'] = s_s.bar.close df.at[i, 'hold_b'] = row.num_b df.at[i, 'hold_s'] = row.num_s else: gap_open = row.num_s * s_s.bar.BidPrice - row.num_b * s_b.bar.AskPrice df.at[i, 'gap_open'] = gap_open df.at[i, 'price_b'] = round(s_b.bar.AskPrice, 2) df.at[i, 'price_s'] = round(s_s.bar.BidPrice, 2) if gap_open >= row.gap: s_b.buy(s_b.bar.AskPrice, row.num_b) # 挂卖价 s_s.short(s_s.bar.BidPrice, row.num_s) # 挂买价 df.at[i, 'hold_b'] = row.num_b df.at[i, 'hold_s'] = row.num_s # 获利平仓 if row.hold_b > 0 and row.hold_s > 0: if self.engine.type == 'backtest': df.at[i, 'profit_b'] = round( (s_b.bar.close - row.price_b) * row.hold_b, 2) df.at[i, 'profit_s'] = round( -(s_s.bar.close - row.price_s) * row.hold_s, 2) df.at[i, 'profit_o'] = round( df.at[i, 'profit_b'] + df.at[i, 'profit_s'], 2) if df.at[i, 'profit_o'] >= row.profit: s_b.sell(s_b.bar.close, row.num_b) s_s.cover(s_s.bar.close, row.num_s) df.at[i, 'hold_b'] = 0 df.at[i, 'hold_s'] = 0 df.at[i, 'state'] = 'stop' else: df.at[i, 'profit_b'] = round( (s_b.bar.BidPrice - row.price_b) * row.hold_b, 2) df.at[i, 'profit_s'] = round( -(s_s.bar.AskPrice - row.price_s) * row.hold_s, 2) df.at[i, 'profit_o'] = round( df.at[i, 'profit_b'] + df.at[i, 'profit_s'], 2) if df.at[i, 'profit_o'] >= row.profit: s_b.sell(s_b.bar.BidPrice, row.num_b) # 挂买价 s_s.cover(s_s.bar.AskPrice, row.num_s) # 挂卖价 df.at[i, 'hold_b'] = 0 df.at[i, 'hold_s'] = 0 df.at[i, 'state'] = 'stop' except Exception as e: s = traceback.format_exc() to_log(s) df.to_csv(fn, index=False) # 回写文件 for symbol in symbol_got_list: self.got_dict[symbol] = False #---------------------------------------------------------------------- def daily_open(self): Portfolio.daily_open(self) #---------------------------------------------------------------------- def daily_close(self): Portfolio.daily_close(self) fn = get_dss() + 'fut/engine/ratio/portfolio_ratio_param.csv' df = pd.read_csv(fn) for i, row in df.iterrows(): if row.date == self.result.date[: 10] and row.hold_b == 0 and row.hold_s == 0: df.at[i, 'state'] = 'stop' df = df[(df.state == 'run') | (df.date >= get_trade_preday(self.result.date[:10]))] df.to_csv(fn, index=False)
class Fut_StraddlePortfolio(Portfolio): #---------------------------------------------------------------------- def __init__(self, engine, symbol_list, signal_param={}): self.name = 'straddle' self.tm = '00:00:00' self.got_dict = {} for symbol in symbol_list: self.got_dict[symbol] = False Portfolio.__init__(self, Fut_StraddleSignal, engine, symbol_list, signal_param) self.promote = True #---------------------------------------------------------------------- def onBar(self, bar, minx='min1'): """引擎新推送过来bar,传递给每个signal""" # 不处理不相关的品种 if bar.vtSymbol not in self.vtSymbolList: return if minx != 'min1': # 本策略为min1 return # 动态加载新维护的symbol config = open(get_dss() + 'fut/cfg/config.json') setting = json.load(config) symbols = setting['symbols_straddle'] symbols_list = symbols.split(',') for vtSymbol in symbols_list: if vtSymbol not in self.vtSymbolList: self.vtSymbolList.append(vtSymbol) self.posDict[vtSymbol] = 0 self.got_dict[vtSymbol] = False signal1 = Fut_StraddleSignal(self, vtSymbol) l = self.signalDict[vtSymbol] l.append(signal1) if self.tm != bar.time: self.tm = bar.time for symbol in self.vtSymbolList: self.got_dict[symbol] = False if self.result.date != bar.date + ' ' + bar.time: previousResult = self.result self.result = DailyResult(bar.date + ' ' + bar.time) self.resultList.append(self.result) if previousResult: self.result.updateClose(previousResult.closeDict) # 将bar推送给signal for signal in self.signalDict[bar.vtSymbol]: signal.onBar(bar, minx) # print(bar.vtSymbol, bar.time) """ 在此实现P层的业务控制逻辑 为每一个品种来检查是否触发下单条件 # 开始处理组合关心的bar , 尤其是品种对价差的加工和处理 """ self.control_in_p(bar) self.result.updateBar(bar) self.result.updatePos(self.posDict) #---------------------------------------------------------------------- def control_in_p(self, bar): if (bar.time > '09:31:00' and bar.time < '11:27:00' and bar.vtSymbol[:2] in ['IF','IO']) or \ (bar.time > '13:01:00' and bar.time < '14:57:00' and bar.vtSymbol[:2] in ['IF','IO']) or \ (bar.time > '21:01:00' and bar.time < '24:00:00' and bar.vtSymbol[:2] in ['al']) or \ (bar.time > '00:00:00' and bar.time < '01:00:00' and bar.vtSymbol[:2] in ['al']) or \ (bar.time > '09:01:00' and bar.time < '11:27:00' and bar.vtSymbol[:2] not in ['IF','IO']) or \ (bar.time > '13:31:00' and bar.time < '14:57:00' and bar.vtSymbol[:2] not in ['IF','IO']) or \ (bar.time > '21:01:00' and bar.time < '22:57:00' and bar.vtSymbol[:2] not in ['IF','IO']) : # 因第一根K线的价格为0 symbol_got_list = [] fn = get_dss() + 'fut/engine/straddle/portfolio_straddle_param.csv' # while get_file_lock(fn) == False: # time.sleep(0.01) df = pd.read_csv(fn) # 加载最新参数 for i, row in df.iterrows(): try: if row.state == 'stop': continue exchangeID = str(get_contract(row.basic_c).exchangeID) if exchangeID in ['CFFEX', 'DCE']: symbol_c = row.basic_c + '-C-' + str(row.strike_c) symbol_p = row.basic_p + '-P-' + str(row.strike_p) else: symbol_c = row.basic_c + 'C' + str(row.strike_c) symbol_p = row.basic_p + 'P' + str(row.strike_p) if symbol_c not in self.got_dict or symbol_p not in self.got_dict: continue if self.got_dict[symbol_c] == False or self.got_dict[ symbol_p] == False: continue else: df.at[i, 'tm'] = bar.time symbol_got_list.append(symbol_c) symbol_got_list.append(symbol_p) s_c = self.signalDict[symbol_c][0] s_p = self.signalDict[symbol_p][0] # 开仓 if row.hold_c == 0 and row.hold_p == 0: # print('come here ') if row.direction == 'duo': if self.engine.type == 'backtest': s_c.buy(s_c.bar.close, row.num_c) s_p.buy(s_p.bar.close, row.num_p) df.at[i, 'price_c'] = s_c.bar.close df.at[i, 'price_p'] = s_p.bar.close else: s_c.buy(s_c.bar.AskPrice, row.num_c) # 挂卖价 s_p.buy(s_p.bar.AskPrice, row.num_p) # 挂卖价 df.at[i, 'price_c'] = round( s_c.bar.AskPrice, 2) df.at[i, 'price_p'] = round( s_p.bar.AskPrice, 2) df.at[i, 'hold_c'] = row.num_c df.at[i, 'hold_p'] = row.num_p if row.direction == 'kong': if self.engine.type == 'backtest': s_c.short(s_c.bar.close, row.num_c) s_p.short(s_p.bar.close, row.num_p) df.at[i, 'price_c'] = s_c.bar.close df.at[i, 'price_p'] = s_p.bar.close else: s_c.short(s_c.bar.BidPrice, row.num_c) # 挂买价 s_p.short(s_p.bar.BidPrice, row.num_p) # 挂买价 df.at[i, 'price_c'] = round( s_c.bar.BidPrice, 2) df.at[i, 'price_p'] = round( s_p.bar.BidPrice, 2) df.at[i, 'hold_c'] = -row.num_c df.at[i, 'hold_p'] = -row.num_p # 多单获利平仓 if row.hold_c >= 1 and row.hold_p >= 1: if self.engine.type == 'backtest': df.at[i, 'profit_c'] = (s_c.bar.close - row.price_c) * row.hold_c df.at[i, 'profit_p'] = (s_p.bar.close - row.price_p) * row.hold_p df.at[i, 'profit_o'] = df.at[ i, 'profit_c'] + df.at[i, 'profit_p'] if row.profit_o >= row.profit: s_c.sell(s_c.bar.close, abs(row.hold_c)) s_p.sell(s_p.bar.close, abs(row.hold_p)) df.at[i, 'hold_c'] = 0 df.at[i, 'hold_p'] = 0 df.at[i, 'state'] = 'stop' else: df.at[i, 'profit_c'] = round( (s_c.bar.BidPrice - row.price_c) * row.hold_c, 2) df.at[i, 'profit_p'] = round( (s_p.bar.BidPrice - row.price_p) * row.hold_p, 2) df.at[i, 'profit_o'] = round( df.at[i, 'profit_c'] + df.at[i, 'profit_p'], 2) if row.profit_o >= row.profit: s_c.sell(s_c.bar.BidPrice, abs(row.hold_c)) s_p.sell(s_p.bar.BidPrice, abs(row.hold_p)) df.at[i, 'hold_c'] = 0 df.at[i, 'hold_p'] = 0 df.at[i, 'state'] = 'stop' # 空单获利平仓 if row.hold_c <= -1 and row.hold_p <= -1: if self.engine.type == 'backtest': df.at[i, 'profit_c'] = (s_c.bar.close - row.price_c) * row.hold_c df.at[i, 'profit_p'] = (s_p.bar.close - row.price_p) * row.hold_p df.at[i, 'profit_o'] = df.at[ i, 'profit_c'] + df.at[i, 'profit_p'] if row.profit_o >= row.profit: s_c.cover(s_c.bar.close, abs(row.hold_c)) s_p.cover(s_p.bar.close, abs(row.hold_p)) df.at[i, 'hold_c'] = 0 df.at[i, 'hold_p'] = 0 df.at[i, 'state'] = 'stop' else: df.at[i, 'profit_c'] = round( (s_c.bar.AskPrice - row.price_c) * row.hold_c, 2) df.at[i, 'profit_p'] = round( (s_p.bar.AskPrice - row.price_p) * row.hold_p, 2) df.at[i, 'profit_o'] = round( df.at[i, 'profit_c'] + df.at[i, 'profit_p'], 2) if row.profit_o >= row.profit: s_c.cover(s_c.bar.AskPrice, abs(row.hold_c)) s_p.cover(s_p.bar.AskPrice, abs(row.hold_p)) df.at[i, 'hold_c'] = 0 df.at[i, 'hold_p'] = 0 df.at[i, 'state'] = 'stop' except Exception as e: s = traceback.format_exc() to_log(s) df.to_csv(fn, index=False) # 回写文件 # release_file_lock(fn) for symbol in symbol_got_list: self.got_dict[symbol] = False #---------------------------------------------------------------------- def daily_open(self): Portfolio.daily_open(self) #---------------------------------------------------------------------- def daily_close(self): Portfolio.daily_close(self) fn = get_dss() + 'fut/engine/straddle/portfolio_straddle_param.csv' df = pd.read_csv(fn) for i, row in df.iterrows(): if row.date == self.result.date[: 10] and row.hold_c == 0 and row.hold_p == 0: df.at[i, 'state'] = 'stop' df = df[(df.state == 'run') | (df.date == self.result.date[:10])] df.to_csv(fn, index=False)
class Fut_RatioPortfolio(Portfolio): #---------------------------------------------------------------------- def __init__(self, engine, symbol_list, signal_param={}): self.name = 'ratio' assert len(symbol_list) == 2 self.symbol_c = symbol_list[0] self.symbol_p = symbol_list[1] self.dual_name = self.symbol_c + '_' + self.symbol_p self.got_dict = {} self.got_dict[self.symbol_c] = False self.got_dict[self.symbol_p] = False self.price_c = 0 self.price_p = 0 self.hold_c = 0 self.hold_p = 0 self.profit_c = 0 self.profit_p = 0 self.fixed_size = 1 self.gap = 100 self.profit = 100 self.load_param(self.symbol_c, self.symbol_p) Portfolio.__init__(self, Fut_RatioSignal, engine, symbol_list, signal_param) self.name_second = 'ratio_' + self.dual_name #---------------------------------------------------------------------- def load_param(self, s_c, s_p): fn = get_dss() + 'fut/engine/ratio/portfolio_ratio_param.csv' df = pd.read_csv(fn) df = df[(df.symbol_c == s_c) & (df.symbol_p == s_p)] if len(df) > 0: row = df.iloc[-1, :] self.fixed_size = int(row.fixed_size) self.gap = int(row.gap) self.profit = int(row.profit) #---------------------------------------------------------------------- def onBar(self, bar, minx='min1'): """引擎新推送过来bar,传递给每个signal""" # 不处理不相关的品种 if bar.vtSymbol not in self.vtSymbolList: return if minx != 'min1': # 本策略为min1 return if self.result.date != bar.date + ' ' + bar.time: previousResult = self.result self.result = DailyResult(bar.date + ' ' + bar.time) self.resultList.append(self.result) if previousResult: self.result.updateClose(previousResult.closeDict) # 将bar推送给signal for signal in self.signalDict[bar.vtSymbol]: signal.onBar(bar, minx) # print(bar.vtSymbol, bar.time) """ 在此实现P层的业务控制逻辑 为每一个品种来检查是否触发下单条件 # 开始处理组合关心的bar , 尤其是品种对价差的加工和处理 """ if (bar.time > '09:35:00' and bar.time < '11:25:00' and bar.vtSymbol[:2] in ['IF','IO']) or \ (bar.time > '13:05:00' and bar.time < '14:55:00' and bar.vtSymbol[:2] in ['IF','IO']) or \ (bar.time > '09:05:00' and bar.time < '11:25:00' and bar.vtSymbol[:2] not in ['IF','IO']) or \ (bar.time > '13:35:00' and bar.time < '14:55:00' and bar.vtSymbol[:2] not in ['IF','IO']) or \ (bar.time > '21:05:00' and bar.time < '22:55:00' and bar.vtSymbol[:2] not in ['IF','IO']) : # 因第一根K线的价格为0 # 开仓 if self.hold_c == 0 and self.hold_p == 0: self.load_param(self.symbol_c, self.symbol_p) # 加载最新参数 if self.got_dict[self.symbol_c] == True and self.got_dict[ self.symbol_p] == True: self.got_dict[self.symbol_c] = False self.got_dict[self.symbol_p] = False s_c = self.signalDict[self.symbol_c][0] s_p = self.signalDict[self.symbol_p][0] if 2 * s_p.bar.close - s_c.bar.close >= self.gap: if self.engine.type == 'backtest': s_c.buy(s_c.bar.close, self.fixed_size) s_p.short(s_p.bar.close, 2 * self.fixed_size) self.price_c = s_c.bar.close self.price_p = s_p.bar.close else: s_c.buy(s_c.bar.AskPrice, self.fixed_size) # 挂卖价 s_p.short(s_p.bar.BidPrice, 2 * self.fixed_size) # 挂买价 self.price_c = s_c.bar.AskPrice self.price_p = s_p.bar.BidPrice self.hold_c = 1 self.hold_p = -2 # 获利平仓 if self.hold_c == 1 and self.hold_p == -2: self.load_param(self.symbol_c, self.symbol_p) # 加载最新参数 if self.got_dict[self.symbol_c] == True and self.got_dict[ self.symbol_p] == True: self.got_dict[self.symbol_c] = False self.got_dict[self.symbol_p] = False s_c = self.signalDict[self.symbol_c][0] s_p = self.signalDict[self.symbol_p][0] if self.profit_c + self.profit_p >= self.profit: if self.engine.type == 'backtest': s_c.sell(s_c.bar.close, self.fixed_size) s_p.cover(s_p.bar.close, 2 * self.fixed_size) else: s_c.sell(s_c.bar.BidPrice, self.fixed_size) # 挂买价 s_p.cover(s_p.bar.AskPrice, 2 * self.fixed_size) # 挂卖价 self.hold_c = 0 self.hold_p = 0 self.result.updateBar(bar) self.result.updatePos(self.posDict) #---------------------------------------------------------------------- def daily_open(self): Portfolio.daily_open(self) fn = get_dss( ) + 'fut/engine/ratio/portfolio_' + self.name_second + '_save.csv' if os.path.exists(fn): df = pd.read_csv(fn) df = df[(df.symbol_c == self.symbol_c) & (df.symbol_p == self.symbol_p)] if len(df) > 0: rec = df.iloc[-1, :] # 取最近日期的记录 self.price_c = rec.price_c self.price_p = rec.price_p self.hold_c = rec.hold_c self.hold_p = rec.hold_p #---------------------------------------------------------------------- def daily_close(self): Portfolio.daily_close(self) r = [[ self.result.date, self.symbol_c, self.symbol_p, self.price_c, self.price_p, self.hold_c, self.hold_p ]] df = pd.DataFrame(r, columns=[ 'datetime', 'symbol_c', 'symbol_p', 'price_c', 'price_p', 'hold_c', 'hold_p' ]) fn = get_dss( ) + 'fut/engine/ratio/portfolio_' + self.name_second + '_save.csv' if os.path.exists(fn): df.to_csv(fn, index=False, mode='a', header=False) else: df.to_csv(fn, index=False)