class Turtle: def __init__(self, account_id, symbol, donchian_channel_open_position=20, donchian_channel_stop_profit=10, atr_day_length=20): self.account_id = account_id self.symbol = symbol # 合约代码 self.donchian_channel_open_position = donchian_channel_open_position # 唐奇安通道的天数周期(开仓) self.donchian_channel_stop_profit = donchian_channel_stop_profit # 唐奇安通道的天数周期(止盈) self.atr_day_length = atr_day_length # ATR计算所用天数 self.state = { "position": 0, # 本策略净持仓数(正数表示多头,负数表示空头,0表示空仓) "last_price": float("nan"), # 上次调仓价 } self.n = 0 self.unit = 0 self.donchian_channel_high = 0 self.donchian_channel_low = 0 self.api = TqApi(self.account_id) self.quote = self.api.get_quote(self.symbol) # 由于ATR是路径依赖函数,因此使用更长的数据序列进行计算以便使其值稳定下来 kline_length = max(donchian_channel_open_position + 1, donchian_channel_stop_profit + 1, atr_day_length * 5) self.klines = self.api.get_kline_serial(self.symbol, 24 * 60 * 60, data_length=kline_length) self.account = self.api.get_account() self.target_pos = TargetPosTask(self.api, self.symbol, init_pos=self.state["position"]) def recalc_paramter(self): try: df = self.klines.to_dataframe() # 本交易日的平均真实波幅(N值) self.n = talib.ATR(df["high"], df["low"], df["close"], timeperiod=self.atr_day_length).iloc[-1] # 买卖单位 self.unit = int((self.account["balance"] * 0.01) / (self.quote["volume_multiple"] * self.n)) print('atr:', self.n, " unit:", self.unit) # 唐奇安通道上轨:前N个交易日的最高价 self.donchian_channel_high = max( self.klines.high[-self.donchian_channel_open_position - 1:-1]) # 唐奇安通道下轨:前N个交易日的最低价 self.donchian_channel_low = min( self.klines.low[-self.donchian_channel_open_position - 1:-1]) print("唐其安通道上下轨:", self.donchian_channel_high, self.donchian_channel_low) except Exception: # 若尚未接收到数据, 即数据为NaN, 则在ATR或unit计算时会报错 return False return True def set_position(self, pos): self.state["position"] = pos self.state["last_price"] = self.quote["last_price"] self.target_pos.set_target_volume(self.state["position"]) def try_open(self): """开仓策略""" while self.state["position"] == 0: self.api.wait_update() if self.api.is_changing(self.klines[-1], "datetime"): # 如果产生新k线,则重新计算唐奇安通道及买卖单位 self.recalc_paramter() if self.api.is_changing(self.quote, "last_price"): print("最新价: ", self.quote["last_price"]) if self.quote[ "last_price"] > self.donchian_channel_high: # 当前价>唐奇安通道上轨,买入1个Unit;(持多仓) print("当前价>唐奇安通道上轨,买入1个Unit(持多仓):", self.unit, "手") self.set_position(self.state["position"] + self.unit) elif self.quote[ "last_price"] < self.donchian_channel_low: # 当前价<唐奇安通道下轨,卖出1个Unit;(持空仓) print("当前价<唐奇安通道下轨,卖出1个Unit(持空仓):", self.unit, "手") self.set_position(self.state["position"] - self.unit) def try_close(self): """交易策略""" while self.state["position"] != 0: self.api.wait_update() if self.api.is_changing(self.quote, "last_price"): print("最新价: ", self.quote["last_price"]) if self.state["position"] > 0: # 持多单 # 加仓策略: 如果是多仓且资产的价格在上一次建仓(或者加仓)的基础上又上涨了0.5N,就再加一个Unit的多仓 if self.quote["last_price"] >= self.state[ "last_price"] + 0.5 * self.n: print("加仓:加1个Unit的多仓") self.set_position(self.state["position"] + self.unit) # 止损策略: 如果是多仓且资产的价格在上一次建仓(或者加仓)的基础上又下跌了2N,就卖出全部头寸止损 elif self.quote["last_price"] <= self.state[ "last_price"] - 2 * self.n: print("止损:卖出全部头寸") self.set_position(0) # 止盈策略: 如果是多仓且当前资产价格跌破了10日唐奇安通道的下轨,就清空所有头寸结束策略,离场 if self.quote["last_price"] <= min( self.klines. low[-self.donchian_channel_stop_profit - 1:-1]): print("止盈:清空所有头寸结束策略,离场") self.set_position(0) elif self.state["position"] < 0: # 持空单 # 加仓策略: 如果是空仓且资产的价格在上一次建仓(或者加仓)的基础上又下跌了0.5N,就再加一个Unit的空仓 if self.quote["last_price"] <= self.state[ "last_price"] - 0.5 * self.n: print("加仓:加1个Unit的空仓") self.set_position(self.state["position"] - self.unit) # 止损策略: 如果是空仓且资产的价格在上一次建仓(或者加仓)的基础上又上涨了2N,就平仓止损 elif self.quote["last_price"] >= self.state[ "last_price"] + 2 * self.n: print("止损:卖出全部头寸") self.set_position(0) # 止盈策略: 如果是空仓且当前资产价格升破了10日唐奇安通道的上轨,就清空所有头寸结束策略,离场 if self.quote["last_price"] >= max( self.klines. high[-self.donchian_channel_stop_profit - 1:-1]): print("止盈:清空所有头寸结束策略,离场") self.set_position(0) def strategy(self): """海龟策略""" print("等待K线及账户数据...") deadline = time.time() + 5 while not self.recalc_paramter(): if not self.api.wait_update(deadline=deadline): raise Exception("获取数据失败,请确认行情连接正常并已经登录交易账户") while True: self.try_open() self.try_close()
def test_lib_insert_order_time_check_7(self): """ lib下单时间判断测试7 订阅合约: 订阅周六有行情的和周六无行情的 测试: (测试:回测从周六开始时 可交易时间段的计算、判断) 1 回测刚开始:current_datetime 为 0:00 , 只有cu能下单,另外两个合约直到白盘9点下单 """ # 预设服务器端响应 dir_path = os.path.dirname(os.path.realpath(__file__)) self.mock.run( os.path.join(dir_path, "log_file", "test_lib_insert_order_time_check_7.script.lzma")) TqApi.RD = random.Random(4) api = TqApi(backtest=TqBacktest( datetime.datetime(2019, 11, 30, 0, 0, 0), datetime.datetime(2019, 12, 2, 9, 30)), _ins_url=self.ins_url_2019_12_04) symbol1 = "SHFE.cu2002" # 有夜盘,凌晨1点结束夜盘 symbol2 = "SHFE.rb2002" # 夜盘23点结束 symbol3 = "DCE.jd2002" # 无夜盘 quote1 = api.get_quote(symbol1) quote2 = api.get_quote(symbol2) quote3 = api.get_quote(symbol3) position1 = api.get_position(symbol1) position2 = api.get_position(symbol2) position3 = api.get_position(symbol3) target_pos1 = TargetPosTask(api, symbol1) target_pos2 = TargetPosTask(api, symbol2) target_pos3 = TargetPosTask(api, symbol3) orders = api.get_order() try: # 1 回测刚开始:current_datetime 为 0:00 , 只有cu能下单,另外两个合约直到白盘9点下单 target_pos1.set_target_volume(1) target_pos2.set_target_volume(2) target_pos3.set_target_volume(3) while max(quote1.datetime, quote2.datetime, quote3.datetime) < "2019-11-30 00:02:00.000000": api.wait_update() self.assertEqual(len(orders), 1) while max(quote1.datetime, quote2.datetime, quote3.datetime) < "2019-11-30 00:15:00.000000": api.wait_update() self.assertEqual(len(orders), 1) self.assertEqual(position1.pos, 1) self.assertEqual(position2.pos, 0) self.assertEqual(position3.pos, 0) while max(quote1.datetime, quote2.datetime, quote3.datetime) < "2019-12-02 09:05:00.000000": api.wait_update() self.assertEqual(len(orders), 3) self.assertEqual(position1.pos, 1) self.assertEqual(position2.pos, 2) self.assertEqual(position3.pos, 3) while True: api.wait_update() except BacktestFinished: self.assertEqual(position1.pos, 1) self.assertEqual(position2.pos, 2) self.assertEqual(position3.pos, 3) api.close()
class Turtle: def __init__(self, symbol, account=None, donchian_channel_open_position=20, donchian_channel_stop_profit=10, atr_day_length=20, max_risk_ratio=0.5): self.account = account # 交易账号 self.symbol = symbol # 合约代码 self.donchian_channel_open_position = donchian_channel_open_position # 唐奇安通道的天数周期(开仓) self.donchian_channel_stop_profit = donchian_channel_stop_profit # 唐奇安通道的天数周期(止盈) self.atr_day_length = atr_day_length # ATR计算所用天数 self.max_risk_ratio = max_risk_ratio # 最高风险度 self.state = { "position": 0, # 本策略净持仓数(正数表示多头,负数表示空头,0表示空仓) "last_price": float("nan"), # 上次调仓价 } self.n = 0 # 平均真实波幅(N值) self.unit = 0 # 买卖单位 self.donchian_channel_high = 0 # 唐奇安通道上轨 self.donchian_channel_low = 0 # 唐奇安通道下轨 self.api = TqApi(self.account) self.quote = self.api.get_quote(self.symbol) # 由于ATR是路径依赖函数,因此使用更长的数据序列进行计算以便使其值稳定下来 kline_length = max(donchian_channel_open_position + 1, donchian_channel_stop_profit + 1, atr_day_length * 5) self.klines = self.api.get_kline_serial(self.symbol, 24 * 60 * 60, data_length=kline_length) self.account = self.api.get_account() self.target_pos = TargetPosTask(self.api, self.symbol) def recalc_paramter(self): # 平均真实波幅(N值) self.n = ATR(self.klines, self.atr_day_length)["atr"].iloc[-1] # 买卖单位 self.unit = int((self.account.balance * 0.01) / (self.quote.volume_multiple * self.n)) # 唐奇安通道上轨:前N个交易日的最高价 self.donchian_channel_high = max( self.klines.high[-self.donchian_channel_open_position - 1:-1]) # 唐奇安通道下轨:前N个交易日的最低价 self.donchian_channel_low = min( self.klines.low[-self.donchian_channel_open_position - 1:-1]) print("唐其安通道上下轨: %f, %f" % (self.donchian_channel_high, self.donchian_channel_low)) return True def set_position(self, pos): self.state["position"] = pos self.state["last_price"] = self.quote["last_price"] self.target_pos.set_target_volume(self.state["position"]) def try_open(self): """开仓策略""" while self.state["position"] == 0: self.api.wait_update() if self.api.is_changing(self.klines.iloc[-1], "datetime"): # 如果产生新k线,则重新计算唐奇安通道及买卖单位 self.recalc_paramter() if self.api.is_changing(self.quote, "last_price"): print("最新价: %f" % self.quote.last_price) if self.quote.last_price > self.donchian_channel_high: # 当前价>唐奇安通道上轨,买入1个Unit;(持多仓) print("当前价>唐奇安通道上轨,买入1个Unit(持多仓): %d 手" % self.unit) self.set_position(self.state["position"] + self.unit) elif self.quote.last_price < self.donchian_channel_low: # 当前价<唐奇安通道下轨,卖出1个Unit;(持空仓) print("当前价<唐奇安通道下轨,卖出1个Unit(持空仓): %d 手" % self.unit) self.set_position(self.state["position"] - self.unit) def try_close(self): """交易策略""" while self.state["position"] != 0: self.api.wait_update() if self.api.is_changing(self.quote, "last_price"): print("最新价: ", self.quote.last_price) if self.state["position"] > 0: # 持多单 # 加仓策略: 如果是多仓且行情最新价在上一次建仓(或者加仓)的基础上又上涨了0.5N,就再加一个Unit的多仓,并且风险度在设定范围内(以防爆仓) if self.quote.last_price >= self.state[ "last_price"] + 0.5 * self.n and self.account.risk_ratio <= self.max_risk_ratio: print("加仓:加1个Unit的多仓") self.set_position(self.state["position"] + self.unit) # 止损策略: 如果是多仓且行情最新价在上一次建仓(或者加仓)的基础上又下跌了2N,就卖出全部头寸止损 elif self.quote.last_price <= self.state[ "last_price"] - 2 * self.n: print("止损:卖出全部头寸") self.set_position(0) # 止盈策略: 如果是多仓且行情最新价跌破了10日唐奇安通道的下轨,就清空所有头寸结束策略,离场 if self.quote.last_price <= min( self.klines. low[-self.donchian_channel_stop_profit - 1:-1]): print("止盈:清空所有头寸结束策略,离场") self.set_position(0) elif self.state["position"] < 0: # 持空单 # 加仓策略: 如果是空仓且行情最新价在上一次建仓(或者加仓)的基础上又下跌了0.5N,就再加一个Unit的空仓,并且风险度在设定范围内(以防爆仓) if self.quote.last_price <= self.state[ "last_price"] - 0.5 * self.n and self.account.risk_ratio <= self.max_risk_ratio: print("加仓:加1个Unit的空仓") self.set_position(self.state["position"] - self.unit) # 止损策略: 如果是空仓且行情最新价在上一次建仓(或者加仓)的基础上又上涨了2N,就平仓止损 elif self.quote.last_price >= self.state[ "last_price"] + 2 * self.n: print("止损:卖出全部头寸") self.set_position(0) # 止盈策略: 如果是空仓且行情最新价升破了10日唐奇安通道的上轨,就清空所有头寸结束策略,离场 if self.quote.last_price >= max( self.klines. high[-self.donchian_channel_stop_profit - 1:-1]): print("止盈:清空所有头寸结束策略,离场") self.set_position(0) def strategy(self): """海龟策略""" print("等待K线及账户数据...") deadline = time.time() + 5 while not self.recalc_paramter(): if not self.api.wait_update(deadline=deadline): raise Exception("获取数据失败,请确认行情连接正常并已经登录交易账户") while True: self.try_open() self.try_close()
def test_insert_order(self): """ 下单 """ # 预设服务器端响应 dir_path = os.path.dirname(os.path.realpath(__file__)) self.mock.run( os.path.join(dir_path, "log_file", "test_td_basic_insert_order_simulate.script.lzma")) # 测试: 模拟账户下单 # 测试脚本重新生成后,数据根据实际情况有变化 TqApi.RD = random.Random(2) api = TqApi(_ins_url=self.ins_url, _td_url=self.td_url, _md_url=self.md_url) order1 = api.insert_order("DCE.jd2001", "BUY", "OPEN", 1) order2 = api.insert_order("SHFE.cu2001", "BUY", "OPEN", 2, limit_price=49200) while order1.status == "ALIVE" or order2.status == "ALIVE": api.wait_update() self.assertEqual(order1.order_id, "5c6e433715ba2bdd177219d30e7a269f") self.assertEqual(order1.direction, "BUY") self.assertEqual(order1.offset, "OPEN") self.assertEqual(order1.volume_orign, 1) self.assertEqual(order1.volume_left, 0) self.assertEqual(order1.limit_price != order1.limit_price, True) # 判断nan self.assertEqual(order1.price_type, "ANY") self.assertEqual(order1.volume_condition, "ANY") self.assertEqual(order1.time_condition, "IOC") self.assertEqual(order1.insert_date_time, 631123200000000000) self.assertEqual(order1.status, "FINISHED") for k, v in order1.trade_records.items(): # 模拟交易为一次性全部成交 self.assertEqual( str(v), "{'order_id': '5c6e433715ba2bdd177219d30e7a269f', 'trade_id': '5c6e433715ba2bdd177219d30e7a269f|1', 'exchange_trade_id': '5c6e433715ba2bdd177219d30e7a269f|1', 'exchange_id': 'DCE', 'instrument_id': 'jd2001', 'direction': 'BUY', 'offset': 'OPEN', 'price': 4087.0, 'volume': 1, 'trade_date_time': 1576121399900001000, 'symbol': 'DCE.jd2001', 'user_id': 'TQSIM', 'commission': 6.122999999999999}" ) self.assertEqual(order2.order_id, "cf1822ffbc6887782b491044d5e34124") self.assertEqual(order2.direction, "BUY") self.assertEqual(order2.offset, "OPEN") self.assertEqual(order2.volume_orign, 2) self.assertEqual(order2.volume_left, 0) self.assertEqual(order2.limit_price, 49200.0) self.assertEqual(order2.price_type, "LIMIT") self.assertEqual(order2.volume_condition, "ANY") self.assertEqual(order2.time_condition, "GFD") self.assertEqual(order2.insert_date_time, 631123200000000000) self.assertEqual(order2.status, "FINISHED") for k, v in order2.trade_records.items(): # 模拟交易为一次性全部成交 self.assertEqual( str(v), "{'order_id': 'cf1822ffbc6887782b491044d5e34124', 'trade_id': 'cf1822ffbc6887782b491044d5e34124|2', 'exchange_trade_id': 'cf1822ffbc6887782b491044d5e34124|2', 'exchange_id': 'SHFE', 'instrument_id': 'cu2001', 'direction': 'BUY', 'offset': 'OPEN', 'price': 49200.0, 'volume': 2, 'trade_date_time': 1576121399900001000, 'symbol': 'SHFE.cu2001', 'user_id': 'TQSIM', 'commission': 23.189999999999998}" ) api.close()
def test_lib_insert_order_time_check_4(self): ''' lib下单时间判断测试4 回测时间: 起始交易日(datetime.date)为周一 订阅合约: cu(有夜盘,凌晨1点结束夜盘),rb(夜盘23点结束),jd(无夜盘) 测试: (测试周五夜盘21点到周六凌晨1点及周一夜盘、周二白盘) 1 周五晚21:00之后: cu、rb能下单, jd到周一的9点后下单 2 周六凌晨1点前:cu能下单 3 周一早9点后都能下单 4 周一晚21点后cu、rb能下单 5 周二白盘开始后,jd能下单 ''' # 预设服务器端响应 dir_path = os.path.dirname(os.path.realpath(__file__)) self.mock.run( os.path.join(dir_path, "log_file", "test_lib_insert_order_time_check_4.script.lzma")) TqApi.RD = random.Random(4) api = TqApi(backtest=TqBacktest(datetime.date(2019, 12, 2), datetime.date(2019, 12, 3)), _ins_url=self.ins_url_2019_12_04) # 2019.12.2:周一 symbol1 = "SHFE.cu2002" # 有夜盘,凌晨1点结束夜盘 symbol2 = "SHFE.rb2002" # 夜盘23点结束 symbol3 = "DCE.jd2002" # 无夜盘 quote1 = api.get_quote(symbol1) quote2 = api.get_quote(symbol2) quote3 = api.get_quote(symbol3) position1 = api.get_position(symbol1) position2 = api.get_position(symbol2) position3 = api.get_position(symbol3) target_pos1 = TargetPosTask(api, symbol1) target_pos2 = TargetPosTask(api, symbol2) target_pos3 = TargetPosTask(api, symbol3) orders = api.get_order() try: # 1 周五晚21:00之后: cu、rb能下单, jd到周一的9点后下单 target_pos1.set_target_volume(1) target_pos2.set_target_volume(2) target_pos3.set_target_volume(3) while max(quote1.datetime, quote2.datetime, quote3.datetime) < "2019-11-29 21:05:00.000000": api.wait_update() self.assertEqual(len(orders), 2) self.assertEqual(position1.pos, 1) self.assertEqual(position2.pos, 2) self.assertEqual(position3.pos, 0) # 2 周五23点后到周六凌晨1点前:cu能下单 while max(quote1.datetime, quote2.datetime, quote3.datetime) < "2019-11-29 23:00:00.000000": api.wait_update() target_pos1.set_target_volume(4) target_pos2.set_target_volume(5) target_pos3.set_target_volume(6) while max(quote1.datetime, quote2.datetime, quote3.datetime) < "2019-11-29 23:05:00.000000": api.wait_update() self.assertEqual(len(orders), 3) self.assertEqual(position1.pos, 4) self.assertEqual(position2.pos, 2) self.assertEqual(position3.pos, 0) # 3 周一早9点后都能下单 while max(quote1.datetime, quote2.datetime, quote3.datetime) < "2019-12-02 09:05:00.000000": api.wait_update() self.assertEqual(len(orders), 5) self.assertEqual(position1.pos, 4) self.assertEqual(position2.pos, 5) self.assertEqual(position3.pos, 6) # 4 周一晚21点后cu、rb能下单 while max(quote1.datetime, quote2.datetime, quote3.datetime) < "2019-12-02 21:00:00.000000": api.wait_update() target_pos1.set_target_volume(0) target_pos2.set_target_volume(0) target_pos3.set_target_volume(0) while max(quote1.datetime, quote2.datetime, quote3.datetime) < "2019-12-02 21:15:00.000000": api.wait_update() self.assertEqual(len(orders), 7) self.assertEqual(position1.pos, 0) self.assertEqual(position2.pos, 0) self.assertEqual(position3.pos, 6) # 5 周二白盘开始后,jd能下单 while max(quote1.datetime, quote2.datetime, quote3.datetime) < "2019-12-03 09:02:00.000000": api.wait_update() self.assertEqual(len(orders), 8) while True: api.wait_update() except BacktestFinished: self.assertEqual(len(orders), 8) self.assertEqual(position1.pos, 0) self.assertEqual(position2.pos, 0) self.assertEqual(position3.pos, 0) api.close()
def test_get_position_option(self): """ 获取持仓 """ # 预设服务器端响应 dir_path = os.path.dirname(os.path.realpath(__file__)) self.mock.run( os.path.join( dir_path, "log_file", "test_td_basic_get_position_simulate_option.script.lzma")) # 测试: 获取数据 api = TqApi(_ins_url=self.ins_url_2020_04_02, _td_url=self.td_url, _md_url=self.md_url) order1 = api.insert_order("CZCE.SR007C5600", "BUY", "OPEN", 2, limit_price=55) order2 = api.insert_order("CZCE.SR007C5600", "BUY", "OPEN", 3, limit_price=55) order3 = api.insert_order("CZCE.SR007C5600", "SELL", "OPEN", 3, limit_price=10) order4 = api.insert_order("CZCE.SR007C5600", "SELL", "OPEN", 3) # 只有郑商所支持期权市价单 order5 = api.insert_order("DCE.m2007-P-2900", "BUY", "OPEN", 1) # 只有郑商所支持期权市价单 while order1.status == "ALIVE" or order2.status == "ALIVE" or order3.status == "ALIVE" or order4.status == "ALIVE" or order5.status == "ALIVE": api.wait_update() self.assertEqual(order4.volume_left, 0) self.assertEqual(order5.volume_left, 1) position = api.get_position("CZCE.SR007C5600") position2 = api.get_position("DCE.m2007-P-2900") self.assertEqual(0, position2.pos_long) self.assertEqual(0, position2.pos_short) # 测试脚本重新生成后,数据根据实际情况有变化 self.assertEqual( "{'exchange_id': 'CZCE', 'instrument_id': 'SR007C5600', 'pos_long_his': 0, 'pos_long_today': 5, 'pos_short_his': 0, 'pos_short_today': 6, 'volume_long_today': 5, 'volume_long_his': 0, 'volume_long': 5, 'volume_long_frozen_today': 0, 'volume_long_frozen_his': 0, 'volume_long_frozen': 0, 'volume_short_today': 6, 'volume_short_his': 0, 'volume_short': 6, 'volume_short_frozen_today': 0, 'volume_short_frozen_his': 0, 'volume_short_frozen': 0, 'open_price_long': 55.0, 'open_price_short': 22.5, 'open_cost_long': 2750.0, 'open_cost_short': 1350.0, 'position_price_long': 55.0, 'position_price_short': 22.5, 'position_cost_long': 2750.0, 'position_cost_short': 1350.0, 'float_profit_long': -1000.0, 'float_profit_short': -750.0, 'float_profit': -1750.0, 'position_profit_long': 0.0, 'position_profit_short': 0.0, 'position_profit': 0.0, 'margin_long': 0.0, 'margin_short': 8156.4000000000015, 'margin': 8156.4000000000015, 'market_value_long': 1750.0, 'market_value_short': -2100.0, 'market_value': -350.0, 'last_price': 35.0}", str(position)) self.assertEqual(-1, position.pos) self.assertEqual(5, position.pos_long) self.assertEqual(6, position.pos_short) self.assertEqual(position.exchange_id, "CZCE") self.assertEqual(position.instrument_id, "SR007C5600") self.assertEqual(position.pos_long_his, 0) self.assertEqual(position.pos_long_today, 5) self.assertEqual(position.pos_short_his, 0) self.assertEqual(position.pos_short_today, 6) self.assertEqual(position.volume_long_today, 5) self.assertEqual(position.volume_long_his, 0) self.assertEqual(position.volume_long, 5) self.assertEqual(position.volume_long_frozen_today, 0) self.assertEqual(position.volume_long_frozen_his, 0) self.assertEqual(position.volume_long_frozen, 0) self.assertEqual(position.volume_short_today, 6) self.assertEqual(position.volume_short_his, 0) self.assertEqual(position.volume_short, 6) self.assertEqual(position.volume_short_frozen_today, 0) self.assertEqual(position.volume_short_frozen_his, 0) self.assertEqual(position.volume_short_frozen, 0) self.assertEqual(position.open_price_long, 55.0) self.assertEqual(position.open_price_short, 22.5) self.assertEqual(position.open_cost_long, 2750.0) self.assertEqual(position.open_cost_short, 1350.0) self.assertEqual(position.position_price_long, 55.0) self.assertEqual(position.position_price_short, 22.5) self.assertEqual(position.position_cost_long, 2750.0) self.assertEqual(position.position_cost_short, 1350.0) self.assertEqual(position.float_profit_long, -1000.0) self.assertEqual(position.float_profit_short, -750.0) self.assertEqual(position.float_profit, -1750.0) self.assertEqual(position.position_profit_long, 0.0) self.assertEqual(position.position_profit_short, 0.0) self.assertEqual(position.position_profit, 0.0) self.assertEqual(position.margin_long, 0.0) self.assertEqual(position.margin_short, 8156.4000000000015) self.assertEqual(position.margin, 8156.4000000000015) self.assertEqual(position.market_value_long, 1750.0) self.assertEqual(position.market_value_short, -2100.0) self.assertEqual(position.market_value, -350.0) self.assertEqual(position.last_price, 35.0) # 其他取值方式测试 self.assertEqual(position["pos_long_today"], 5) self.assertEqual(position["pos_short_today"], 6) self.assertEqual(position["volume_long_his"], 0) self.assertEqual(position["volume_long"], 5) api.close()
def test_get_position(self): """ 获取持仓 """ # 预设服务器端响应 dir_path = os.path.dirname(os.path.realpath(__file__)) self.mock.run( os.path.join(dir_path, "log_file", "test_td_basic_get_position_simulate.script.lzma")) # 测试: 获取数据 api = TqApi(_ins_url=self.ins_url, _td_url=self.td_url, _md_url=self.md_url) order1 = api.insert_order("DCE.jd2001", "BUY", "OPEN", 1, limit_price=4592) order2 = api.insert_order("DCE.jd2001", "BUY", "OPEN", 3) order3 = api.insert_order("DCE.jd2001", "SELL", "OPEN", 3) while order1.status == "ALIVE" or order2.status == "ALIVE" or order3.status == "ALIVE": api.wait_update() position = api.get_position("DCE.jd2001") # 测试脚本重新生成后,数据根据实际情况有变化 self.assertEqual( "{'exchange_id': 'DCE', 'instrument_id': 'jd2001', 'pos_long_his': 0, 'pos_long_today': 4, 'pos_short_his': 0, 'pos_short_today': 3, 'volume_long_today': 4, 'volume_long_his': 0, 'volume_long': 4, 'volume_long_frozen_today': 0, 'volume_long_frozen_his': 0, 'volume_long_frozen': 0, 'volume_short_today': 3, 'volume_short_his': 0, 'volume_short': 3, 'volume_short_frozen_today': 0, 'volume_short_frozen_his': 0, 'volume_short_frozen': 0, 'open_price_long': 4193.0, 'open_price_short': 4059.0, 'open_cost_long': 167720.0, 'open_cost_short': 121770.0, 'position_price_long': 4193.0, 'position_price_short': 4059.0, 'position_cost_long': 167720.0, 'position_cost_short': 121770.0, 'float_profit_long': -5320.0, 'float_profit_short': -30.0, 'float_profit': -5350.0, 'position_profit_long': -5320.0, 'position_profit_short': -30.0, 'position_profit': -5350.0, 'margin_long': 11429.6, 'margin_short': 8572.2, 'margin': 20001.800000000003, 'symbol': 'DCE.jd2001', 'last_price': 4060.0}", str(position)) self.assertEqual(1, position.pos) self.assertEqual(4, position.pos_long) self.assertEqual(3, position.pos_short) self.assertEqual(position.exchange_id, "DCE") self.assertEqual(position.instrument_id, "jd2001") self.assertEqual(position.pos_long_his, 0) self.assertEqual(position.pos_long_today, 4) self.assertEqual(position.pos_short_his, 0) self.assertEqual(position.pos_short_today, 3) self.assertEqual(position.volume_long_today, 4) self.assertEqual(position.volume_long_his, 0) self.assertEqual(position.volume_long, 4) self.assertEqual(position.volume_long_frozen_today, 0) self.assertEqual(position.volume_long_frozen_his, 0) self.assertEqual(position.volume_long_frozen, 0) self.assertEqual(position.volume_short_today, 3) self.assertEqual(position.volume_short_his, 0) self.assertEqual(position.volume_short, 3) self.assertEqual(position.volume_short_frozen_today, 0) self.assertEqual(position.volume_short_frozen_his, 0) self.assertEqual(position.volume_short_frozen, 0) self.assertEqual(position.open_price_long, 4193.0) self.assertEqual(position.open_price_short, 4059.0) self.assertEqual(position.open_cost_long, 167720.0) self.assertEqual(position.open_cost_short, 121770.0) self.assertEqual(position.position_price_long, 4193.0) self.assertEqual(position.position_price_short, 4059.0) self.assertEqual(position.position_cost_long, 167720.0) self.assertEqual(position.position_cost_short, 121770.0) self.assertEqual(position.float_profit_long, -5320.0) self.assertEqual(position.float_profit_short, -30.0) self.assertEqual(position.float_profit, -5350.0) self.assertEqual(position.position_profit_long, -5320.0) self.assertEqual(position.position_profit_short, -30.0) self.assertEqual(position.position_profit, -5350.0) self.assertEqual(position.margin_long, 11429.6) self.assertEqual(position.margin_short, 8572.2) self.assertEqual(position.margin, 20001.800000000003) self.assertEqual(position.symbol, "DCE.jd2001") self.assertEqual(position.last_price, 4060.0) # 其他取值方式测试 self.assertEqual(position["pos_long_today"], 4) self.assertEqual(position["pos_short_today"], 3) self.assertEqual(position["volume_long_his"], 0) self.assertEqual(position["volume_long"], 4) api.close()
def test_sim_insert_order_time_check_1(self): """ 模拟交易下单时间判断测试1 测试时间段: 2019.12.2(周一) 21:00 - 25:00 订阅合约的条件: 1. 无夜盘 2. 有夜盘, 在23:00结束 3. 有夜盘, 在25:00结束 测试: 1. 21:00起始时刻两个有夜盘合约下单,无夜盘合约不能下单; 2. 在正常夜盘可下单时段两个有夜盘合约能下单,无夜盘合约不能成; 3. 23:00某一夜盘合约停止交易后不能下单,另一有夜盘合约能下单; """ # 预设服务器端响应 dir_path = os.path.dirname(os.path.realpath(__file__)) self.mock.run(os.path.join(dir_path, "log_file", "test_sim_insert_order_time_check_1.script.lzma")) # 测试 utils.RD = random.Random(4) api = TqApi( backtest=TqBacktest(datetime.datetime(2019, 12, 2, 21, 0, 0), datetime.datetime(2019, 12, 3, 1, 0, 0)), _ins_url=self.ins_url_2019_12_04, _td_url=self.td_url, _md_url=self.md_url) # 2019.12.2周一 symbol1 = "DCE.jd2002" # 无夜盘 symbol2 = "SHFE.rb2002" # 夜盘23点结束 symbol3 = "SHFE.cu2002" # 夜盘凌晨1点结束 quote1 = api.get_quote(symbol1) quote2 = api.get_quote(symbol2) quote3 = api.get_quote(symbol3) position1 = api.get_position(symbol1) position2 = api.get_position(symbol2) position3 = api.get_position(symbol3) try: # 1 回测起始时间(21:00:00)下单 order1 = api.insert_order(symbol=symbol1, direction="BUY", offset="OPEN", volume=1, limit_price=quote1.last_price) order2 = api.insert_order(symbol=symbol2, direction="BUY", offset="OPEN", volume=2, limit_price=quote2.last_price) order3 = api.insert_order(symbol=symbol3, direction="BUY", offset="OPEN", volume=3, limit_price=quote3.last_price) while order1.status != "FINISHED" or order2.status != "FINISHED" or order3.status != "FINISHED": api.wait_update() self.assertEqual(order1.order_id, "8534f45738d048ec0f1099c6c3e1b258") self.assertEqual(order1.direction, 'BUY') self.assertEqual(order1.offset, 'OPEN') self.assertEqual(order1.volume_orign, 1) self.assertEqual(order1.volume_left, 1) self.assertEqual(order1.limit_price, 3963.0) self.assertEqual(order1.price_type, 'LIMIT') self.assertEqual(order1.volume_condition, 'ANY') self.assertEqual(order1.time_condition, 'GFD') self.assertEqual(1575291600000000000, order1.insert_date_time) self.assertEqual(order2.order_id, "c79d679346d4ac7a5c3902b38963dc6e") self.assertEqual(order2.direction, 'BUY') self.assertEqual(order2.offset, 'OPEN') self.assertEqual(order2.volume_orign, 2) self.assertEqual(order2.volume_left, 0) self.assertEqual(order2.limit_price, 3522.0) self.assertEqual(order2.price_type, 'LIMIT') self.assertEqual(order2.volume_condition, 'ANY') self.assertEqual(order2.time_condition, 'GFD') self.assertEqual(1575291600000000000, order2.insert_date_time) self.assertEqual(order3.order_id, "43000de01b2ed40ed3addccb2c33be0a") self.assertEqual(order3.direction, 'BUY') self.assertEqual(order3.offset, 'OPEN') self.assertEqual(order3.volume_orign, 3) self.assertEqual(order3.volume_left, 0) self.assertEqual(order3.limit_price, 47390.0) self.assertEqual(order3.price_type, 'LIMIT') self.assertEqual(order3.volume_condition, 'ANY') self.assertEqual(order3.time_condition, 'GFD') self.assertEqual(1575291600000000000, order3.insert_date_time) # 2 正常夜盘时间下单 while datetime.datetime.strptime(quote3.datetime, "%Y-%m-%d %H:%M:%S.%f") < datetime.datetime(2019, 12, 2, 21, 15): api.wait_update() order1 = api.insert_order(symbol=symbol1, direction="BUY", offset="OPEN", volume=1, limit_price=quote1.last_price) order2 = api.insert_order(symbol=symbol2, direction="BUY", offset="OPEN", volume=2, limit_price=quote2.last_price) order3 = api.insert_order(symbol=symbol3, direction="BUY", offset="OPEN", volume=3, limit_price=quote3.last_price) while order1.status != "FINISHED" or order2.status != "FINISHED" or order3.status != "FINISHED": api.wait_update() self.assertEqual(order1.volume_orign, 1) self.assertEqual(order1.volume_left, 1) self.assertEqual(order2.volume_orign, 2) self.assertEqual(order2.volume_left, 0) self.assertEqual(order3.volume_orign, 3) self.assertEqual(order3.volume_left, 0) self.assertEqual(1575292559999999000, order1.insert_date_time) self.assertEqual(1575292559999999000, order2.insert_date_time) self.assertEqual(1575292559999999000, order3.insert_date_time) # 3 23:00rb2002停止交易后不能下单,cu2002能下单; while datetime.datetime.strptime(quote3.datetime, "%Y-%m-%d %H:%M:%S.%f") < datetime.datetime(2019, 12, 2, 23, 0, 0): api.wait_update() order1 = api.insert_order(symbol=symbol1, direction="BUY", offset="OPEN", volume=1, limit_price=quote1.last_price) order2 = api.insert_order(symbol=symbol2, direction="BUY", offset="OPEN", volume=2, limit_price=quote2.last_price) order3 = api.insert_order(symbol=symbol3, direction="BUY", offset="OPEN", volume=3, limit_price=quote3.last_price) while order1.status != "FINISHED" or order2.status != "FINISHED" or order3.status != "FINISHED": api.wait_update() self.assertEqual(order1.volume_orign, 1) self.assertEqual(order1.volume_left, 1) self.assertEqual(order2.volume_orign, 2) self.assertEqual(order2.volume_left, 2) self.assertEqual(order3.volume_orign, 3) self.assertEqual(order3.volume_left, 0) self.assertEqual(1575298859999999000, order1.insert_date_time) self.assertEqual(1575298859999999000, order2.insert_date_time) self.assertEqual(1575298859999999000, order3.insert_date_time) while True: api.wait_update() except BacktestFinished: self.assertEqual(position1.pos, 0) self.assertEqual(position2.pos, 4) self.assertEqual(position3.pos, 9) api.close()
def test_sim_insert_order_time_check_2(self): """ 模拟交易下单时间判断测试2 测试时间段: 2020.2.17(周一) 10:15 - 10:45 订阅合约的条件: IF、T(无盘中休息时间),cu(有盘中休息时间) 测试: 1. 10:15 - 10:30期间 IF和T能下单,cu不能下单 2. 10:15 - 10:30之间 IF、T能下单 3. 10:30 - 10:45之间 IF、T、cu都能下单 """ # 预设服务器端响应 dir_path = os.path.dirname(os.path.realpath(__file__)) self.mock.run(os.path.join(dir_path, "log_file", "test_sim_insert_order_time_check_2.script.lzma")) # 测试 utils.RD = random.Random(4) api = TqApi( backtest=TqBacktest(datetime.datetime(2020, 2, 17, 10, 15, 0), datetime.datetime(2020, 2, 17, 10, 45, 0)), _ins_url=self.ins_url_2020_02_18, _td_url=self.td_url, _md_url=self.md_url) symbol1 = "SHFE.cu2003" symbol2 = "CFFEX.T2003" symbol3 = "CFFEX.IF2003" quote1 = api.get_quote(symbol1) quote2 = api.get_quote(symbol2) quote3 = api.get_quote(symbol3) position1 = api.get_position(symbol1) position2 = api.get_position(symbol2) position3 = api.get_position(symbol3) try: # 1 10:15 - 10:30期间IF和T能下单,cu不能下单 order1 = api.insert_order(symbol=symbol1, direction="SELL", offset="OPEN", volume=1, limit_price=quote1.last_price) order2 = api.insert_order(symbol=symbol2, direction="BUY", offset="OPEN", volume=2, limit_price=quote2.last_price) order3 = api.insert_order(symbol=symbol3, direction="BUY", offset="OPEN", volume=3, limit_price=quote3.last_price) while order1.status != "FINISHED" or order2.status != "FINISHED" or order3.status != "FINISHED": api.wait_update() self.assertEqual(order1.volume_orign, 1) self.assertEqual(order1.volume_left, 1) self.assertEqual(order2.volume_orign, 2) self.assertEqual(order2.volume_left, 0) self.assertEqual(order3.volume_orign, 3) self.assertEqual(order3.volume_left, 0) self.assertEqual(1581905700000000000, order1.insert_date_time) self.assertEqual(1581905700000000000, order2.insert_date_time) self.assertEqual(1581905700000000000, order3.insert_date_time) # 2 10:15 - 10:30之间 IF、T能下单; while datetime.datetime.strptime(quote3.datetime, "%Y-%m-%d %H:%M:%S.%f") < datetime.datetime(2020, 2, 17, 10, 20): api.wait_update() order1 = api.insert_order(symbol=symbol1, direction="BUY", offset="OPEN", volume=1, limit_price=quote1.last_price) order2 = api.insert_order(symbol=symbol2, direction="BUY", offset="OPEN", volume=2) order3 = api.insert_order(symbol=symbol3, direction="BUY", offset="OPEN", volume=3) while order1.status != "FINISHED" or order2.status != "FINISHED" or order3.status != "FINISHED": api.wait_update() self.assertEqual(order1.volume_orign, 1) self.assertEqual(order1.volume_left, 1) self.assertEqual(order2.volume_orign, 2) self.assertEqual(order2.volume_left, 0) self.assertEqual(order3.volume_orign, 3) self.assertEqual(order3.volume_left, 0) self.assertEqual(1581906059999999000, order1.insert_date_time) self.assertEqual(1581906059999999000, order2.insert_date_time) self.assertEqual(1581906059999999000, order3.insert_date_time) # 3 10:30 - 10:45之间 IF、T、cu都能下单; while datetime.datetime.strptime(quote3.datetime, "%Y-%m-%d %H:%M:%S.%f") < datetime.datetime(2020, 2, 17, 10, 30): api.wait_update() order1 = api.insert_order(symbol=symbol1, direction="BUY", offset="OPEN", volume=1, limit_price=quote1.last_price) order2 = api.insert_order(symbol=symbol2, direction="BUY", offset="OPEN", volume=2) order3 = api.insert_order(symbol=symbol3, direction="BUY", offset="OPEN", volume=3) while order1.status != "FINISHED" or order2.status != "FINISHED" or order3.status != "FINISHED": api.wait_update() self.assertEqual(order1.volume_orign, 1) self.assertEqual(order1.volume_left, 0) self.assertEqual(order2.volume_orign, 2) self.assertEqual(order2.volume_left, 0) self.assertEqual(order3.volume_orign, 3) self.assertEqual(order3.volume_left, 0) self.assertEqual(1581906659999999000, order1.insert_date_time) self.assertEqual(1581906659999999000, order2.insert_date_time) self.assertEqual(1581906659999999000, order3.insert_date_time) while True: api.wait_update() except BacktestFinished: self.assertEqual(position1.pos, 1) self.assertEqual(position2.pos, 6) self.assertEqual(position3.pos, 9) api.close()
def run_tianqin_code(bid, user_id, pwd, td_url): api = TqApi(TqAccount(bid, user_id, pwd), auth="[email protected],MaYanQiong", _stock=True) # api = TqApi(TqAccount(bid, user_id, pwd), auth="[email protected],MaYanQiong", _stock=True) is_ctp = False if bid == "快期模拟" else True account = api.get_account() if bid == "快期模拟": assert account.ctp_balance == '-' or math.isnan(account.ctp_balance) assert account.ctp_available == '-' or math.isnan(account.ctp_available) else: logger.info(f"{account.ctp_balance}, {account.ctp_available}") logger.info(f"{'='*30} 登录成功后,账户初始状态 {'='*30}") positions = api._data["trade"][user_id]["positions"] orders = api._data["trade"][user_id]["orders"] check_orders(orders, api, is_ctp) check_positions(positions, api, is_ctp) check_account(account, positions, is_ctp) logger.info(f"{'='*12} 期权 开仓 {'='*12}") quote = api.get_quote("CZCE.CF009C11600") # ETF 期权 # 挂单 # order = api.insert_order(symbol="SSE.10002513", direction="BUY", offset="OPEN", limit_price=quote.lower_limit + quote.price_tick, volume=2) # 可成交 order = api.insert_order(symbol="CZCE.CF009C11600", direction="BUY", offset="OPEN", limit_price=quote.ask_price1, volume=1) # 可成交 FAK 下单失败,CTP:交易所不支持的价格类型 # order = api.insert_order(symbol="SSE.10002513", direction="BUY", offset="OPEN", limit_price=quote.ask_price1, volume=2, advanced="FAK") # 可成交 FOK # order = api.insert_order(symbol="SSE.10002513", direction="BUY", offset="OPEN", limit_price=quote.ask_price1, volume=2, advanced="FOK") # any_price 通知: 下单失败,CTP:交易所不支持的价格类型 # order = api.insert_order(symbol="SSE.10002513", direction="BUY", offset="OPEN", volume=3) # BEST # order = api.insert_order(symbol="CFFEX.IF2008", direction="BUY", offset="OPEN", limit_price="BEST", volume=3) # BEST FOK 下单失败,已撤单报单被拒绝12038,合约代码:SSE.10002513,下单方向:买,开平标志:开仓,委托价格:最优价,委托手数:3 # order = api.insert_order(symbol="SSE.10002513", direction="BUY", offset="OPEN", limit_price="BEST", volume=3, advanced="FOK") # BEST FOK 成交???? # order = api.insert_order(symbol="SSE.10002513", direction="BUY", offset="OPEN", limit_price="BEST", volume=3, advanced="FOK") # FIVELEVEL 通知: 下单失败,CTP:交易所不支持的价格类型 # order = api.insert_order(symbol="SSE.10002513", direction="BUY", offset="OPEN", limit_price="FIVELEVEL", volume=3) # end = time.time() + 90 # i = 0 # while time.time() < end: # i = i + 1 # print(i) # order = api.insert_order(symbol="SSE.10002513", direction="BUY", offset="OPEN", limit_price="BEST", volume=1) # while order.status == "ALIVE": # api.wait_update() api.wait_update() api.wait_update() api.wait_update() api.wait_update() api.wait_update() check_all(api, bid, user_id) # logger.info(f"{'='*30} 发平仓挂单 {'='*30}") # positions = api._data["trade"][user_id]["positions"] # for pos in positions.values(): # symbol = f"{pos.exchange_id}.{pos.instrument_id}" # quote = api.get_quote(symbol) # if pos.pos_long > 0: # api.insert_order(symbol=symbol, direction="SELL", offset="CLOSE", # limit_price=quote.upper_limit - quote.price_tick, # volume=pos.pos_long) # if pos.pos_short > 0: # api.insert_order(symbol=symbol, direction="BUY", offset="CLOSE", # limit_price=quote.lower_limit + quote.price_tick, # volume=pos.pos_short) # check_all(api, bid, user_id) api.close()
class TianqinClient: """ Client for querying history data from Tianqin. """ def __init__(self): """""" self.inited: bool = False self.symbols: set = set() self.api = None self.username: str = SETTINGS["tqdata.username"] self.password: str = SETTINGS["tqdata.password"] def init(self) -> bool: """""" if self.inited: return True if not self.username or not self.password: return False try: self.api = TqApi(auth=TqAuth(self.username, self.password)) # 获得全部合约 self.symbols = [k for k, v in self.api._data["quotes"].items()] except: return False self.inited = True return True def to_tq_symbol(self, symbol: str, exchange: Exchange) -> str: """ TQSdk exchange first """ for count, word in enumerate(symbol): if word.isdigit(): break # Check for index symbol time_str = symbol[count:] if "88" in time_str: return f"KQ.m@{exchange.value}.{symbol[:count]}" if "99" in time_str: return f"KQ.i@{exchange.value}.{symbol[:count]}" return f"{exchange.value}.{symbol}" def query_history(self, req: HistoryRequest) -> Optional[List[BarData]]: """ Query history bar data from TqSdk. """ symbol = req.symbol exchange = req.exchange interval = req.interval start = req.start end = req.end tq_symbol = self.to_tq_symbol(symbol, exchange) if tq_symbol not in self.symbols: return None tq_interval = INTERVAL_VT2TQ.get(interval) if not tq_interval: return None # For querying night trading period data end += timedelta(1) total_num = int((end - start).total_seconds() / tq_interval) if total_num > 8964: df = self.download_history(start, end, tq_symbol, tq_interval) else: # 只能用来补充最新的数据,无法指定日期 df = self.api.get_kline_serial(tq_symbol, tq_interval, 8000).sort_values(by=["datetime"]) # 时间戳对齐 df["datetime"] = pd.DatetimeIndex( pd.to_datetime(df["datetime"] + TIME_GAP)).tz_localize( 'UTC').tz_convert('Asia/Shanghai') # 过滤开始结束时间 df = df[(df['datetime'] >= start - timedelta(days=1)) & (df['datetime'] < end)] data: List[BarData] = [] if df is not None: for ix, row in df.iterrows(): bar = BarData( symbol=symbol, exchange=exchange, interval=interval, datetime=row["datetime"].to_pydatetime(), open_price=row["open"], high_price=row["high"], low_price=row["low"], close_price=row["close"], volume=row["volume"], open_interest=row.get("open_oi", 0), gateway_name="TQ", ) data.append(bar) return data def download_history(self, start, end, symbol, interval): """ 下载CSV文件回来,并转换成dataframe """ csv_file = "tqdata.csv" status = DataDownloader(api=self.api, symbol_list=[symbol], start_dt=start, end_dt=end, dur_sec=interval, csv_file_name=csv_file) while not status.is_finished(): self.api.wait_update() if os.path.exists(csv_file): df = pd.read_csv(csv_file) df["datetime"] = pd.to_datetime(df["datetime"]) if interval > 0: df = df.rename(columns={f"{symbol}.open": "open"}) df = df.rename(columns={f"{symbol}.high": "high"}) df = df.rename(columns={f"{symbol}.low": "low"}) df = df.rename(columns={f"{symbol}.close": "close"}) df = df.rename(columns={f"{symbol}.volume": "volume"}) df = df.rename(columns={f"{symbol}.open_oi": "open_oi"}) os.unlink(csv_file) return df else: return None
def test_lib_insert_order_time_check_5(self): ''' lib下单时间判断测试5 回测时间: 起始交易日(datetime.date)在非周一 订阅: cu(有夜盘,凌晨1点结束夜盘),rb(夜盘23点结束),jd(无夜盘) 测试: 1 起始回测在21点后rb、cu下单,到第二日9点后jd下单 2 本交易日白盘9:00后jd下单 ''' # 预设服务器端响应 dir_path = os.path.dirname(os.path.realpath(__file__)) self.mock.run( os.path.join(dir_path, "log_file", "test_lib_insert_order_time_check_5.script.lzma")) utils.RD = random.Random(4) api = TqApi(backtest=TqBacktest(datetime.date(2019, 12, 3), datetime.date(2019, 12, 4)), _ins_url=self.ins_url_2019_12_04, _td_url=self.td_url, _md_url=self.md_url) # 2019, 12, 3:周二 symbol1 = "SHFE.cu2002" # 有夜盘,凌晨1点结束夜盘 symbol2 = "SHFE.rb2002" # 夜盘23点结束 symbol3 = "DCE.jd2002" # 无夜盘 quote1 = api.get_quote(symbol1) quote2 = api.get_quote(symbol2) quote3 = api.get_quote(symbol3) position1 = api.get_position(symbol1) position2 = api.get_position(symbol2) position3 = api.get_position(symbol3) target_pos1 = TargetPosTask(api, symbol1) target_pos2 = TargetPosTask(api, symbol2) target_pos3 = TargetPosTask(api, symbol3) orders = api.get_order() try: # 1 起始回测在21点后rb、cu下单,到第二日9点后jd下单 target_pos1.set_target_volume(1) target_pos2.set_target_volume(2) target_pos3.set_target_volume(3) while max(quote1.datetime, quote2.datetime, quote3.datetime) < "2019-12-02 21:05:00.000000": api.wait_update() self.assertEqual(len(orders), 2) self.assertEqual(position1.pos, 1) self.assertEqual(position2.pos, 2) self.assertEqual(position3.pos, 0) # 2 本交易日白盘9:00后jd下单 while max(quote1.datetime, quote2.datetime, quote3.datetime) < "2019-12-03 09:02:00.000000": api.wait_update() self.assertEqual(len(orders), 3) while True: api.wait_update() except BacktestFinished: self.assertEqual(len(orders), 3) self.assertEqual(position1.pos, 1) self.assertEqual(position2.pos, 2) self.assertEqual(position3.pos, 3) api.close()
class doubleMA(): def __init__(self, account, symbol, MA1, MA2, max_value, mini_value, trading_direction, trading_cycle, volume_number): self.account = account #交易账号 self.symbol = symbol #合约代码 self.MA1 = MA1 #小周期 self.MA2 = MA2 #大周期 self.max_value = max_value #震荡区间的最高点 self.mini_value = mini_value #震荡区间的最低点 self.trading_direction = trading_direction #交易方向 1为涨 0为跌 以下均以 1 0 为定义 self.trading_cycle = trading_cycle #交易周期(以分钟记) self.volume_number = volume_number #交易数量 self.position_flag = 0 #持仓标记 self.kline_flag = 0 #K线标记 避免单根K线上多次开仓 self.open_flag = 0 #开仓标记,避免止损点移动 self.api = TqApi(self.account) self.kline = self.api.get_kline_serial(self.symbol, self.trading_cycle * 60, data_length=200) self.position = self.api.get_position(self.symbol) #获得持仓状态 self.sell_list = [] self.buy_list = [] #存放开仓时的两个k线的最高或者最低点,在开仓时记录平仓时清空 def open_json(self): try: fp = open( 'F:\python\PythonApplication1\PythonApplication1\doubleMA.json', 'r') result = json.load(fp) self.buy_list = result['self.buy_list'] self.sell_list = result['self.sell_list'] print('buy_list: ', self.buy_list) print('sell_list: ', self.sell_list) except: print("还没有json") def save_json(self): fp = open( 'F:\python\PythonApplication1\PythonApplication1\doubleMA.json', 'w') save = { 'self.buy_list': self.buy_list, 'self.sell_list': self.sell_list } json.dump(save, fp) def ma(self, daytime): close_list = [] for i in range(1, daytime + 1): close_list.append(self.kline[-i]["close"]) avg = sum(close_list) / daytime return avg def account_trading(self, trading_direction, offset_flag, td_price): if self.position["volume_long"] or self.position["volume_short"] != 0: self.position_flag = 1 if offset_flag == "OPEN": if self.position_flag != 1: self.api.insert_order(symbol=self.symbol, direction=trading_direction, offset=offset_flag, volume=self.volume_number, limit_price=td_price) self.position_flag = 1 if offset_flag == "CLOSE": if self.position_flag == 1: if self.position["volume_long_today"] or self.position[ "volume_short_today"] != 0: self.api.insert_order(symbol=self.symbol, direction=trading_direction, offset="CLOSETODAY", volume=self.volume_number, limit_price=td_price) self.position_flag = 0 elif self.position["volume_long_his"] or self.position[ "volume_short_his"] != 0: self.api.insert_order(symbol=self.symbol, direction=trading_direction, offset="CLOSE", volume=self.volume_number, limit_price=td_price) self.position_flag = 0 def close_buy(self): if self.position_flag == 1: if (self.trading_direction == 1): #平多 while True: self.api.wait_update() if (self.kline[-1]["close"] < self.buy_list[-1]): self.account_trading("SELL", "CLOSE", self.kline[-1]["close"]) self.kline_flag += 1 self.buy_list.clear() self.save_json() self.open_flag -= 1 break if (self.kline[-1]["close"] > self.max_value): break if (self.trading_direction == 0): while True: self.api.wait_update() if (self.kline[-1]["close"] > self.sell_list[-1]): self.account_trading("BUY", "CLOSE", self.kline[-1]["close"]) self.kline_flag += 1 self.open_flag -= 1 self.sell_list.clear() self.save_json() break if (self.kline[-1]["close"] < self.mini_value): break def open_buy(self): if self.position_flag == 0: if (self.trading_direction == 1): #交易方向为涨 if self.kline_flag == 0: while True: self.api.wait_update() ma1 = self.ma(self.MA1) ma2 = self.ma(self.MA2) if (self.kline[-1]["close"] >= self.kline[-2]["high"]): #突破最高点开仓 self.account_trading("BUY", "OPEN", self.kline[-1]["close"]) if self.open_flag == 0: self.buy_list.append(int( self.kline[-1]["low"])) self.buy_list.append(int( self.kline[-2]["low"])) self.buy_list.sort() self.buy_list.pop() #抛弃掉最大的 self.save_json() self.open_flag += 1 self.kline_flag += 1 print("止损点:", self.buy_list[-1]) break if (self.kline[-1]["close"] < self.mini_value) or (ma1 > ma2): break elif (self.trading_direction == 0): #交易方向为跌 if self.kline_flag == 0: while True: self.api.wait_update() ma1 = self.ma(self.MA1) ma2 = self.ma(self.MA2) if (self.kline[-1]["close"] <= self.kline[-2]["low"]): self.account_trading("SELL", "OPEN", self.kline[-1]["close"]) if self.open_flag == 0: self.sell_list.append( int(self.kline[-1]["high"])) self.sell_list.append( int(self.kline[-2]["high"])) self.sell_list.sort(reverse=True) self.sell_list.pop() #抛弃掉最小的 self.open_flag += 1 self.save_json() self.kline_flag += 1 print("止损点:", self.sell_list[-1]) break if (self.kline[-1]["close"] > self.max_value) or (ma1 < ma2): break def star(self): self.open_json() if self.position["volume_long"] or self.position["volume_short"] != 0: self.position_flag = 1 while True: self.api.wait_update() if self.api.is_changing(self.kline[-1], "datetime"): self.kline_flag = 0 #开仓方法 ma1 = self.ma(self.MA1) ma2 = self.ma(self.MA2) if self.trading_direction == 1: #做多 if self.kline[-1]["close"] > self.mini_value and self.kline[ -1]["close"] < self.max_value: if ma2 > ma1: #print('震荡区间中') self.open_buy() self.close_buy() elif self.kline[-1]["close"] < self.mini_value: self.close_buy() break elif self.kline[-1]["close"] > self.max_value: if ma1 < ma2: self.account_trading("SELL", "CLOSE", self.kline[-1]["close"]) break else: self.open_buy() self.close_buy() elif self.trading_direction == 0: #做空 if self.kline[-1]["close"] > self.mini_value and self.kline[ -1]["close"] < self.max_value: if ma1 > ma2: self.open_buy() self.close_buy() elif self.kline[-1]["close"] > self.max_value: self.close_buy() break elif self.kline[-1]["close"] < self.mini_value: if ma1 > ma2: self.account_trading("BUY", "CLOSE", self.kline[-1]["close"]) break else: self.open_buy() self.close_buy() self.api.close()
def test_insert_order_fak(self): """ 下单 """ # 预设服务器端响应 dir_path = os.path.dirname(os.path.realpath(__file__)) self.mock.run( os.path.join( dir_path, "log_file", "test_td_basic_insert_order_fak_simulate.script.lzma")) # 测试: 模拟账户下单 # 非回测, 则需在盘中生成测试脚本: 测试脚本重新生成后,数据根据实际情况有变化,因此需要修改assert语句的内容 utils.RD = random.Random(2) api = TqApi(_ins_url=self.ins_url_2020_05_07, _td_url=self.td_url, _md_url=self.md_url) order1 = api.insert_order("SHFE.au2012", "BUY", "OPEN", 2, limit_price=419, advanced="FAK") order2 = api.insert_order("SHFE.cu2010", "BUY", "OPEN", 2, limit_price=49100, advanced="FAK") while order1.status == "ALIVE" or order2.status == "ALIVE": api.wait_update() self.assertEqual(order1.order_id, "PYSDK_insert_5c6e433715ba2bdd177219d30e7a269f") self.assertEqual(order1.direction, "BUY") self.assertEqual(order1.offset, "OPEN") self.assertEqual(order1.volume_orign, 2) self.assertEqual(order1.volume_left, 0) self.assertEqual(order1.limit_price, 419.0) # 判断nan self.assertEqual(order1.price_type, "LIMIT") self.assertEqual(order1.volume_condition, "ANY") self.assertEqual(order1.time_condition, "IOC") self.assertAlmostEqual(1593671890008459000 / 1e9, order1.insert_date_time / 1e9, places=1) self.assertEqual(order1.status, "FINISHED") for k, v in order1.trade_records.items(): # 模拟交易为一次性全部成交,因此只有一条成交记录 self.assertAlmostEqual(1593671890008850000 / 1e9, v.trade_date_time / 1e9, places=1) del v.trade_date_time self.assertEqual( str(v), "{'order_id': 'PYSDK_insert_5c6e433715ba2bdd177219d30e7a269f', 'trade_id': 'PYSDK_insert_5c6e433715ba2bdd177219d30e7a269f|2', 'exchange_trade_id': 'PYSDK_insert_5c6e433715ba2bdd177219d30e7a269f|2', 'exchange_id': 'SHFE', 'instrument_id': 'au2012', 'direction': 'BUY', 'offset': 'OPEN', 'price': 419.0, 'volume': 2, 'user_id': 'TQSIM', 'commission': 20.0}" ) self.assertEqual(order2.order_id, "PYSDK_insert_cf1822ffbc6887782b491044d5e34124") self.assertEqual(order2.direction, "BUY") self.assertEqual(order2.offset, "OPEN") self.assertEqual(order2.volume_orign, 2) self.assertEqual(order2.volume_left, 2) self.assertEqual(order2.limit_price, 49100.0) self.assertEqual(order2.price_type, "LIMIT") self.assertEqual(order2.volume_condition, "ANY") self.assertEqual(order2.time_condition, "IOC") self.assertAlmostEqual(1593671890009772000 / 1e9, order2.insert_date_time / 1e9, places=1) self.assertEqual(order2.status, "FINISHED") self.assertEqual(len(order2.trade_records.items()), 0) # 没有成交记录 api.close()
def test_insert_order(self): """ 下单 """ # 预设服务器端响应 dir_path = os.path.dirname(os.path.realpath(__file__)) self.mock.run( os.path.join(dir_path, "log_file", "test_td_basic_insert_order_simulate.script.lzma")) # 测试: 模拟账户下单 # 非回测, 则需在盘中生成测试脚本: 测试脚本重新生成后,数据根据实际情况有变化,因此需要修改assert语句的内容 TqApi.RD = random.Random(2) api = TqApi(_ins_url=self.ins_url_2019_07_03, _td_url=self.td_url, _md_url=self.md_url) order1 = api.insert_order("DCE.jd2005", "BUY", "OPEN", 1) order2 = api.insert_order("SHFE.cu2004", "BUY", "OPEN", 2, limit_price=49200) while order1.status == "ALIVE" or order2.status == "ALIVE": api.wait_update() self.assertEqual(order1.order_id, "5c6e433715ba2bdd177219d30e7a269f") self.assertEqual(order1.direction, "BUY") self.assertEqual(order1.offset, "OPEN") self.assertEqual(order1.volume_orign, 1) self.assertEqual(order1.volume_left, 0) self.assertNotEqual(order1.limit_price, order1.limit_price) # 判断nan self.assertEqual(order1.price_type, "ANY") self.assertEqual(order1.volume_condition, "ANY") self.assertEqual(order1.time_condition, "IOC") self.assertAlmostEqual(1584423143664478000 / 1e9, order1.insert_date_time / 1e9, places=1) self.assertEqual(order1.status, "FINISHED") for k, v in order1.trade_records.items(): # 模拟交易为一次性全部成交,因此只有一条成交记录 self.assertAlmostEqual(1584423143664478000 / 1e9, v.trade_date_time / 1e9, places=1) del v.trade_date_time self.assertEqual( str(v), "{'order_id': '5c6e433715ba2bdd177219d30e7a269f', 'trade_id': '5c6e433715ba2bdd177219d30e7a269f|1', 'exchange_trade_id': '5c6e433715ba2bdd177219d30e7a269f|1', 'exchange_id': 'DCE', 'instrument_id': 'jd2005', 'direction': 'BUY', 'offset': 'OPEN', 'price': 3205.0, 'volume': 1, 'user_id': 'TQSIM', 'commission': 6.122999999999999}" ) self.assertEqual(order2.order_id, "cf1822ffbc6887782b491044d5e34124") self.assertEqual(order2.direction, "BUY") self.assertEqual(order2.offset, "OPEN") self.assertEqual(order2.volume_orign, 2) self.assertEqual(order2.volume_left, 0) self.assertEqual(order2.limit_price, 49200.0) self.assertEqual(order2.price_type, "LIMIT") self.assertEqual(order2.volume_condition, "ANY") self.assertEqual(order2.time_condition, "GFD") self.assertAlmostEqual(1584423143666130000 / 1e9, order2.insert_date_time / 1e9, places=1) self.assertEqual(order2.status, "FINISHED") for k, v in order2.trade_records.items(): # 模拟交易为一次性全部成交,因此只有一条成交记录 self.assertAlmostEqual(1584423143666130000 / 1e9, v.trade_date_time / 1e9, places=1) del v.trade_date_time self.assertEqual( str(v), "{'order_id': 'cf1822ffbc6887782b491044d5e34124', 'trade_id': 'cf1822ffbc6887782b491044d5e34124|2', 'exchange_trade_id': 'cf1822ffbc6887782b491044d5e34124|2', 'exchange_id': 'SHFE', 'instrument_id': 'cu2004', 'direction': 'BUY', 'offset': 'OPEN', 'price': 49200.0, 'volume': 2, 'user_id': 'TQSIM', 'commission': 23.189999999999998}" ) api.close()
def test_sim_insert_order_time_check_3(self): """ 模拟交易下单时间判断测试3 测试时间段: 2020.2.17(周一) 10:29:29 - 15:18 订阅合约条件: IF、T(无盘中休息时间),cu(有盘中休息时间) 测试: 1. 10:29:29 IF、T能下单, cu不能下单 2. 10:30 之后都能下单 3. 11:29:29.999999 能下单 4. 13:00 之后T、IF能下单,cu不能下单 5. 13:30 之后都能下单 6. 15:00 - 15:15 : T能下单,IF、cu不能下单; 7. 15:14:59 只有T2003能下单 """ # 预设服务器端响应 dir_path = os.path.dirname(os.path.realpath(__file__)) self.mock.run(os.path.join(dir_path, "log_file", "test_sim_insert_order_time_check_3.script.lzma")) # 测试 utils.RD = random.Random(4) api = TqApi( backtest=TqBacktest(datetime.datetime(2020, 2, 17, 10, 29, 29), datetime.datetime(2020, 2, 17, 15, 18, 0)), _ins_url=self.ins_url_2020_02_18) # 2019.12.2周一 symbol1 = "SHFE.cu2003" symbol2 = "CFFEX.T2003" symbol3 = "CFFEX.IF2003" quote1 = api.get_quote(symbol1) quote2 = api.get_quote(symbol2) quote3 = api.get_quote(symbol3) position1 = api.get_position(symbol1) position2 = api.get_position(symbol2) position3 = api.get_position(symbol3) try: # 1 10:29:29 IF、T能下单, cu不能下单 order1 = api.insert_order(symbol=symbol1, direction="SELL", offset="OPEN", volume=1, limit_price=quote1.last_price) order2 = api.insert_order(symbol=symbol2, direction="BUY", offset="OPEN", volume=2, limit_price=quote2.last_price) order3 = api.insert_order(symbol=symbol3, direction="BUY", offset="OPEN", volume=3, limit_price=quote3.last_price) while order1.status != "FINISHED" or order2.status != "FINISHED" or order3.status != "FINISHED": api.wait_update() self.assertEqual(order1.volume_orign, 1) self.assertEqual(order1.volume_left, 1) self.assertEqual(order2.volume_orign, 2) self.assertEqual(order2.volume_left, 0) self.assertEqual(order3.volume_orign, 3) self.assertEqual(order3.volume_left, 0) self.assertEqual(1581906569000000000, order1.insert_date_time) self.assertEqual(1581906569000000000, order2.insert_date_time) self.assertEqual(1581906569000000000, order3.insert_date_time) # 2 10:30 之后都能下单; while max(quote1.datetime, quote2.datetime, quote3.datetime) < "2020-02-17 10:30:00.000000": api.wait_update() order1 = api.insert_order(symbol=symbol1, direction="SELL", offset="OPEN", volume=1, limit_price=quote1.last_price) order2 = api.insert_order(symbol=symbol2, direction="BUY", offset="OPEN", volume=2, limit_price=quote2.last_price) order3 = api.insert_order(symbol=symbol3, direction="BUY", offset="OPEN", volume=3, limit_price=quote3.last_price) while order1.status != "FINISHED" or order2.status != "FINISHED" or order3.status != "FINISHED": api.wait_update() self.assertEqual(order1.volume_orign, 1) self.assertEqual(order1.volume_left, 0) self.assertEqual(order2.volume_orign, 2) self.assertEqual(order2.volume_left, 0) self.assertEqual(order3.volume_orign, 3) self.assertEqual(order3.volume_left, 0) self.assertEqual(1581906659999999000, order1.insert_date_time) self.assertEqual(1581906659999999000, order2.insert_date_time) self.assertEqual(1581906659999999000, order3.insert_date_time) # 3 11:29:29.999999 能下单 while max(quote1.datetime, quote2.datetime, quote3.datetime) != "2020-02-17 11:29:59.999999": api.wait_update() order1 = api.insert_order(symbol=symbol1, direction="SELL", offset="OPEN", volume=1, limit_price=quote1.bid_price1) # 使用quote1.bid_price1使其立即成交 order2 = api.insert_order(symbol=symbol2, direction="BUY", offset="OPEN", volume=2, limit_price=quote2.last_price) order3 = api.insert_order(symbol=symbol3, direction="BUY", offset="OPEN", volume=3, limit_price=quote3.last_price) while order1.status != "FINISHED" or order2.status != "FINISHED" or order3.status != "FINISHED": api.wait_update() self.assertEqual(order1.volume_orign, 1) self.assertEqual(order1.volume_left, 0) self.assertEqual(order2.volume_orign, 2) self.assertEqual(order2.volume_left, 0) self.assertEqual(order3.volume_orign, 3) self.assertEqual(order3.volume_left, 0) self.assertEqual(1581910199999999000, order1.insert_date_time) self.assertEqual(1581910199999999000, order2.insert_date_time) self.assertEqual(1581910199999999000, order3.insert_date_time) # 4 13:00 之后T、IF能下单,cu不能下单 while max(quote1.datetime, quote2.datetime, quote3.datetime) < "2020-02-17 13:00:00.000000": api.wait_update() order1 = api.insert_order(symbol=symbol1, direction="SELL", offset="OPEN", volume=1, limit_price=quote1.last_price) order2 = api.insert_order(symbol=symbol2, direction="BUY", offset="OPEN", volume=2, limit_price=quote2.last_price) order3 = api.insert_order(symbol=symbol3, direction="BUY", offset="OPEN", volume=3, limit_price=quote3.last_price) while order1.status != "FINISHED" or order2.status != "FINISHED" or order3.status != "FINISHED": api.wait_update() self.assertEqual(order1.volume_orign, 1) self.assertEqual(order1.volume_left, 1) self.assertEqual(order2.volume_orign, 2) self.assertEqual(order2.volume_left, 0) self.assertEqual(order3.volume_orign, 3) self.assertEqual(order3.volume_left, 0) self.assertEqual(1581915839999999000, order1.insert_date_time) self.assertEqual(1581915839999999000, order2.insert_date_time) self.assertEqual(1581915839999999000, order3.insert_date_time) # 5 13:30 之后都能下单 while max(quote1.datetime, quote2.datetime, quote3.datetime) < "2020-02-17 13:30:00.000000": api.wait_update() order1 = api.insert_order(symbol=symbol1, direction="SELL", offset="OPEN", volume=1, limit_price=quote1.last_price) order2 = api.insert_order(symbol=symbol2, direction="BUY", offset="OPEN", volume=2, limit_price=quote2.last_price) order3 = api.insert_order(symbol=symbol3, direction="BUY", offset="OPEN", volume=3, limit_price=quote3.last_price) while order1.status != "FINISHED" or order2.status != "FINISHED" or order3.status != "FINISHED": api.wait_update() self.assertEqual(order1.volume_orign, 1) self.assertEqual(order1.volume_left, 0) self.assertEqual(order2.volume_orign, 2) self.assertEqual(order2.volume_left, 0) self.assertEqual(order3.volume_orign, 3) self.assertEqual(order3.volume_left, 0) self.assertEqual(1581917459999999000, order1.insert_date_time) self.assertEqual(1581917459999999000, order2.insert_date_time) self.assertEqual(1581917459999999000, order3.insert_date_time) # 6 15:00 - 15:15 : T能下单,IF、cu不能下单; while max(quote1.datetime, quote2.datetime, quote3.datetime) < "2020-02-17 15:00:00.000000": api.wait_update() order1 = api.insert_order(symbol=symbol1, direction="SELL", offset="OPEN", volume=1, limit_price=quote1.last_price) order2 = api.insert_order(symbol=symbol2, direction="BUY", offset="OPEN", volume=2, limit_price=quote2.last_price) order3 = api.insert_order(symbol=symbol3, direction="BUY", offset="OPEN", volume=3, limit_price=quote3.last_price) while order1.status != "FINISHED" or order2.status != "FINISHED" or order3.status != "FINISHED": api.wait_update() self.assertEqual(order1.volume_orign, 1) self.assertEqual(order1.volume_left, 1) self.assertEqual(order2.volume_orign, 2) self.assertEqual(order2.volume_left, 0) self.assertEqual(order3.volume_orign, 3) self.assertEqual(order3.volume_left, 3) self.assertEqual(1581922859999999000, order1.insert_date_time) self.assertEqual(1581922859999999000, order2.insert_date_time) self.assertEqual(1581922859999999000, order3.insert_date_time) # 7 15:14:59 只有T2003能下单 while max(quote1.datetime, quote2.datetime, quote3.datetime) != "2020-02-17 15:14:59.999999": api.wait_update() order1 = api.insert_order(symbol=symbol1, direction="SELL", offset="OPEN", volume=1, limit_price=quote1.last_price) order2 = api.insert_order(symbol=symbol2, direction="BUY", offset="OPEN", volume=2) order3 = api.insert_order(symbol=symbol3, direction="BUY", offset="OPEN", volume=3) while order1.status != "FINISHED" or order2.status != "FINISHED" or order3.status != "FINISHED": api.wait_update() self.assertEqual(order1.volume_orign, 1) self.assertEqual(order1.volume_left, 1) self.assertEqual(order2.volume_orign, 2) self.assertEqual(order2.volume_left, 0) self.assertEqual(order3.volume_orign, 3) self.assertEqual(order3.volume_left, 3) self.assertEqual(1581923699999999000, order1.insert_date_time) self.assertEqual(1581923699999999000, order2.insert_date_time) self.assertEqual(1581923699999999000, order3.insert_date_time) while True: api.wait_update() except BacktestFinished: self.assertEqual(position1.pos, -3) self.assertEqual(position2.pos, 14) self.assertEqual(position3.pos, 15) api.close()
def test_insert_order_option(self): """ 期权下单 """ # 预设服务器端响应 dir_path = os.path.dirname(os.path.realpath(__file__)) self.mock.run( os.path.join( dir_path, "log_file", "test_td_basic_insert_order_simulate_option.script.lzma")) # 测试: 模拟账户下单 # 非回测, 则需在盘中生成测试脚本: 测试脚本重新生成后,数据根据实际情况有变化,因此需要修改assert语句的内容 TqApi.RD = random.Random(2) api = TqApi(_ins_url=self.ins_url_2020_04_02, _td_url=self.td_url, _md_url=self.md_url) order1 = api.insert_order("SHFE.cu2006C47000", "BUY", "OPEN", 1, limit_price=135) order2 = api.insert_order("CZCE.SR007C5600", "SELL", "OPEN", 2, limit_price=30) order3 = api.insert_order("DCE.m2007-P-2900", "BUY", "OPEN", 3, limit_price=192) while order1.status == "ALIVE" or order2.status == "ALIVE" or order3.status == "ALIVE": api.wait_update() self.assertEqual(order1.order_id, "5c6e433715ba2bdd177219d30e7a269f") self.assertEqual(order1.direction, "BUY") self.assertEqual(order1.offset, "OPEN") self.assertEqual(order1.volume_orign, 1) self.assertEqual(order1.volume_left, 0) self.assertEqual(order1.limit_price, 135.0) self.assertEqual(order1.price_type, "LIMIT") self.assertEqual(order1.volume_condition, "ANY") self.assertEqual(order1.time_condition, "GFD") self.assertAlmostEqual(1586829882005334000 / 1e9, order1.insert_date_time / 1e9, places=1) self.assertEqual(order1.status, "FINISHED") for k, v in order1.trade_records.items(): # 模拟交易为一次性全部成交,因此只有一条成交记录 self.assertAlmostEqual(1586829882005979000 / 1e9, v.trade_date_time / 1e9, places=1) del v.trade_date_time self.assertEqual( str(v), "{'order_id': '5c6e433715ba2bdd177219d30e7a269f', 'trade_id': '5c6e433715ba2bdd177219d30e7a269f|1', 'exchange_trade_id': '5c6e433715ba2bdd177219d30e7a269f|1', 'exchange_id': 'SHFE', 'instrument_id': 'cu2006C47000', 'direction': 'BUY', 'offset': 'OPEN', 'price': 135.0, 'volume': 1, 'user_id': 'TQSIM', 'commission': 10}" ) self.assertEqual(order2.order_id, "cf1822ffbc6887782b491044d5e34124") self.assertEqual(order2.direction, "SELL") self.assertEqual(order2.offset, "OPEN") self.assertEqual(order2.volume_orign, 2) self.assertEqual(order2.volume_left, 0) self.assertEqual(order2.limit_price, 30.0) self.assertEqual(order2.price_type, "LIMIT") self.assertEqual(order2.volume_condition, "ANY") self.assertEqual(order2.time_condition, "GFD") self.assertAlmostEqual(1586829882236154000 / 1e9, order2.insert_date_time / 1e9, places=1) self.assertEqual(order2.status, "FINISHED") for k, v in order2.trade_records.items(): # 模拟交易为一次性全部成交,因此只有一条成交记录 self.assertAlmostEqual(1586829882236518000 / 1e9, v.trade_date_time / 1e9, places=1) del v.trade_date_time self.assertEqual( str(v), "{'order_id': 'cf1822ffbc6887782b491044d5e34124', 'trade_id': 'cf1822ffbc6887782b491044d5e34124|2', 'exchange_trade_id': 'cf1822ffbc6887782b491044d5e34124|2', 'exchange_id': 'CZCE', 'instrument_id': 'SR007C5600', 'direction': 'SELL', 'offset': 'OPEN', 'price': 30.0, 'volume': 2, 'user_id': 'TQSIM', 'commission': 20}" ) self.assertEqual(order3.order_id, "4067c3584ee207f8da94e3e8ab73738f") self.assertEqual(order3.direction, "BUY") self.assertEqual(order3.offset, "OPEN") self.assertEqual(order3.volume_orign, 3) self.assertEqual(order3.volume_left, 0) self.assertEqual(order3.limit_price, 192.0) self.assertEqual(order3.price_type, "LIMIT") self.assertEqual(order3.volume_condition, "ANY") self.assertEqual(order3.time_condition, "GFD") self.assertAlmostEqual(1586829882228039000 / 1e9, order3.insert_date_time / 1e9, places=1) self.assertEqual(order3.status, "FINISHED") for k, v in order3.trade_records.items(): # 模拟交易为一次性全部成交,因此只有一条成交记录 self.assertAlmostEqual(1586829882228603000 / 1e9, v.trade_date_time / 1e9, places=1) del v.trade_date_time self.assertEqual( str(v), "{'order_id': '4067c3584ee207f8da94e3e8ab73738f', 'trade_id': '4067c3584ee207f8da94e3e8ab73738f|3', 'exchange_trade_id': '4067c3584ee207f8da94e3e8ab73738f|3', 'exchange_id': 'DCE', 'instrument_id': 'm2007-P-2900', 'direction': 'BUY', 'offset': 'OPEN', 'price': 192.0, 'volume': 3, 'user_id': 'TQSIM', 'commission': 30}" ) api.close()
def test_sim_insert_order_time_check_4(self): """ 模拟交易下单时间判断测试4 测试时间段: 交易日(datetime.date)为周一, 夜盘从周五21点到周六凌晨1点 订阅合约: cu(有夜盘,凌晨1点结束夜盘), rb(夜盘23点结束), jd(无夜盘) 测试: 1. 回测刚开始:current_datetime 为 18:00 , 都无法下单 2. 周五晚21:00之后: cu和rb能下单 3. 周五23点到周六凌晨1点前:cu能下单 4. 周一早9点后都能下单 5. 周一晚21点后cu和rb能下单 """ # 预设服务器端响应 dir_path = os.path.dirname(os.path.realpath(__file__)) self.mock.run(os.path.join(dir_path, "log_file", "test_sim_insert_order_time_check_4.script.lzma")) utils.RD = random.Random(4) api = TqApi(backtest=TqBacktest(datetime.date(2019, 12, 2), datetime.date(2019, 12, 3)), _ins_url=self.ins_url_2019_12_04) symbol1 = "SHFE.cu2002" # 有夜盘,凌晨1点结束夜盘 symbol2 = "SHFE.rb2002" # 夜盘23点结束 symbol3 = "DCE.jd2002" # 无夜盘 quote1 = api.get_quote(symbol1) quote2 = api.get_quote(symbol2) quote3 = api.get_quote(symbol3) position1 = api.get_position(symbol1) position2 = api.get_position(symbol2) position3 = api.get_position(symbol3) try: # 1 回测刚开始:current_datetime 为 18:00 , 都无法下单 order1 = api.insert_order(symbol=symbol1, direction="SELL", offset="OPEN", volume=1, limit_price=quote1.last_price) order2 = api.insert_order(symbol=symbol2, direction="BUY", offset="OPEN", volume=2, limit_price=quote2.last_price) order3 = api.insert_order(symbol=symbol3, direction="BUY", offset="OPEN", volume=3, limit_price=quote3.last_price) while order1.status != "FINISHED" or order2.status != "FINISHED" or order3.status != "FINISHED": api.wait_update() self.assertEqual(order1.volume_orign, 1) self.assertEqual(order1.volume_left, 1) self.assertEqual(order2.volume_orign, 2) self.assertEqual(order2.volume_left, 2) self.assertEqual(order3.volume_orign, 3) self.assertEqual(order3.volume_left, 3) self.assertEqual(1575021600000000000, order1.insert_date_time) self.assertEqual(1575021600000000000, order2.insert_date_time) self.assertEqual(1575021600000000000, order3.insert_date_time) # 2 周五晚21:00之后: cu和rb能下单 while max(quote1.datetime, quote2.datetime, quote3.datetime) < "2019-11-29 21:00:00.000000": api.wait_update() order1 = api.insert_order(symbol=symbol1, direction="SELL", offset="OPEN", volume=1, limit_price=quote1.last_price) order2 = api.insert_order(symbol=symbol2, direction="BUY", offset="OPEN", volume=2, limit_price=quote2.last_price) order3 = api.insert_order(symbol=symbol3, direction="BUY", offset="OPEN", volume=3, limit_price=quote3.last_price) while order1.status != "FINISHED" or order2.status != "FINISHED" or order3.status != "FINISHED": api.wait_update() self.assertEqual(order1.volume_orign, 1) self.assertEqual(order1.volume_left, 0) self.assertEqual(order2.volume_orign, 2) self.assertEqual(order2.volume_left, 0) self.assertEqual(order3.volume_orign, 3) self.assertEqual(order3.volume_left, 3) self.assertEqual(1575032459999999000, order1.insert_date_time) self.assertEqual(1575032459999999000, order2.insert_date_time) self.assertEqual(1575032459999999000, order3.insert_date_time) # 3 周六凌晨1点前:cu能下单 while max(quote1.datetime, quote2.datetime, quote3.datetime) < "2019-11-30 00:01:00.000000": api.wait_update() order1 = api.insert_order(symbol=symbol1, direction="SELL", offset="OPEN", volume=1, limit_price=quote1.last_price) order2 = api.insert_order(symbol=symbol2, direction="BUY", offset="OPEN", volume=2, limit_price=quote2.last_price) order3 = api.insert_order(symbol=symbol3, direction="BUY", offset="OPEN", volume=3, limit_price=quote3.last_price) while order1.status != "FINISHED" or order2.status != "FINISHED" or order3.status != "FINISHED": api.wait_update() self.assertEqual(order1.volume_orign, 1) self.assertEqual(order1.volume_left, 0) self.assertEqual(order2.volume_orign, 2) self.assertEqual(order2.volume_left, 2) self.assertEqual(order3.volume_orign, 3) self.assertEqual(order3.volume_left, 3) self.assertEqual(1575043319999999000, order1.insert_date_time) self.assertEqual(1575043319999999000, order2.insert_date_time) self.assertEqual(1575043319999999000, order3.insert_date_time) # 4 周一早9点后都能下单 while max(quote1.datetime, quote2.datetime, quote3.datetime) < "2019-12-02 09:00:00.000000": api.wait_update() order1 = api.insert_order(symbol=symbol1, direction="SELL", offset="OPEN", volume=1, limit_price=quote1.last_price) order2 = api.insert_order(symbol=symbol2, direction="BUY", offset="OPEN", volume=2, limit_price=quote2.last_price) order3 = api.insert_order(symbol=symbol3, direction="BUY", offset="OPEN", volume=3, limit_price=quote3.last_price) while order1.status != "FINISHED" or order2.status != "FINISHED" or order3.status != "FINISHED": api.wait_update() self.assertEqual(order1.volume_orign, 1) self.assertEqual(order1.volume_left, 0) self.assertEqual(order2.volume_orign, 2) self.assertEqual(order2.volume_left, 0) self.assertEqual(order3.volume_orign, 3) self.assertEqual(order3.volume_left, 0) self.assertEqual(1575248459999999000, order1.insert_date_time) self.assertEqual(1575248459999999000, order2.insert_date_time) self.assertEqual(1575248459999999000, order3.insert_date_time) # 5 周一晚21点后cu和rb能下单 while max(quote1.datetime, quote2.datetime, quote3.datetime) < "2019-12-02 21:00:00.000000": api.wait_update() order1 = api.insert_order(symbol=symbol1, direction="BUY", offset="OPEN", volume=1, limit_price=quote1.last_price) order2 = api.insert_order(symbol=symbol2, direction="BUY", offset="OPEN", volume=2, limit_price=quote2.last_price) order3 = api.insert_order(symbol=symbol3, direction="BUY", offset="OPEN", volume=3, limit_price=quote3.last_price) while order1.status != "FINISHED" or order2.status != "FINISHED" or order3.status != "FINISHED": api.wait_update() self.assertEqual(order1.volume_orign, 1) self.assertEqual(order1.volume_left, 0) self.assertEqual(order2.volume_orign, 2) self.assertEqual(order2.volume_left, 0) self.assertEqual(order3.volume_orign, 3) self.assertEqual(order3.volume_left, 3) self.assertEqual(1575291659999999000, order1.insert_date_time) self.assertEqual(1575291659999999000, order2.insert_date_time) self.assertEqual(1575291659999999000, order3.insert_date_time) while True: api.wait_update() except BacktestFinished: self.assertEqual(position1.pos, -2) self.assertEqual(position2.pos, 6) self.assertEqual(position3.pos, 3) api.close()
def run_tianqin_code(bid, user_id, pwd, td_url): api = TqApi(TqAccount(bid, user_id, pwd), auth="[email protected],MaYanQiong", _td_url=td_url) is_ctp = False if bid == "快期模拟" else True account = api.get_account() if bid == "快期模拟": assert account.ctp_balance == '-' or math.isnan(account.ctp_balance) assert account.ctp_available == '-' or math.isnan( account.ctp_available) else: logger.info(f"{account.ctp_balance}, {account.ctp_available}") logger.info(f"{'='*30} 登录成功后,账户初始状态 {'='*30}") positions = api._data["trade"][user_id]["positions"] orders = api._data["trade"][user_id]["orders"] check_orders(orders, api, is_ctp) check_positions(positions, api, is_ctp) check_account(account, positions, is_ctp) logger.info(f"{'='*30} 全部撤单 & 全部平仓 {'='*30}") for order in orders.values(): if order.status != "FINISHED": api.cancel_order(order) for pos in positions.values(): symbol = f"{pos.exchange_id}.{pos.instrument_id}" quote = api.get_quote(symbol) if pos.pos_long > 0: api.insert_order(symbol=symbol, direction="SELL", offset="CLOSE", limit_price=quote.bid_price1, volume=pos.pos_long) if pos.pos_short > 0: api.insert_order(symbol=symbol, direction="BUY", offset="CLOSE", limit_price=quote.ask_price1, volume=pos.pos_short) while True: api.wait_update(deadline=time.time() + 30) # 全部持仓清 0 is_all_clear = True for pos in positions.values(): if pos.pos_long > 0 or pos.pos_short > 0: is_all_clear = False for order in orders.values(): if order.status != "FINISHED": is_all_clear = False if is_all_clear: logger.info("全部撤单 & 全部平仓 ok") break else: logger.info("还没完成全部撤单 & 全部平仓") logger.info(f"{'='*12} 期货 开仓 {'='*12}") quote = api.get_quote("CZCE.RM105") api.insert_order(symbol="CZCE.RM105", direction="BUY", offset="OPEN", limit_price=quote.lower_limit + quote.price_tick, volume=2) api.insert_order(symbol="CZCE.RM105", direction="BUY", offset="OPEN", limit_price=quote.ask_price1, volume=3) quote1 = api.get_quote("CZCE.CF105") api.insert_order(symbol="CZCE.CF105", direction="SELL", offset="OPEN", limit_price=quote1.upper_limit - quote1.price_tick, volume=2) api.insert_order(symbol="CZCE.CF105", direction="SELL", offset="OPEN", limit_price=quote1.bid_price1, volume=3) check_all(api, bid, user_id) # logger.info(f"{'='*12} 期权 开仓 {'='*12}") # quote = api.get_quote("CZCE.RM009C2300") # api.insert_order(symbol="CZCE.RM009C2300", direction="BUY", offset="OPEN", # limit_price=quote.lower_limit + quote.price_tick, # volume=2) # api.insert_order(symbol="CZCE.RM009C2300", direction="BUY", offset="OPEN", limit_price=quote.ask_price1, # volume=3) # quote1 = api.get_quote("CZCE.CF009C11600") # api.insert_order(symbol="CZCE.CF009C11600", direction="SELL", offset="OPEN", # limit_price=quote1.upper_limit - quote1.price_tick, # volume=2) # api.insert_order(symbol="CZCE.CF009C11600", direction="SELL", offset="OPEN", limit_price=quote1.bid_price1, # volume=3) # # quote2 = api.get_quote("CZCE.RM009P2300") # api.insert_order(symbol="CZCE.RM009P2300", direction="BUY", offset="OPEN", # limit_price=quote2.lower_limit + quote2.price_tick, # volume=2) # api.insert_order(symbol="CZCE.RM009P2300", direction="BUY", offset="OPEN", limit_price=quote2.ask_price1, # volume=3) # quote3 = api.get_quote("CZCE.CF009C11600") # api.insert_order(symbol="CZCE.CF009P11600", direction="SELL", offset="OPEN", # limit_price=quote3.upper_limit - quote3.price_tick, # volume=2) # api.insert_order(symbol="CZCE.CF009P11600", direction="SELL", offset="OPEN", limit_price=quote3.bid_price1, # volume=3) # PUT # check_all(api, bid, user_id) # logger.info(f"{'='*30} 发平仓挂单 {'='*30}") # positions = api._data["trade"][user_id]["positions"] # for pos in positions.values(): # symbol = f"{pos.exchange_id}.{pos.instrument_id}" # quote = api.get_quote(symbol) # if pos.pos_long > 0: # api.insert_order(symbol=symbol, direction="SELL", offset="CLOSE", # limit_price=quote.upper_limit - quote.price_tick, # volume=pos.pos_long) # if pos.pos_short > 0: # api.insert_order(symbol=symbol, direction="BUY", offset="CLOSE", # limit_price=quote.lower_limit + quote.price_tick, # volume=pos.pos_short) # check_all(api, bid, user_id) api.close()
def test_sim_insert_order_time_check_5(self): """ 模拟交易下单时间判断测试5 测试时间段: 交易日(datetime.date)在非周一,订阅有夜盘合约,判断其可交易时间段 合约: cu(有夜盘,凌晨1点结束夜盘), rb(夜盘23点结束), jd(无夜盘) 测试: 1 回测刚开始:current_datetime 为 18:00 , 都无法下单 2 前一日21点以后rb、cu能下单 3 本交易日9:00后都能下单 """ # 预设服务器端响应 dir_path = os.path.dirname(os.path.realpath(__file__)) self.mock.run(os.path.join(dir_path, "log_file", "test_sim_insert_order_time_check_5.script.lzma")) utils.RD = random.Random(4) api = TqApi(backtest=TqBacktest(datetime.date(2019, 12, 3), datetime.date(2019, 12, 4)), _ins_url=self.ins_url_2019_12_04) symbol1 = "SHFE.cu2002" # 有夜盘,凌晨1点结束夜盘 symbol2 = "SHFE.rb2002" # 夜盘23点结束 symbol3 = "DCE.jd2002" # 无夜盘 quote1 = api.get_quote(symbol1) quote2 = api.get_quote(symbol2) quote3 = api.get_quote(symbol3) position1 = api.get_position(symbol1) position2 = api.get_position(symbol2) position3 = api.get_position(symbol3) try: # 1 回测刚开始:current_datetime 为 18:00 , 都无法下单 order1 = api.insert_order(symbol=symbol1, direction="SELL", offset="OPEN", volume=1, limit_price=quote1.last_price) order2 = api.insert_order(symbol=symbol2, direction="BUY", offset="OPEN", volume=2, limit_price=quote2.last_price) order3 = api.insert_order(symbol=symbol3, direction="BUY", offset="OPEN", volume=3, limit_price=quote3.last_price) while order1.status != "FINISHED" or order2.status != "FINISHED" or order3.status != "FINISHED": api.wait_update() self.assertEqual(order1.volume_orign, 1) self.assertEqual(order1.volume_left, 1) self.assertEqual(order2.volume_orign, 2) self.assertEqual(order2.volume_left, 2) self.assertEqual(order3.volume_orign, 3) self.assertEqual(order3.volume_left, 3) self.assertEqual(1575280800000000000, order1.insert_date_time) self.assertEqual(1575280800000000000, order2.insert_date_time) self.assertEqual(1575280800000000000, order3.insert_date_time) # 2 前一日21点以后rb、cu能下单 while max(quote1.datetime, quote2.datetime, quote3.datetime) < "2019-12-02 21:00:00.000000": api.wait_update() order1 = api.insert_order(symbol=symbol1, direction="BUY", offset="OPEN", volume=1, limit_price=quote1.last_price) order2 = api.insert_order(symbol=symbol2, direction="BUY", offset="OPEN", volume=2, limit_price=quote2.last_price) order3 = api.insert_order(symbol=symbol3, direction="BUY", offset="OPEN", volume=3, limit_price=quote3.last_price) while order1.status != "FINISHED" or order2.status != "FINISHED" or order3.status != "FINISHED": api.wait_update() self.assertEqual(order1.volume_orign, 1) self.assertEqual(order1.volume_left, 0) self.assertEqual(order2.volume_orign, 2) self.assertEqual(order2.volume_left, 0) self.assertEqual(order3.volume_orign, 3) self.assertEqual(order3.volume_left, 3) self.assertEqual(1575291659999999000, order1.insert_date_time) self.assertEqual(1575291659999999000, order2.insert_date_time) self.assertEqual(1575291659999999000, order3.insert_date_time) # 3 本交易日9:00后都能下单 while max(quote1.datetime, quote2.datetime, quote3.datetime) < "2019-12-03 09:00:00.000000": api.wait_update() order1 = api.insert_order(symbol=symbol1, direction="BUY", offset="OPEN", volume=1, limit_price=quote1.last_price) order2 = api.insert_order(symbol=symbol2, direction="BUY", offset="OPEN", volume=2, limit_price=quote2.last_price) order3 = api.insert_order(symbol=symbol3, direction="BUY", offset="OPEN", volume=3, limit_price=quote3.last_price) while order1.status != "FINISHED" or order2.status != "FINISHED" or order3.status != "FINISHED": api.wait_update() self.assertEqual(order1.volume_orign, 1) self.assertEqual(order1.volume_left, 0) self.assertEqual(order2.volume_orign, 2) self.assertEqual(order2.volume_left, 0) self.assertEqual(order3.volume_orign, 3) self.assertEqual(order3.volume_left, 0) self.assertEqual(1575334859999999000, order1.insert_date_time) self.assertEqual(1575334859999999000, order2.insert_date_time) self.assertEqual(1575334859999999000, order3.insert_date_time) while True: api.wait_update() except BacktestFinished: self.assertEqual(position1.pos, 2) self.assertEqual(position2.pos, 4) self.assertEqual(position3.pos, 3) api.close()
def test_get_order(self): """ 获取委托单信息 """ # 预设服务器端响应 dir_path = os.path.dirname(os.path.realpath(__file__)) self.mock.run( os.path.join(dir_path, "log_file", "test_td_basic_get_order_simulate.script.lzma")) # 测试: 模拟账户下单 TqApi.RD = random.Random(4) api = TqApi(_ins_url=self.ins_url, _td_url=self.td_url, _md_url=self.md_url) order1 = api.insert_order("DCE.jd2001", "BUY", "OPEN", 1) order2 = api.insert_order("SHFE.cu2001", "SELL", "OPEN", 2, limit_price=47040) while order1.status == "ALIVE" or order2.status == "ALIVE": api.wait_update() get_order1 = api.get_order(order1.order_id) get_order2 = api.get_order(order2.order_id) self.assertEqual( str(get_order1), "{'order_id': '1710cf5327ac435a7a97c643656412a9', 'exchange_order_id': '1710cf5327ac435a7a97c643656412a9', 'exchange_id': 'DCE', 'instrument_id': 'jd2001', 'direction': 'BUY', 'offset': 'OPEN', 'volume_orign': 1, 'volume_left': 0, 'limit_price': nan, 'price_type': 'ANY', 'volume_condition': 'ANY', 'time_condition': 'IOC', 'insert_date_time': 631123200000000000, 'last_msg': '全部成交', 'status': 'FINISHED', 'user_id': 'TQSIM', 'symbol': 'DCE.jd2001', 'frozen_margin': 0.0}" ) self.assertEqual( str(get_order2), "{'order_id': '8ca5996666ceab360512bd1311072231', 'exchange_order_id': '8ca5996666ceab360512bd1311072231', 'exchange_id': 'SHFE', 'instrument_id': 'cu2001', 'direction': 'SELL', 'offset': 'OPEN', 'volume_orign': 2, 'volume_left': 0, 'limit_price': 47040.0, 'price_type': 'LIMIT', 'volume_condition': 'ANY', 'time_condition': 'GFD', 'insert_date_time': 631123200000000000, 'last_msg': '全部成交', 'status': 'FINISHED', 'user_id': 'TQSIM', 'symbol': 'SHFE.cu2001', 'frozen_margin': 0.0}" ) self.assertEqual(get_order1.order_id, "1710cf5327ac435a7a97c643656412a9") self.assertEqual(get_order1.direction, "BUY") self.assertEqual(get_order1.offset, "OPEN") self.assertEqual(get_order1.volume_orign, 1) self.assertEqual(get_order1.volume_left, 0) self.assertEqual(get_order1.limit_price != get_order1.limit_price, True) # 判断nan self.assertEqual(get_order1.price_type, "ANY") self.assertEqual(get_order1.volume_condition, "ANY") self.assertEqual(get_order1.time_condition, "IOC") self.assertEqual(get_order1.insert_date_time, 631123200000000000) self.assertEqual(get_order1.last_msg, "全部成交") self.assertEqual(get_order1.status, "FINISHED") self.assertEqual(get_order1.symbol, "DCE.jd2001") self.assertEqual(get_order1.frozen_margin, 0) self.assertEqual(get_order2.order_id, "8ca5996666ceab360512bd1311072231") self.assertEqual(get_order2.direction, "SELL") self.assertEqual(get_order2.offset, "OPEN") self.assertEqual(get_order2.volume_orign, 2) self.assertEqual(get_order2.volume_left, 0) self.assertEqual(get_order2.limit_price, 47040) self.assertEqual(get_order2.price_type, "LIMIT") self.assertEqual(get_order2.volume_condition, "ANY") self.assertEqual(get_order2.time_condition, "GFD") self.assertEqual(get_order2["insert_date_time"], 631123200000000000) self.assertEqual(get_order2["last_msg"], "全部成交") self.assertEqual(get_order2["status"], "FINISHED") self.assertEqual(get_order2.symbol, "SHFE.cu2001") self.assertEqual(get_order2.frozen_margin, 0) api.close()
def test_sim_insert_order_time_check_7(self): """ 模拟交易下单时间判断测试7 订阅合约: 订阅周六有行情的和周六无行情的 测试: (回测从周六开始) 1 回测刚开始:current_datetime 为 0:00 , 只有cu能下单 2 白盘开始后,都能下单 """ # 预设服务器端响应 dir_path = os.path.dirname(os.path.realpath(__file__)) self.mock.run(os.path.join(dir_path, "log_file", "test_sim_insert_order_time_check_7.script.lzma")) utils.RD = random.Random(4) api = TqApi( backtest=TqBacktest(datetime.datetime(2019, 11, 30, 0, 0, 0), datetime.datetime(2019, 12, 2, 9, 30)), _ins_url=self.ins_url_2019_12_04) symbol1 = "SHFE.cu2002" # 有夜盘,凌晨1点结束夜盘 symbol2 = "SHFE.rb2002" # 夜盘23点结束 symbol3 = "DCE.jd2002" # 无夜盘 quote1 = api.get_quote(symbol1) quote2 = api.get_quote(symbol2) quote3 = api.get_quote(symbol3) position1 = api.get_position(symbol1) position2 = api.get_position(symbol2) position3 = api.get_position(symbol3) try: # 1 回测刚开始:current_datetime 为 0:00 , 只有cu能下单 order1 = api.insert_order(symbol=symbol1, direction="SELL", offset="OPEN", volume=1, limit_price=quote1.last_price) order2 = api.insert_order(symbol=symbol2, direction="BUY", offset="OPEN", volume=2, limit_price=quote2.last_price) order3 = api.insert_order(symbol=symbol3, direction="BUY", offset="OPEN", volume=3, limit_price=quote3.last_price) while order1.status != "FINISHED" or order2.status != "FINISHED" or order3.status != "FINISHED": api.wait_update() self.assertEqual(order1.volume_orign, 1) self.assertEqual(order1.volume_left, 0) self.assertEqual(order2.volume_orign, 2) self.assertEqual(order2.volume_left, 2) self.assertEqual(order3.volume_orign, 3) self.assertEqual(order3.volume_left, 3) self.assertEqual(1575043200000000000, order1.insert_date_time) self.assertEqual(1575043200000000000, order2.insert_date_time) self.assertEqual(1575043200000000000, order3.insert_date_time) # 2 白盘开始后,都能下单 while max(quote1.datetime, quote2.datetime, quote3.datetime) < "2019-12-02 09:00:00.000000": api.wait_update() order1 = api.insert_order(symbol=symbol1, direction="BUY", offset="OPEN", volume=1, limit_price=quote1.last_price) order2 = api.insert_order(symbol=symbol2, direction="BUY", offset="OPEN", volume=2, limit_price=quote2.last_price) order3 = api.insert_order(symbol=symbol3, direction="BUY", offset="OPEN", volume=3, limit_price=quote3.last_price) while order1.status != "FINISHED" or order2.status != "FINISHED" or order3.status != "FINISHED": api.wait_update() self.assertEqual(order1.volume_orign, 1) self.assertEqual(order1.volume_left, 0) self.assertEqual(order2.volume_orign, 2) self.assertEqual(order2.volume_left, 0) self.assertEqual(order3.volume_orign, 3) self.assertEqual(order3.volume_left, 0) self.assertEqual(1575248459999999000, order1.insert_date_time) self.assertEqual(1575248459999999000, order2.insert_date_time) self.assertEqual(1575248459999999000, order3.insert_date_time) while True: api.wait_update() except BacktestFinished: self.assertEqual(position1.pos, 0) self.assertEqual(position2.pos, 2) self.assertEqual(position3.pos, 3) api.close()
def test_lib_insert_order_time_check_3(self): ''' lib下单时间判断测试3 回测时间: 第一日白盘11:30 - 第二日白盘9:40 订阅合约: IF、T(无盘中休息时间),cu(有盘中休息时间) 测试: 1 T、IF在13:00后下单,cu到13:30后下单 2 15:00 - 15:15 : T能下单,IF、cu不能下单 3 2020.2.18 交易所通知cu这段时间没有夜盘,因此之前set的手数到第二个交易日开盘后下单 4 cu在9点开盘下单,IF在9:30开盘下单 ''' # 预设服务器端响应 dir_path = os.path.dirname(os.path.realpath(__file__)) self.mock.run( os.path.join(dir_path, "log_file", "test_lib_insert_order_time_check_3.script.lzma")) TqApi.RD = random.Random(4) api = TqApi(backtest=TqBacktest(datetime.datetime(2020, 2, 17, 11, 30), datetime.datetime(2020, 2, 18, 9, 40)), _ins_url=self.ins_url_2020_02_18) symbol1 = "SHFE.cu2003" symbol2 = "CFFEX.T2003" symbol3 = "CFFEX.IF2003" quote1 = api.get_quote(symbol1) quote2 = api.get_quote(symbol2) quote3 = api.get_quote(symbol3) position1 = api.get_position(symbol1) position2 = api.get_position(symbol2) position3 = api.get_position(symbol3) target_pos1 = TargetPosTask(api, symbol1) target_pos2 = TargetPosTask(api, symbol2) target_pos3 = TargetPosTask(api, symbol3) orders = api.get_order() try: # 1 T、IF在13:00后下单,cu到13:30后下单 target_pos1.set_target_volume(1) target_pos2.set_target_volume(2) target_pos3.set_target_volume(3) while max(quote1.datetime, quote2.datetime, quote3.datetime) < "2020-02-17 13:15:00.000000": api.wait_update() self.assertEqual(len(orders), 2) self.assertEqual(position1.pos, 0) self.assertEqual(position2.pos, 2) self.assertEqual(position3.pos, 3) while max(quote1.datetime, quote2.datetime, quote3.datetime) < "2020-02-17 13:31:00.000000": api.wait_update() self.assertEqual(len(orders), 3) while max(quote1.datetime, quote2.datetime, quote3.datetime) < "2020-02-17 13:40:00.000000": api.wait_update() self.assertEqual(position1.pos, 1) self.assertEqual(position2.pos, 2) self.assertEqual(position3.pos, 3) while max(quote1.datetime, quote2.datetime, quote3.datetime) < "2020-02-17 15:00:00.000000": api.wait_update() # 2 15:00 - 15:15 : T能下单,IF、cu不能下单 target_pos1.set_target_volume(4) target_pos2.set_target_volume(5) target_pos3.set_target_volume(6) while max(quote1.datetime, quote2.datetime, quote3.datetime) < "2020-02-17 15:13:59.000000": api.wait_update() self.assertEqual(len(orders), 4) self.assertEqual(position1.pos, 1) self.assertEqual(position2.pos, 5) self.assertEqual(position3.pos, 3) # 3 2020.2.18 交易所通知cu这段时间没有夜盘,因此之前set的手数到第二个交易日开盘后下单 while max(quote1.datetime, quote2.datetime, quote3.datetime) < "2020-02-18 09:00:00.0000": api.wait_update() self.assertEqual(len(orders), 4) self.assertEqual(position1.pos, 1) self.assertEqual(position2.pos, 5) self.assertEqual(position3.pos, 3) # 4 cu在9点开盘下单,IF在9:30开盘下单 while max(quote1.datetime, quote2.datetime, quote3.datetime) < "2020-02-18 09:20:00.0000": api.wait_update() self.assertEqual(len(orders), 5) self.assertEqual(position1.pos, 4) self.assertEqual(position2.pos, 5) self.assertEqual(position3.pos, 3) while max(quote1.datetime, quote2.datetime, quote3.datetime) < "2020-02-18 09:35:00.0000": api.wait_update() self.assertEqual(len(orders), 6) self.assertEqual(position1.pos, 4) self.assertEqual(position2.pos, 5) self.assertEqual(position3.pos, 6) while True: api.wait_update() except BacktestFinished: self.assertEqual(len(orders), 6) self.assertEqual(position1.pos, 4) self.assertEqual(position2.pos, 5) self.assertEqual(position3.pos, 6) api.close()
def test_get_trade_option(self): """ 获取成交记录 """ # 预设服务器端响应 dir_path = os.path.dirname(os.path.realpath(__file__)) self.mock.run( os.path.join( dir_path, "log_file", "test_td_basic_get_trade_simulate_option.script.lzma")) # 测试: 模拟账户 utils.RD = random.Random(4) api = TqApi(_ins_url=self.ins_url_2020_04_02, _td_url=self.td_url, _md_url=self.md_url) order1 = api.insert_order("CZCE.SR007C5600", "SELL", "OPEN", 1, limit_price=50) order2 = api.insert_order("DCE.m2007-P-2900", "BUY", "OPEN", 2, limit_price=180) while order1.status == "ALIVE" or order2.status == "ALIVE": api.wait_update() trade1 = api.get_trade( "PYSDK_insert_1710cf5327ac435a7a97c643656412a9|1") trade2 = api.get_trade( "PYSDK_insert_8ca5996666ceab360512bd1311072231|2") self.assertAlmostEqual(1586501231007428000 / 1e9, trade1.trade_date_time / 1e9, places=1) self.assertAlmostEqual(1586501233361505000 / 1e9, trade2.trade_date_time / 1e9, places=1) del trade1["trade_date_time"] del trade2["trade_date_time"] self.assertEqual( str(trade1), "{'order_id': 'PYSDK_insert_1710cf5327ac435a7a97c643656412a9', 'trade_id': 'PYSDK_insert_1710cf5327ac435a7a97c643656412a9|1', 'exchange_trade_id': 'PYSDK_insert_1710cf5327ac435a7a97c643656412a9|1', 'exchange_id': 'CZCE', 'instrument_id': 'SR007C5600', 'direction': 'SELL', 'offset': 'OPEN', 'price': 50.0, 'volume': 1, 'user_id': 'TQSIM', 'commission': 10}" ) self.assertEqual( str(trade2), "{'order_id': 'PYSDK_insert_8ca5996666ceab360512bd1311072231', 'trade_id': 'PYSDK_insert_8ca5996666ceab360512bd1311072231|2', 'exchange_trade_id': 'PYSDK_insert_8ca5996666ceab360512bd1311072231|2', 'exchange_id': 'DCE', 'instrument_id': 'm2007-P-2900', 'direction': 'BUY', 'offset': 'OPEN', 'price': 180.0, 'volume': 2, 'user_id': 'TQSIM', 'commission': 20}" ) self.assertEqual(trade1.direction, "SELL") self.assertEqual(trade1.offset, "OPEN") self.assertEqual(trade1.price, 50.0) self.assertEqual(trade1.volume, 1) self.assertEqual(trade1.commission, 10) self.assertEqual(trade2.direction, "BUY") self.assertEqual(trade2.offset, "OPEN") self.assertEqual(trade2.price, 180.0) self.assertEqual(trade2.volume, 2) self.assertEqual(trade2.commission, 20) api.close()
def test_lib_insert_order_time_check_1(self): """ lib下单时间判断测试1 回测时间: 周一21:00 - 周二10:00 合约订阅: 无夜盘; 有夜盘24:00结束; 有夜盘25:00结束 测试: 21:00起始时刻两个有夜盘合约立即下單,无夜盘合约第二日白盘下单; 23:00某一夜盘合约停止交易后不能下單,另一合约能下單; """ # 预设服务器端响应 dir_path = os.path.dirname(os.path.realpath(__file__)) self.mock.run( os.path.join(dir_path, "log_file", "test_lib_insert_order_time_check_1.script.lzma")) TqApi.RD = random.Random(4) api = TqApi(backtest=TqBacktest( datetime.datetime(2019, 12, 2, 21, 0, 0), datetime.datetime(2019, 12, 3, 10, 0, 0)), _ins_url=self.ins_url_2019_12_04) # 2019.12.2周一 symbol1 = "DCE.jd2002" # 无夜盘 symbol2 = "SHFE.rb2002" # 夜盘23点结束 symbol3 = "SHFE.cu2002" # 夜盘凌晨1点结束 quote3 = api.get_quote(symbol3) target_pos1 = TargetPosTask(api, symbol1) target_pos2 = TargetPosTask(api, symbol2) target_pos3 = TargetPosTask(api, symbol3) position1 = api.get_position(symbol1) position2 = api.get_position(symbol2) position3 = api.get_position(symbol3) orders = api.get_order() try: # 1 21:00起始时刻有夜盘合约立即下單,无夜盘合约第二日白盘下单; target_pos1.set_target_volume(1) target_pos2.set_target_volume(2) target_pos3.set_target_volume(3) while datetime.datetime.strptime( quote3.datetime, "%Y-%m-%d %H:%M:%S.%f") < datetime.datetime( 2019, 12, 2, 21, 2): api.wait_update() self.assertEqual(len(orders), 2) self.assertEqual(position1.pos, 0) self.assertEqual(position2.pos, 2) self.assertEqual(position3.pos, 3) # 2 23:00某一夜盘合约停止交易后不能下單,另一合约能下單; while datetime.datetime.strptime( quote3.datetime, "%Y-%m-%d %H:%M:%S.%f") < datetime.datetime( 2019, 12, 3, 0, 0): api.wait_update() target_pos1.set_target_volume(4) target_pos2.set_target_volume(5) target_pos3.set_target_volume(6) while datetime.datetime.strptime( quote3.datetime, "%Y-%m-%d %H:%M:%S.%f") < datetime.datetime( 2019, 12, 3, 0, 30): api.wait_update() self.assertEqual(len(orders), 3) self.assertEqual(position1.pos, 0) self.assertEqual(position2.pos, 2) self.assertEqual(position3.pos, 6) while True: api.wait_update() except BacktestFinished: # 验证下單情況 # 第二个交易日白盘,将所有合约调整到目标手数 self.assertEqual(len(orders), 5) self.assertEqual(position1.pos, 4) self.assertEqual(position2.pos, 5) self.assertEqual(position3.pos, 6) print("回测结束") api.close()
def linear(data1,data2): regr = linear_model.LinearRegression() data1=np.transpose(np.array(data1)).reshape(1,-1) data2=np.transpose(np.array(data2)).reshape(1,-1) result=regr.fit(data1,data2) alpha = np.mean(result.intercept_) beta = np.mean(result.coef_) data1_adj = alpha + beta * data2 residuals = data1_adj - data1 mean = np.mean(residuals) std = np.std(residuals) result_all = [mean,std,beta,alpha] return (result_all) while True: #判断开仓条件的主循环 api.wait_update() #等待业务数据更新 if api.is_changing(klines_b): linear_result = linear(klines_a.close_oi,klines_b.close_oi) print(linear_result) spread = linear_result[3]+linear_result[2]*klines_a['close'].tolist()[-1]-klines_b['close'].tolist()[-1] print(spread) if spread < linear_result[0]+ 2*linear_result[1]: #实际调整为2个sigma print("此为多头市场") target_pos.set_target_volume(50) elif spread > linear_result[0]- 2*linear_result[1]: print("此为空头市场") target_pos.set_target_volume(-50) #如果触发了,则通过 target_pos 将 目标持仓设置为多头 1 手,具体的调仓工作则由 target_pos 在后台完成 break #跳出开仓循环,进入下面的平仓循环 while True: #判断平仓条件的主循环 api.wait_update() #等待业务数据更新
symbol = "SHFE.cu1905" # 合约代码 close_hour, close_minute = 14, 50 # 平仓时间 api = TqApi(TqSim()) # 使用模拟帐号直连行情和交易服务器 quote = api.get_quote(symbol) # 获取指定合约的盘口行情 klines = api.get_kline_serial(symbol, 24 * 60 * 60) # 获取日线 position = api.get_position(symbol) # 持仓信息 target_pos = TargetPosTask(api, symbol) # 目标持仓 top_rail = klines.high.iloc[-2] # 上轨: 昨日高点 bottom_rail = klines.low.iloc[-2] # 下轨: 昨日低点 print("上轨:", top_rail, ",下轨:", bottom_rail, ",昨日收盘价:", klines.close.iloc[-2], ",今日开盘价:", klines.open.iloc[-1]) while True: api.wait_update() if api.is_changing(klines.iloc[-1], "datetime"): # 如果产生一根新日线 (即到达下一个交易日): 重新获取上下轨 top_rail = klines.high.iloc[-2] bottom_rail = klines.low.iloc[-2] print("上轨:", top_rail, ",下轨:", bottom_rail, ",昨日收盘价:", klines.close.iloc[-2], ",今日开盘价:", klines.open.iloc[-1]) if api.is_changing(quote, "last_price"): # 如果行情最新价发生变化 print("当前最新价", quote.last_price) # 开仓突破 if quote.last_price > top_rail and position.volume_long == 0: # 如果价格突破上轨: 买入开仓 print("最新价:", quote.last_price, ", 价格突破上轨,买入开仓") target_pos.set_target_volume(3) # 设置目标持仓手数,将指定合约调整到目标头寸 elif quote.last_price < bottom_rail and position.volume_short == 0: # 如果价格跌破下轨: 卖出开仓 print("最新价:", quote.last_price, ", 价格跌破下轨, 卖出开仓")
def test_get_order(self): """ 获取委托单信息 """ # 预设服务器端响应 dir_path = os.path.dirname(os.path.realpath(__file__)) self.mock.run( os.path.join(dir_path, "log_file", "test_td_basic_get_order_simulate.script.lzma")) # 测试: 模拟账户下单 TqApi.RD = random.Random(4) api = TqApi(_ins_url=self.ins_url_2019_07_03, _td_url=self.td_url, _md_url=self.md_url) order1 = api.insert_order("DCE.jd2005", "BUY", "OPEN", 1) order2 = api.insert_order("SHFE.cu2005", "SELL", "OPEN", 2, limit_price=40750) while order1.status == "ALIVE" or order2.status == "ALIVE": api.wait_update() get_order1 = api.get_order(order1.order_id) get_order2 = api.get_order(order2.order_id) self.assertEqual(get_order1.order_id, "1710cf5327ac435a7a97c643656412a9") self.assertEqual(get_order1.direction, "BUY") self.assertEqual(get_order1.offset, "OPEN") self.assertEqual(get_order1.volume_orign, 1) self.assertEqual(get_order1.volume_left, 0) self.assertNotEqual(get_order1.limit_price, get_order1.limit_price) # 判断nan self.assertEqual(get_order1.price_type, "ANY") self.assertEqual(get_order1.volume_condition, "ANY") self.assertEqual(get_order1.time_condition, "IOC") # 因为TqSim模拟交易的 insert_date_time 不是固定值,所以改为判断范围(前后100毫秒) self.assertAlmostEqual(1586415071223454000 / 1e9, get_order1.insert_date_time / 1e9, places=1) self.assertEqual(get_order1.last_msg, "全部成交") self.assertEqual(get_order1.status, "FINISHED") self.assertEqual(get_order1.frozen_margin, 0) self.assertEqual(get_order2.order_id, "8ca5996666ceab360512bd1311072231") self.assertEqual(get_order2.direction, "SELL") self.assertEqual(get_order2.offset, "OPEN") self.assertEqual(get_order2.volume_orign, 2) self.assertEqual(get_order2.volume_left, 0) self.assertEqual(get_order2.limit_price, 40750) self.assertEqual(get_order2.price_type, "LIMIT") self.assertEqual(get_order2.volume_condition, "ANY") self.assertEqual(get_order2.time_condition, "GFD") self.assertAlmostEqual(1586415071224110000 / 1e9, get_order2["insert_date_time"] / 1e9, places=1) self.assertEqual(get_order2["last_msg"], "全部成交") self.assertEqual(get_order2["status"], "FINISHED") self.assertEqual(get_order2.frozen_margin, 0) del get_order1["insert_date_time"] del get_order2["insert_date_time"] self.assertEqual( str(get_order1), "{'order_id': '1710cf5327ac435a7a97c643656412a9', 'exchange_order_id': '1710cf5327ac435a7a97c643656412a9', 'exchange_id': 'DCE', 'instrument_id': 'jd2005', 'direction': 'BUY', 'offset': 'OPEN', 'volume_orign': 1, 'volume_left': 0, 'limit_price': nan, 'price_type': 'ANY', 'volume_condition': 'ANY', 'time_condition': 'IOC', 'last_msg': '全部成交', 'status': 'FINISHED', 'user_id': 'TQSIM', 'frozen_margin': 0.0, 'frozen_premium': 0.0}" ) self.assertEqual( str(get_order2), "{'order_id': '8ca5996666ceab360512bd1311072231', 'exchange_order_id': '8ca5996666ceab360512bd1311072231', 'exchange_id': 'SHFE', 'instrument_id': 'cu2005', 'direction': 'SELL', 'offset': 'OPEN', 'volume_orign': 2, 'volume_left': 0, 'limit_price': 40750.0, 'price_type': 'LIMIT', 'volume_condition': 'ANY', 'time_condition': 'GFD', 'last_msg': '全部成交', 'status': 'FINISHED', 'user_id': 'TQSIM', 'frozen_margin': 0.0, 'frozen_premium': 0.0}" ) api.close()
symbol = "DCE.jd1905" # 交易合约代码 history_day_length = 20 # 使用多少天的历史数据用来计算每个时间单元的下单手数 time_slot_start = datetime.time(9, 35) # 计划交易时段起始时间点 time_slot_end = datetime.time(10, 50) # 计划交易时段终点时间点 api = TqApi(TqSim()) # 根据 history_day_length 推算出需要订阅的历史数据长度, 需要注意history_day_length与time_cell的比例关系以避免超过订阅限制 klines = api.get_kline_serial(symbol, time_cell, data_length=int(10 * 60 * 60 / time_cell * history_day_length)) target_pos = TargetPosTask(api, symbol) position = api.get_position(symbol) # 持仓信息 while not klines.is_ready(): # 等待数据 api.wait_update() df = klines.to_dataframe() # 将k线数据转为DataFrame def get_kline_time(kline_datetime): """获取k线的时间(不包含日期)""" kline_time = datetime.datetime.fromtimestamp(kline_datetime // 1000000000).time() # 每根k线的时间 return kline_time def get_market_day(kline_datetime): """获取k线所对应的交易日""" kline_dt = datetime.datetime.fromtimestamp(kline_datetime // 1000000000) # 每根k线的日期和时间
def test_get_position(self): """ 获取持仓 """ # 预设服务器端响应 self.mock.run("test_td_basic_get_position_simulate.script") # 测试: 获取数据 api = TqApi(_ins_url=self.ins_url, _td_url=self.td_url, _md_url=self.md_url) order1 = api.insert_order("DCE.jd2001", "BUY", "OPEN", 1, limit_price=4592) order2 = api.insert_order("DCE.jd2001", "BUY", "OPEN", 3) order3 = api.insert_order("DCE.jd2001", "SELL", "OPEN", 3) while order1.status == "ALIVE" or order2.status == "ALIVE" or order3.status == "ALIVE": api.wait_update() position = api.get_position("DCE.jd2001") self.assertEqual( "{'exchange_id': 'DCE', 'instrument_id': 'jd2001', 'pos_long_his': 0, 'pos_long_today': 4, 'pos_short_his': 0, 'pos_short_today': 3, 'volume_long_today': 4, 'volume_long_his': 0, 'volume_long': 4, 'volume_long_frozen_today': 0, 'volume_long_frozen_his': 0, 'volume_long_frozen': 0, 'volume_short_today': 3, 'volume_short_his': 0, 'volume_short': 3, 'volume_short_frozen_today': 0, 'volume_short_frozen_his': 0, 'volume_short_frozen': 0, 'open_price_long': 4574.75, 'open_price_short': 4568.0, 'open_cost_long': 182990.0, 'open_cost_short': 137040.0, 'position_price_long': 4574.75, 'position_price_short': 4568.0, 'position_cost_long': 182990.0, 'position_cost_short': 137040.0, 'float_profit_long': -270.0, 'float_profit_short': 0.0, 'float_profit': -270.0, 'position_profit_long': -270.0, 'position_profit_short': 0.0, 'position_profit': -270.0, 'margin_long': 11429.6, 'margin_short': 8572.2, 'margin': 20001.800000000003, 'symbol': 'DCE.jd2001', 'last_price': 4568.0}", str(position)) self.assertEqual(1, position.pos) self.assertEqual(4, position.pos_long) self.assertEqual(3, position.pos_short) self.assertEqual(position.exchange_id, "DCE") self.assertEqual(position.instrument_id, "jd2001") self.assertEqual(position.pos_long_his, 0) self.assertEqual(position.pos_long_today, 4) self.assertEqual(position.pos_short_his, 0) self.assertEqual(position.pos_short_today, 3) self.assertEqual(position.volume_long_today, 4) self.assertEqual(position.volume_long_his, 0) self.assertEqual(position.volume_long, 4) self.assertEqual(position.volume_long_frozen_today, 0) self.assertEqual(position.volume_long_frozen_his, 0) self.assertEqual(position.volume_long_frozen, 0) self.assertEqual(position.volume_short_today, 3) self.assertEqual(position.volume_short_his, 0) self.assertEqual(position.volume_short, 3) self.assertEqual(position.volume_short_frozen_today, 0) self.assertEqual(position.volume_short_frozen_his, 0) self.assertEqual(position.volume_short_frozen, 0) self.assertEqual(position.open_price_long, 4574.75) self.assertEqual(position.open_price_short, 4568.0) self.assertEqual(position.open_cost_long, 182990.0) self.assertEqual(position.open_cost_short, 137040.0) self.assertEqual(position.position_price_long, 4574.75) self.assertEqual(position.position_price_short, 4568.0) self.assertEqual(position.position_cost_long, 182990.0) self.assertEqual(position.position_cost_short, 137040.0) self.assertEqual(position.float_profit_long, -270.0) self.assertEqual(position.float_profit_short, 0.0) self.assertEqual(position.float_profit, -270.0) self.assertEqual(position.position_profit_long, -270.0) self.assertEqual(position.position_profit_short, 0.0) self.assertEqual(position.position_profit, -270.0) self.assertEqual(position.margin_long, 11429.6) self.assertEqual(position.margin_short, 8572.2) self.assertEqual(position.margin, 20001.800000000003) self.assertEqual(position.symbol, "DCE.jd2001") self.assertEqual(position.last_price, 4568.0) # 其他取值方式测试 self.assertEqual(position["pos_long_today"], 4) self.assertEqual(position["pos_short_today"], 3) self.assertEqual(position["volume_long_his"], 0) self.assertEqual(position["volume_long"], 4) api.close()