def record_quotes(symbols, _stock, _md_url): api = TqApi(auth=AUTH, _stock=_stock, _md_url=_md_url) api._requests["quotes"] = set(symbols) api._send_chan.send_nowait({ "aid": "subscribe_quote", "ins_list": ",".join(symbols) }) api.wait_update() api.wait_update() quotes = {} csv_files = {} for s in symbols: quotes[s] = api.get_quote(s) csv_files[s] = (create_csvfile(s, "new" if _stock else "old")) csv_files[s][1].writerow(["local_nano_time", "quote_nano_time"] + HEADER_ROW) end = time() + 60 * 60 # 记录 30 min 分钟的数据分析 while True: if end < time(): break api.wait_update() for s, q in quotes.items(): if api.is_changing(q): csv_files[s][1].writerow([ f"{time()*1e9:.0f}", f"{_str_to_nano(q['datetime']):.0f}" ] + [q[k] for k in HEADER_ROW]) close_csvfiles(csv_files) api.close()
def test_is_changing(self): """is_changing() 测试""" # 预设服务器端响应 dir_path = os.path.dirname(os.path.realpath(__file__)) self.mock.run(os.path.join(dir_path, "log_file", "test_func_basic_is_changing.script.lzma")) # 测试: 模拟账户下单 TqApi.RD = random.Random(4) api = TqApi(_ins_url=self.ins_url, _td_url=self.td_url, _md_url=self.md_url) quote = api.get_quote("SHFE.rb2001") position = api.get_position("SHFE.rb2001") order1 = api.insert_order("DCE.m2001", "BUY", "OPEN", 1) api.wait_update() order2 = api.insert_order("SHFE.rb2001", "SELL", "OPEN", 2) api.wait_update() self.assertEqual(api.is_changing(order2, "status"), True) self.assertEqual(api.is_changing(position, "volume_short"), True) self.assertEqual(api.is_changing(position, "volume_long"), False) order3 = api.insert_order("SHFE.rb2001", "BUY", "CLOSETODAY", 1) while order3.status == "ALIVE": api.wait_update() self.assertEqual(api.is_changing(order3, "status"), True) self.assertEqual(api.is_changing(position, "volume_short"), True) self.assertEqual(api.is_changing(quote, "last_price"), False) api.close()
def test_is_changing(self): """ is_changing() 测试 注:本函数不是回测,重新生成测试用例script文件时更改为当前可交易的合约代码,在盘中生成,且_ins_url可能需修改。 """ # 预设服务器端响应 dir_path = os.path.dirname(os.path.realpath(__file__)) self.mock.run( os.path.join(dir_path, "log_file", "test_func_basic_is_changing.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) quote = api.get_quote("SHFE.rb2010") position = api.get_position("SHFE.rb2010") order1 = api.insert_order("DCE.m2009", "BUY", "OPEN", 1) api.wait_update() order2 = api.insert_order("SHFE.rb2010", "SELL", "OPEN", 2) api.wait_update() self.assertTrue(api.is_changing(order2, "status")) self.assertTrue(api.is_changing(position, "volume_short")) self.assertFalse(api.is_changing(position, "volume_long")) order3 = api.insert_order("SHFE.rb2010", "BUY", "CLOSETODAY", 1) while order3.status == "ALIVE": api.wait_update() self.assertTrue(api.is_changing(order3, "status")) self.assertTrue(api.is_changing(position, "volume_short")) self.assertFalse(api.is_changing(quote, "last_price")) api.close()
def run_tianqin_code(port): try: api = TqApi(backtest=TqBacktest(start_dt=date(2018, 5, 5), end_dt=date(2018, 5, 10)), web_gui="127.0.0.1:" + port) klines = api.get_kline_serial("DCE.m1901", 5 * 60, data_length=15) target_pos = TargetPosTask(api, "DCE.m1901") while True: api.wait_update() if api.is_changing(klines): ma = sum(klines.close.iloc[-15:]) / 15 if klines.close.iloc[-1] > ma: target_pos.set_target_volume(5) elif klines.close.iloc[-1] < ma: target_pos.set_target_volume(0) except BacktestFinished as e: while True: api.wait_update() except Exception as e: api.close()
def run_tianqin_code(port, queue): try: ins_url = "http://127.0.0.1:5000/t/md/symbols/2019-07-03.json" api = TqApi(backtest=TqBacktest(start_dt=date(2019, 7, 10), end_dt=date(2019, 7, 20)), _ins_url=ins_url, web_gui="127.0.0.1:" + port) queue.put("webready") klines = api.get_kline_serial("DCE.m1912", 5 * 60, data_length=15) target_pos = TargetPosTask(api, "DCE.m1912") while True: api.wait_update() if api.is_changing(klines): ma = sum(klines.close.iloc[-15:]) / 15 if klines.close.iloc[-1] > ma: target_pos.set_target_volume(5) elif klines.close.iloc[-1] < ma: target_pos.set_target_volume(0) except BacktestFinished as e: while True: api.wait_update() except Exception as e: api.close()
def test_is_changing(self): # 预设服务器端响应 self.mock.run("test_func_basic_is_changing.script") # 测试: 模拟账户下单 TqApi.RD = random.Random(4) api = TqApi(_ins_url=self.ins_url, _td_url=self.td_url, _md_url=self.md_url) quote = api.get_quote("SHFE.rb2001") position = api.get_position("SHFE.rb2001") order1 = api.insert_order("DCE.m2001", "BUY", "OPEN", 1) api.wait_update() order2 = api.insert_order("SHFE.rb2001", "SELL", "OPEN", 2) api.wait_update() self.assertEqual(api.is_changing(order2, "status"), True) self.assertEqual(api.is_changing(position, "volume_short"), True) self.assertEqual(api.is_changing(position, "volume_long"), False) order3 = api.insert_order("SHFE.rb2001", "BUY", "CLOSETODAY", 1) while order3.status == "ALIVE": api.wait_update() self.assertEqual(api.is_changing(order3, "status"), True) self.assertEqual(api.is_changing(position, "volume_short"), True) self.assertEqual(api.is_changing(quote, "last_price"), False)
#!/usr/bin/env python # -*- coding: utf-8 -*- __author__ = 'chengzhi' from tqsdk import TqApi # 可以指定debug选项将调试信息写入指定的文件中 api = TqApi(debug="debug.log") quote = api.get_quote("SHFE.cu1909") print(quote.datetime, quote.last_price, quote.ask_price1, quote.ask_price2) while True: # 调用 wait_update 等待业务信息发生变化,例如: 行情发生变化, 委托单状态变化, 发生成交等等 # 注意:其他合约的行情的更新也会触发业务信息变化,因此下面使用 is_changing 判断 cu1909 的行情是否有变化 api.wait_update() # 如果 cu1909 的任何字段有变化,is_changing就会返回 True if api.is_changing(quote): print("行情变化", quote) # 只有当 cu1909 的最新价有变化,is_changing才会返回 True if api.is_changing(quote, "last_price"): print("最新价变化", quote.last_price) # 当 cu1909 的买1价/买1量/卖1价/卖1量中任何一个有变化,is_changing都会返回 True if api.is_changing(quote, ["ask_price1", "ask_volume1", "bid_price1", "bid_volume1"]): print("盘口变化", quote.ask_price1, quote.ask_volume1, quote.bid_price1, quote.bid_volume1)
spread_oc = sum(kline1.open[:-1] - kline1.low[:-1]) # spread_oc 为0时,设置为最小价格跳动值 if spread_oc == 0: spread_oc = quote.price_tick ar = (spread_ho/spread_oc)*100 return ar ar = AR(klines) print("策略开始启动") while True: api.wait_update() # 生成新K线时,重新计算价格动量值ar if api.is_changing(klines.iloc[-1], "datetime"): ar = AR(klines) print("价格动量是:", ar) # 每次最新价发生变动时,重新进行判断 if api.is_changing(quote, "last_price"): # 开仓策略 if position.pos_long == 0 and position.pos_short == 0: # 如果ar大于110并且小于150,开多仓 if 110 < ar < 150: print("价值动量超过110,小于150,做多") target_pos.set_target_volume(100) # 如果ar大于50,小于90,开空仓 elif 50 < ar < 90: print("价值动量大于50,小于90,做空") target_pos.set_target_volume(-100)
class CuatroStrategy(Process): '''''' author = 'XIAO LI' boll_window = 20 boll_dev = 1.8 rsi_window = 14 rsi_signal = 20 fast_window = 4 slow_window = 26 trailing_long = 0.5 trailing_short = 0.3 vol = 1 boll_up = float('nan') boll_down = float('nan') rsi_value = float('nan') rsi_long = float('nan') rsi_short = float('nan') fast_ma = float('nan') slow_ma = float('nan') ma_trend = float('nan') intra_trade_high = float('nan') intra_trade_low = float('nan') long_stop = float('nan') short_stop = float('nan') parameters = [ 'boll_window' 'boll_dev' 'rsi_window' 'rsi_signal' 'fast_window' 'slow_window' 'trailing_long' 'trailing_short' 'vol' ] variables = [ 'boll_up' 'boll_down' 'rsi_value' 'rsi_long' 'rsi_short' 'fast_ma' 'slow_ma' 'ma_trend' 'intra_trade_high' 'intra_trade_low ' 'long_stop' 'short_stop' ] def __init__(self, symbol): Process.__init__(self) self.symbol = symbol self.rsi_long = 50 + self.rsi_signal self.rsi_short = 50 - self.rsi_signal self.api = TqApi(TqSim(init_balance=50000)) self.now = datetime.now() self.target_pos = TargetPosTask(self.api, self.symbol) self.ticks = self.api.get_tick_serial(self.symbol) self.klines5 = self.api.get_kline_serial(self.symbol, 60 * 5) self.klines15 = self.api.get_kline_serial(self.symbol, 60 * 15) self.position = self.api.get_position(self.symbol) def on_init(self): print(self.now, '策略初始化') def on_start(self): print(self.now, '策略启动') def on_stop(self): print(self.now, '策略停止') def on_tick(self, ticks): if self.api.is_changing(ticks, 'datetime'): if self.position.pos_long == 0 and self.position.pos_short == 0: if self.ma_trend > 0 and self.rsi_value >= self.rsi_long and ticks.iloc[-1].last_price > self.boll_up: self.target_pos.set_target_volume(self.vol) self.intra_trade_high = ticks.iloc[-1].last_price if self.ma_trend < 0 and self.rsi_value <= self.rsi_short and ticks.iloc[ -1].last_price < self.boll_down: self.target_pos.set_target_volume(-self.vol) self.intra_trade_low = ticks.iloc[-1].last_price elif self.position.pos_long > 0: self.intra_trade_high = max(self.intra_trade_high, ticks.iloc[-1].last_price) self.long_stop = (self.intra_trade_high - self.trailing_long * (self.boll_up - self.boll_down)) if ticks.iloc[-1].last_price < self.long_stop: self.target_pos.set_target_volume(0) self.intra_trade_high = float('nan') else: self.intra_trade_low = min(self.intra_trade_low, ticks.iloc[-1].last_price) self.short_stop = (self.intra_trade_low + self.trailing_short * (self.boll_up - self.boll_down)) if ticks.iloc[-1].last_price > self.short_stop: self.target_pos.set_target_volume(0) self.intra_trade_low = float('nan') def on_5minbar(self, klines5): if self.api.is_changing(klines5, 'datetime'): boll = ta.BOLL(klines5.iloc[:-1], self.boll_window, self.boll_dev).iloc[-1] self.boll_up = boll['top'] self.boll_down = boll['bottom'] self.rsi_value = ta.RSI(klines5.iloc[:-1], self.rsi_window).iloc[-1]['rsi'] def on_15minbar(self, klines15): if self.api.is_changing(klines15, 'datetime'): self.fast_ma = ta.SMA(klines15.iloc[:-1], self.fast_window, 2) self.slow_ma = ta.SMA(klines15.iloc[:-1], self.slow_window, 2) if self.fast_ma > self.slow_ma: self.ma_trend = 1 elif self.fast_ma < self.slow_ma: self.ma_trend = -1 else: self.ma_trend = 0 def on_order(self): if self.api.is_changing(self.api.get_order()): pass def on_trade(self): if self.api.is_changing(self.api.get_trade()): pass def run(self): self.on_init() self.on_start() while True: self.api.wait_update() self.on_tick(self.ticks) self.on_5minbar(self.klines5) self.on_15minbar(self.klines15) self.on_order() self.on_trade() self.on_stop()
#!/usr/bin/env python # -*- coding: utf-8 -*- __author__ = 'chengzhi' from datetime import date from tqsdk import TqApi, TqReplay, TargetPosTask ''' 复盘 2019-11-12 如果当前价格大于5分钟K线的MA15则开多仓,如果小于则平仓 ''' # 在创建 api 实例时传入 TqReplay 就会进入复盘模式, 同时打开 web_gui api = TqApi(backtest=TqReplay(date(2019, 11, 12)), web_gui=True) # 获得 m1901 5分钟K线的引用 klines = api.get_kline_serial("SHFE.cu2001", 5 * 60, data_length=15) # 创建 m1901 的目标持仓 task,该 task 负责调整 m1901 的仓位到指定的目标仓位 target_pos = TargetPosTask(api, "SHFE.cu2001") while True: api.wait_update() if api.is_changing(klines): ma = sum(klines.close.iloc[-15:]) / 15 print("最新价", klines.close.iloc[-1], "MA", ma) if klines.close.iloc[-1] > ma: print("最新价大于MA: 目标多头5手") # 设置目标持仓为多头5手 target_pos.set_target_volume(5) elif klines.close.iloc[-1] < ma: print("最新价小于MA: 目标空仓") # 设置目标持仓为空仓 target_pos.set_target_volume(0)
signal = -1 stop_loss = Wave_down[0] target_price = pricet - h_down else: signal = 0 return signal, stop_loss, target_price with closing(api): try: while True: target_pos.set_target_volume(target_pos_value) api.wait_update() # 判断最后一根K线的时间是否有变化,如果发生变化则表示新产生了一根K线 if api.is_changing(klines[-1], "datetime"): # 注意引用k线的时间是k线的起始时间 k_time = dt.datetime.fromtimestamp(klines[-2]["datetime"] / 1e9) dict_results = wave(klines, w=3, X=5) signal, stop_loss, target_price = wave_rule(dict_results) if api.is_changing(quote, 'last_price'): if target_pos_value == 0: if signal == 1: target_pos_value = 1 print('开仓多头') print("判断信号K线时间", k_time) print(dict_results['Up']) print('price target: ', target_price)
class Turtle: def __init__(self, account, symbol, 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, init_pos=self.state["position"]) 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()
(MA.loc[ls_down[0]] > MA.loc[ls_down[1]] > MA[-1]) and \ (np.abs(pricet - MA[-1]) < 0.6): signal = -1 stop_loss = Wave_down[0] target_price = pricet - h_down else: signal = 0 return signal, stop_loss, target_price with closing(api): while True: api.wait_update() # 判断最后一根K线的时间是否有变化,如果发生变化则表示新产生了一根K线 if api.is_changing(klines[-1], "datetime"): # 注意引用k线的时间是k线的起始时间 k_time = dt.datetime.fromtimestamp(klines[-2]["datetime"] / 1e9) dict_results = wave(klines, w=3, X=20) signal, stop_loss, target_price = wave_rule(dict_results) print(k_time) if signal == 1: print('开仓多头') print("判断信号K线时间", k_time) print(dict_results['Up']) print('price target: ', target_price) print('stop loss: ', stop_loss) elif signal == -1: print('开仓空头') print("判断信号K线时间", k_time) print(dict_results['Down'])
#!/usr/bin/env python # -*- coding: utf-8 -*- __author__ = 'mayanqiong' from datetime import date from tqsdk import TqApi, TqAuth, TqReplay ''' 复盘模式示例: 指定日期行情完全复盘 复盘 2020-05-26 行情 ''' # 在创建 api 实例时传入 TqReplay 就会进入复盘模式 api = TqApi(backtest=TqReplay(date(2020, 5, 26)), auth=TqAuth("信易账户", "账户密码")) quote = api.get_quote("SHFE.cu2009") while True: api.wait_update() if api.is_changing(quote): print("最新价", quote.datetime, quote.last_price)
else: return 0 def long_shortposition(): if direction_long.iloc[-1] < direction_long.iloc[-2] and macd_long[ 'bar'].iloc[-1] < 0: return 1 else: return 0 while True: api.wait_update() # 每次k线更新,判断MACD的红绿柱和均线的方向 if api.is_changing(klines.iloc[-1], "datetime"): direction = tafunc.ema2(klines.close, EMA2_long) direction_long = tafunc.ema2(klines_long.close, EMA2_long) if direction.iloc[-1] > direction.iloc[-2] and direction_long.iloc[ -1] > direction_long.iloc[-2]: print("小周期上涨,大周期也上涨") elif direction.iloc[-1] < direction.iloc[-2] and direction_long.iloc[ -1] > direction_long.iloc[-2]: print("小周期下跌趋势,大周期上涨趋势") elif direction.iloc[-1] < direction.iloc[-2] and direction_long.iloc[ -1] < direction_long.iloc[-2]: print("大小周期都在下跌") macd = MACD(klines, 12, 26, 9) macd_long = MACD(klines_long, 12, 26, 9) if macd['bar'].iloc[-1] > 0 and macd_long['bar'].iloc[-1] > 0:
or (lt.tm_wday == 4 and lt.tm_hour == 22 and lt.tm_min >= 55 and lt.tm_min <= 58)): # 周五 night #pos_manage.close() strage_manager.close() #pos_manage.close() init_flag = False continue elif (lt.tm_hour == 14 and lt.tm_min == 59 and lt.tm_sec == 1): #mc_indictor.on_day_bar(day_klines) #stg_watcher.on_day_bar(day_klines) continue #stg_grid.run(klines, serial.iloc[-1].ask_price1, serial.iloc[-1].bid_price1) #stg_avg.run(klines, serial.iloc[-1].ask_price1, serial.iloc[-1].bid_price1) # bid_price 买价,ask_price 卖价 if api.is_changing(day_klines.iloc[-1], "datetime"): print(".................on day bar....................") #mc_indictor.on_day_bar(day_klines) #stg_watcher.on_day_bar(day_klines) strage_manager.on_day_bar(day_klines) if api.is_changing(klines.iloc[-1], "datetime"): #strage_manager.run(klines, serial.iloc[-1].ask_price1, serial.iloc[-1].bid_price1, serial.iloc[-1].average) strage_manager.on_bar(klines) avg_recorder.on_bar(klines) #print("lt.tm_min=%d lt.tm_sec=%d"%(lt.tm_min, lt.tm_sec)) strage_manager.on_tick(serial) avg_recorder.on_tick(serial) # pos_manage.check()
# api = TqApi('SIM') quote = api.get_quote(SYMBOL) klines_15 = api.get_kline_serial(SYMBOL, duration_seconds=15 * 60) klines_1 = api.get_kline_serial(SYMBOL, duration_seconds=60) position = api.get_position(SYMBOL) target_pos = TargetPosTask(api, SYMBOL) target_pos_value = position["volume_long"] - position[ "volume_short"] # 净目标净持仓数 account = api.get_account() with closing(api): while True: target_pos.set_target_volume(target_pos_value) api.wait_update() if api.is_changing(klines_15[-1], 'datetime'): k15 = str(dt.datetime.fromtimestamp(klines_15.datetime[-1] / 1e9)) print(k15) ys = pd.Series(data=klines_15.close[-40:], index=[ str(dt.datetime.fromtimestamp(i / 1e9)) for i in klines_15.datetime[-40:] ]) dict_results = BB(ys) print('Up', dict_results['Up'][-1]) print('Mid', dict_results['Mid'][-1]) print('Low', dict_results['Low'][-1]) if target_pos_value == 0:
) and val['status'] != 'FINISHED': un_buy_close[secid].append(order_id) elif val['direction'] == 'SELL' and (val['offset'] == 'CLOSE' or val['offset'] == 'CLOSETODAY' ) and val['status'] != 'FINISHED': un_sell_close[secid].append(order_id) #api.wait_update() setScheduler() # 执行轮询任务 exit_flag = 0 while True: api.wait_update() for sec in SEC_LIST: ndate = quotes[sec].datetime if ndate > '2021-10-02': log.logger.info('当前程序已过有效期,即将退出程序...') exit_flag = 1 break if api.is_changing(klines_dict[sec].iloc[-1], "datetime"): log.logger.info('------------------------------------------') log.logger.info('{0}新K线时间:{1}'.format( sec, datetime.datetime.fromtimestamp( klines_dict[sec].iloc[-1]["datetime"] / 1e9))) log.logger.info('账户权益:{0}'.format(account.balance)) run_trade(sec) if exit_flag == 1: break api.close()
def TianqinBacktesing(start_date, end_date, symbol, duration_seconds, init_balance=200000): # TqBacktest api = TqApi(TqSim(init_balance=init_balance), backtest=TqBacktest(start_dt=start_date, end_dt=end_date)) # TqBacktest with Tianqin Terminal # api = TqApi('SIM', backtest=TqBacktest(start_dt=start_date, end_dt=end_date)) quote = api.get_quote(symbol) klines = api.get_kline_serial(symbol, duration_seconds=duration_seconds) # 日线 target_pos = TargetPosTask(api, symbol) with closing(api): try: while True: while not api.is_changing(klines[-1], "datetime"): # 等到达下一个交易日 api.wait_update() while True: api.wait_update() # 在收盘后预测下一交易日的涨跌情况 if api.is_changing(quote, "datetime"): now = dt.datetime.strptime( quote["datetime"], "%Y-%m-%d %H:%M:%S.%f") # 当前quote的时间 print(now) # 判断是否到达预定收盘时间: 如果到达 则认为本交易日收盘, 此时预测下一交易日的涨跌情况, 并调整为对应仓位 # if now.hour == close_hour and now.minute >= close_minute: # # 1- 获取数据 # x_train, y_train, x_predict = get_prediction_data(klines, 75) # 参数1: K线, 参数2:需要的数据长度 # # # 2- 利用机器学习算法预测下一个交易日的涨跌情况 # # n_estimators 参数: 选择森林里(决策)树的数目; bootstrap 参数: 选择建立决策树时,是否使用有放回抽样 # clf = RandomForestClassifier(n_estimators=30, bootstrap=True) # clf.fit(x_train, y_train) # 传入训练数据, 进行参数训练 # predictions.append(bool(clf.predict([x_predict]))) # 传入测试数据进行预测, 得到预测的结果 # # # 3- 进行交易 # if predictions[-1] == True: # 如果预测结果为涨: 买入 # print(quote["datetime"], "预测下一交易日为 涨") # target_pos.set_target_volume(10) # else: # 如果预测结果为跌: 卖出 # print(quote["datetime"], "预测下一交易日为 跌") # target_pos.set_target_volume(-10) # break except BacktestFinished: # 回测结束, 获取预测结果,统计正确率 # df_klines = klines.to_dataframe() # 将K线序列中的数据转换为 pandas.DataFrame # df_klines["pre_close"] = df_klines["close"].shift(1) # 增加 pre_close(上一交易日的收盘价) 字段 # df_klines = df_klines[-len(predictions) + 1:] # 取出在回测日期内的K线数据 # df_klines["prediction"] = predictions[:-1] # 增加预测的本交易日涨跌情况字段(向后移一个数据目的: 将 本交易日对应下一交易日的涨跌 调整为 本交易日对应本交易日的涨跌) # results = (df_klines["close"] - df_klines["pre_close"] >= 0) == df_klines["prediction"] # # print(df_klines) print("----回测结束----") # print("预测结果正误:\n", results) # print("预测结果数目统计: 总计", len(results), "个预测结果") # print(pd.value_counts(results)) # print("预测的准确率:") # print((pd.value_counts(results)[True]) / len(results)) return BacktestFinished
x_train = x_all[: -1] # 训练数据: 特征 x_predict = x_all[-1] # 预测数据(用本交易日的指标预测下一交易日的涨跌) y_train = y_all[1:] # 训练数据: 标签 (去掉第一个数据后让其与指标隔一位对齐(例如: 昨天的特征 -> 对应预测今天的涨跌标签)) return x_train, y_train, x_predict predictions = [] # 用于记录每次的预测结果(在每个交易日收盘时用收盘数据预测下一交易日的涨跌,并记录在此列表里) api = TqApi(backtest=TqBacktest(start_dt=datetime.date(2018, 7, 2), end_dt=datetime.date(2018, 9, 26)), auth=TqAuth("信易账户", "账户密码")) quote = api.get_quote(symbol) klines = api.get_kline_serial(symbol, duration_seconds=24 * 60 * 60) # 日线 target_pos = TargetPosTask(api, symbol) with closing(api): try: while True: while not api.is_changing(klines.iloc[-1], "datetime"): # 等到达下一个交易日 api.wait_update() while True: api.wait_update() # 在收盘后预测下一交易日的涨跌情况 if api.is_changing(quote, "datetime"): now = datetime.datetime.strptime(quote.datetime, "%Y-%m-%d %H:%M:%S.%f") # 当前quote的时间 # 判断是否到达预定收盘时间: 如果到达 则认为本交易日收盘, 此时预测下一交易日的涨跌情况, 并调整为对应仓位 if now.hour == close_hour and now.minute >= close_minute: # 1- 获取数据 x_train, y_train, x_predict = get_prediction_data(klines, 75) # 参数1: K线, 参数2:需要的数据长度 # 2- 利用机器学习算法预测下一个交易日的涨跌情况 # n_estimators 参数: 选择森林里(决策)树的数目; bootstrap 参数: 选择建立决策树时,是否使用有放回抽样 clf = RandomForestClassifier(n_estimators=30, bootstrap=True) clf.fit(x_train, y_train) # 传入训练数据, 进行参数训练
# "duration_seconds=60"为一分钟线, 日线的duration_seconds参数为: 24*60*60 klines = api.get_kline_serial(SYMBOL, duration_seconds=1*60, data_length=data_length) #收盘后不可查 target_pos = TargetPosTask(api, SYMBOL) position = api.get_position(SYMBOL)#指定一个品种查看持仓相关信息 account = api.get_account()#获取用户账户资金信息 while True: api.wait_update() if api.is_changing(klines.iloc[-1], "datetime"): # 产生新k线:重新计算SMA klines["ma5"]=ma(klines["close"], 5) klines["ma10"]=ma(klines["close"], 10) klines["ma89"]=ma(klines["close"], 89) klines["ma144"]=ma(klines["close"], 144) sar=SAR(klines, 4, 0.02, 0.2) if api.is_changing(klines.iloc[-1], "datetime"): # 产生新k线:重新计算SMA if klines['close'].iloc[-1] < klines['ma89'].iloc[-2]: if klines["ma5"].iloc[-2] < klines["ma10"].iloc[-2] and klines["ma10"].iloc[-1] > klines["ma5"].iloc[-1]: target_pos.set_target_volume(-1) print("均线下穿,做空") elif klines["close"].iloc[-2] > klines["ma5"].iloc[-2]: target_pos.set_target_volume(0) print("均线上穿,平空")
def double_moving_average(api: TqApi, symbol: str, max_position: int = 10, fast: int = 5, slow: int = 20): strategy_name: str = 'DoubleMovingAverage' api: TqApi = api symbol: str = symbol timeout: int = 5 max_position: int = max_position fast: int = fast slow: int = slow ma: DataFrame = DataFrame() tq_account: Account = api.get_account() tq_position: Position = api.get_position(symbol) tq_candlestick: DataFrame = api.get_kline_serial(symbol=symbol, duration_seconds=24 * 60 * 60) tq_target_pos = TargetPosTask(api, symbol) deadline: float try: while True: deadline = time.time() + timeout if not api.wait_update(deadline=deadline): raise RuntimeError('没有在规定时间内获得数据!') # api.wait_update() if api.is_changing(tq_candlestick): ma['fast'] = tafunc.ma(tq_candlestick.close, fast) ma['slow'] = tafunc.ma(tq_candlestick.close, slow) tq_candlestick['ma_fast'] = ma['fast'] tq_candlestick['ma_fast.color'] = 'green' tq_candlestick['ma_slow'] = ma['slow'] tq_candlestick['ma_slow.color'] = 0xFF9933CC # 最新的快均线数值 > 最新的慢均线数值,且 前一根快均线数值 < 前一根慢均线数值 # 即快均线从下向上穿过慢均线 if (ma['fast'].iloc[-1] > ma['slow'].iloc[-1] and ma['fast'].iloc[-2] < ma['slow'].iloc[-2]): # # 如果有空仓,平空仓 # if tq_position.pos_short > 0: # api.insert_order(symbol=symbol, # direction='BUY', # offset='CLOSE', # limit_price=tq_candlestick.close.iloc[-1], # volume=tq_position.pos_short # ) # # 开多仓 # api.insert_order(symbol=symbol, # direction='BUY', # offset='OPEN', # limit_price=tq_candlestick.close.iloc[-1], # volume=max_position # ) tq_target_pos.set_target_volume(max_position) # 最新的快均线数值 < 最新的慢均线数值,且 前一根快均线数值 > 前一根慢均线数值 # 即快均线从上向下穿过慢均线 if (ma['fast'].iloc[-1] < ma['slow'].iloc[-1] and ma['fast'].iloc[-2] > ma['slow'].iloc[-2]): # # 如果有多仓,平多仓 # if tq_position.pos_short > 0: # api.insert_order(symbol=symbol, # direction='SELL', # offset='CLOSE', # limit_price=tq_candlestick.close.iloc[-1], # volume=tq_position.pos_short # ) # # 开空仓 # api.insert_order(symbol=symbol, # direction='SELL', # offset='OPEN', # limit_price=tq_candlestick.close.iloc[-1], # volume=max_position # ) tq_target_pos.set_target_volume(-max_position) except BacktestFinished: api.close() print(f'参数: fast={fast}, slow={slow}, 最终权益={tq_account["balance"]}')
% (pivot, bBreak, sSetup, sEnter, bEnter, bSetup, sBreak)) return pivot, bBreak, sSetup, sEnter, bEnter, bSetup, sBreak quote = api.get_quote(SYMBOL) klines = api.get_kline_serial(SYMBOL, 24 * 60 * 60) # 86400: 使用日线 position = api.get_position(SYMBOL) target_pos = TargetPosTask(api, SYMBOL) target_pos_value = position.pos_long - position.pos_short # 净目标净持仓数 open_position_price = position.open_price_long if target_pos_value > 0 else position.open_price_short # 开仓价 pivot, bBreak, sSetup, sEnter, bEnter, bSetup, sBreak = get_index_line(klines) # 七条标准线 while True: target_pos.set_target_volume(target_pos_value) api.wait_update() if api.is_changing(klines.iloc[-1], "datetime"): # 产生新k线,则重新计算7条指标线 pivot, bBreak, sSetup, sEnter, bEnter, bSetup, sBreak = get_index_line(klines) if api.is_changing(quote, "datetime"): now = datetime.strptime(quote.datetime, "%Y-%m-%d %H:%M:%S.%f") if now.hour == CLOSE_HOUR and now.minute >= CLOSE_MINUTE: # 到达平仓时间: 平仓 print("临近本交易日收盘: 平仓") target_pos_value = 0 # 平仓 pivot = bBreak = sSetup = sEnter = bEnter = bSetup = sBreak = float("nan") # 修改各指标线的值, 避免平仓后再次触发 '''交易规则''' if api.is_changing(quote, "last_price"): print("最新价: %f" % quote.last_price) # 开仓价与当前行情价之差大于止损点则止损 if (target_pos_value > 0 and open_position_price - quote.last_price >= STOP_LOSS_PRICE) or \
# 计算每个时间单元的成交量预测值 predicted_volume = {} # 记录每个时间单元需调整的持仓量 percentage_left = 1 # 剩余比例 volume_left = TARGET_VOLUME # 剩余手数 for index, value in predicted_percent.items(): volume = round(volume_left * (value / percentage_left)) predicted_volume[index] = volume percentage_left -= value volume_left -= volume print("各时间单元应下单手数: %s" % predicted_volume) # 交易 current_volume = 0 # 记录已调整持仓量 while True: api.wait_update() # 新产生一根K线并且在计划交易时间段内: 调整目标持仓量 if api.is_changing(klines.iloc[-1], "datetime"): t = datetime.datetime.fromtimestamp(klines.iloc[-1]["datetime"] // 1000000000).time() if t in predicted_volume: current_volume += predicted_volume[t] print("到达下一时间单元,调整持仓为: %d" % current_volume) target_pos.set_target_volume(current_volume) # 用持仓信息判断是否完成所有目标交易手数 if api.is_changing(position, "volume_long") or api.is_changing( position, "volume_short"): if position["volume_long"] - position["volume_short"] == TARGET_VOLUME: break api.close()
# api = TqApi(TqAccount("快期模拟", "cjj208", "Chenjj1230")) api = TqApi(TqAccount("simnow", "090828", "jimc1230", front_broker='9999', front_url='tcp://180.168.146.187:10100'), web_gui="0.0.0.0:9876") # 获得 m2005 的持仓引用,当持仓有变化时 position 中的字段会对应更新 position = api.get_position("SHFE.rb2005") # 获得资金账户引用,当账户有变化时 account 中的字段会对应更新 account = api.get_account() # 下单并返回委托单的引用,当该委托单有变化时 order 中的字段会对应更新 order = api.insert_order(symbol="SHFE.rb2005", direction="BUY", offset="OPEN", volume=2, limit_price=3521) #canorder = api.cancel_order(order) while True: api.wait_update() if api.is_changing(order, ["status", "volume_orign", "volume_left"]): #subprocess.call("cls",shell=True) print("单状态: %s, 已成交: %d 手" % (order.status, order.volume_orign - order.volume_left)) if api.is_changing(position, "pos_long_today"): print("今多头: %d 手" % (position.pos_long_today)) if api.is_changing(account, "available"): print("可用资金: %.2f" % (account.available))
__author__ = 'chengzhi' from tqsdk import TqApi, TqAuth, TargetPosTask ''' 价差回归 当近月-远月的价差大于250时做空近月,做多远月 当价差小于200时平仓 ''' api = TqApi(auth=TqAuth("信易账户", "账户密码")) quote_near = api.get_quote("SHFE.rb2104") quote_deferred = api.get_quote("SHFE.rb2105") # 创建 rb2104 的目标持仓 task,该 task 负责调整 rb2104 的仓位到指定的目标仓位 target_pos_near = TargetPosTask(api, "SHFE.rb2104") # 创建 rb2105 的目标持仓 task,该 task 负责调整 rb2105 的仓位到指定的目标仓位 target_pos_deferred = TargetPosTask(api, "SHFE.rb2105") while True: api.wait_update() if api.is_changing(quote_near) or api.is_changing(quote_deferred): spread = quote_near.last_price - quote_deferred.last_price print("当前价差:", spread) if spread > 250: print("目标持仓: 空近月,多远月") # 设置目标持仓为正数表示多头,负数表示空头,0表示空仓 target_pos_near.set_target_volume(-1) target_pos_deferred.set_target_volume(1) elif spread < 200: print("目标持仓: 空仓") target_pos_near.set_target_volume(0) target_pos_deferred.set_target_volume(0)
def dual_thrust(quote, klines): current_open = klines[-1]["open"] HH = max(klines.high[-NDAY - 1:-1]) # N日最高价的最高价 HC = max(klines.close[-NDAY - 1:-1]) # N日收盘价的最高价 LC = min(klines.close[-NDAY - 1:-1]) # N日收盘价的最低价 LL = min(klines.low[-NDAY - 1:-1]) # N日最低价的最低价 range = max(HH - LC, HC - LL) buy_line = current_open + range * K1 # 上轨 sell_line = current_open - range * K2 # 下轨 logger.info("当前开盘价: %f, 上轨: %f, 下轨: %f" % (current_open, buy_line, sell_line)) return buy_line, sell_line buy_line, sell_line = dual_thrust(quote, klines) # 获取上下轨 while True: api.wait_update() if api.is_changing(klines[-1], ["datetime", "open"]): # 新产生一根日线或开盘价发生变化: 重新计算上下轨 buy_line, sell_line = dual_thrust(quote, klines) if api.is_changing(quote, "last_price"): if quote["last_price"] > buy_line: # 高于上轨 logger.info("高于上轨,目标持仓 多头3手") target_pos.set_target_volume(3) # 交易 elif quote["last_price"] < sell_line: # 低于下轨 logger.info("低于下轨,目标持仓 空头3手") target_pos.set_target_volume(-3) # 交易 else: logger.info('未穿越上下轨,不调整持仓')
return df_short ################################################################################# df_long = reset_df_long(quote, GRID_AMOUNT, grid_region_long, grid_volume_long) df_short = reset_df_short(quote, GRID_AMOUNT, grid_region_short, grid_volume_short) ################################################################################# while True: api.wait_update() ################################################################################# if api.is_changing(ticks): now = time_to_datetime(ticks.iloc[-1].datetime) if (now.hour >= 9 and now.hour < 15) or (now.hour >= 21 and now.hour < 23): if is_clear_all1: api.insert_order(symbol, "SELL", close, position.pos_long, quote.bid_price1 - 2) is_clear_all1 = False if is_clear_all2: api.insert_order(symbol, "BUY", close, position.pos_short, quote.ask_price1 + 2) is_clear_all2 = False ################################################################################# if api.is_changing(quote): df = pd.DataFrame(api.get_order().values()) if not df.empty:
symbol = "SHFE.cu2002" # 合约代码 close_hour, close_minute = 14, 50 # 平仓时间 api = TqApi() # 使用模拟帐号直连行情和交易服务器 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.pos_long == 0: # 如果价格突破上轨: 买入开仓 print("最新价:", quote.last_price, ", 价格突破上轨,买入开仓") target_pos.set_target_volume(3) # 设置目标持仓手数,将指定合约调整到目标头寸 elif quote.last_price < bottom_rail and position.pos_short == 0: # 如果价格跌破下轨: 卖出开仓 print("最新价:", quote.last_price, ", 价格跌破下轨, 卖出开仓") target_pos.set_target_volume(-3) # 平仓止损: 当价格 向上突破上轨 或 向下突破下轨 后, 再次回破当日开盘价
# dict_results = wave_check(ys, method='RW', w=1, iteration=0) api = TqApi(TqSim(), backtest=TqBacktest(start_dt=dt.datetime(2019, 1, 2), end_dt=dt.datetime(2019, 1, 3))) symbol = 'CFFEX.IF1903' quote = api.get_quote(symbol) klines = api.get_kline_serial(symbol, duration_seconds=60) target_pos = TargetPosTask(api, symbol) with closing(api): try: while True: api.wait_update() if api.is_changing(klines): try: now = dt.datetime.fromtimestamp(klines.datetime[-1] / 1e9) except: now = 'No data' # print(now) ys = pd.Series(data=klines.close[-40:], index=[ dt.datetime.fromtimestamp(i / 1e9) for i in klines.datetime[-40:] ]) dict_results = wave_check(ys, 'RW', w=3, iteration=0) Wave_up = dict_results['Up'] Wave_down = dict_results['Down'] MA = dict_results['MA']