Skip to content

Commit 4ce2488

Browse files
同步目录文档
1 parent 11f81c2 commit 4ce2488

File tree

153 files changed

+5084
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

153 files changed

+5084
-0
lines changed

doc/Makefile

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Minimal makefile for Sphinx documentation
2+
#
3+
4+
# You can set these variables from the command line.
5+
SPHINXOPTS =
6+
SPHINXBUILD = sphinx-build
7+
SPHINXPROJ = TianQin
8+
SOURCEDIR = .
9+
BUILDDIR = _build
10+
11+
# Put it first so that "make" without argument is like "make help".
12+
help:
13+
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
14+
15+
livehtml:
16+
sphinx-autobuild -b html $(SOURCEDIR) $(BUILDDIR)/html
17+
18+
.PHONY: help Makefile
19+
20+
# Catch-all target: route all unknown targets to Sphinx using the new
21+
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
22+
%: Makefile
23+
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

doc/_static/baidu.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
var _hmt = _hmt || [];
2+
(function() {
3+
var hm = document.createElement("script");
4+
hm.src = "https://hm.baidu.com/hm.js?f7292fcf4a7be122de798d24f80e32f6";
5+
var s = document.getElementsByTagName("script")[0];
6+
s.parentNode.insertBefore(hm, s);
7+
})();

doc/_static/demo_t10.png

210 KB
Loading

doc/_static/faq1.png

180 KB
Loading

doc/_static/trading_system.svg

Lines changed: 2 additions & 0 deletions
Loading

doc/advanced/backtest.rst

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
.. _batch_backtest:
2+
3+
批量回测, 参数搜索及其它
4+
=================================================
5+
在阅读本文档前, 请确保您已经熟悉了 :ref:`backtest`
6+
7+
参数优化/参数搜索
8+
-------------------------------------------------
9+
TqSdk 并不提供专门的参数优化机制. 您可以按照自己的需求, 针对可能的每个参数值安排一个回测, 观察它们的回测结果, 以简单的双均线策略为例::
10+
11+
from tqsdk import TqApi, TqAuth, TqSim, TargetPosTask, BacktestFinished, TqBacktest
12+
from tqsdk.tafunc import ma
13+
from datetime import date
14+
15+
LONG = 60
16+
SYMBOL = "SHFE.cu1907"
17+
18+
for SHORT in range(20, 40): # 短周期参数从20-40分别做回测
19+
acc = TqSim() # 每次回测都创建一个新的模拟账户
20+
try:
21+
api = TqApi(acc, backtest=TqBacktest(start_dt=date(2019, 5, 6), end_dt=date(2019, 5, 10)), auth=TqAuth("信易账户", "账户密码"))
22+
account = api.get_account()
23+
klines = api.get_kline_serial(SYMBOL, duration_seconds=60, data_length=LONG + 2)
24+
target_pos = TargetPosTask(api, SYMBOL)
25+
while True:
26+
api.wait_update()
27+
if api.is_changing(klines.iloc[-1], "datetime"):
28+
short_avg = ma(klines.close, SHORT)
29+
long_avg = ma(klines.close, LONG)
30+
if long_avg.iloc[-2] < short_avg.iloc[-2] and long_avg.iloc[-1] > short_avg.iloc[-1]:
31+
target_pos.set_target_volume(-1)
32+
if short_avg.iloc[-2] < long_avg.iloc[-2] and short_avg.iloc[-1] > long_avg.iloc[-1]:
33+
target_pos.set_target_volume(1)
34+
except BacktestFinished:
35+
api.close()
36+
print("SHORT=", SHORT, "最终权益=", account["balance"]) # 每次回测结束时, 输出使用的参数和最终权益
37+
38+
39+
多进程并发执行多个回测任务
40+
-------------------------------------------------
41+
如果您有大量回测任务想要尽快完成, 您首先需要一台给力的电脑(可以考虑到XX云上租一台32核的, 一小时几块钱). 然后您就可以并发执行N个回测了. 还是以上面的策略为例::
42+
43+
from tqsdk import TqApi, TqAuth, TqSim, TargetPosTask, BacktestFinished, TqBacktest
44+
from tqsdk.tafunc import ma
45+
from datetime import date
46+
import multiprocessing
47+
from multiprocessing import Pool
48+
49+
def MyStrategy(SHORT):
50+
LONG = 60
51+
SYMBOL = "SHFE.cu1907"
52+
acc = TqSim()
53+
try:
54+
api = TqApi(acc, backtest=TqBacktest(start_dt=date(2019, 5, 6), end_dt=date(2019, 5, 10)), auth=TqAuth("信易账户", "账户密码"))
55+
data_length = LONG + 2
56+
klines = api.get_kline_serial(SYMBOL, duration_seconds=60, data_length=data_length)
57+
target_pos = TargetPosTask(api, SYMBOL)
58+
while True:
59+
api.wait_update()
60+
if api.is_changing(klines.iloc[-1], "datetime"):
61+
short_avg = ma(klines.close, SHORT)
62+
long_avg = ma(klines.close, LONG)
63+
if long_avg.iloc[-2] < short_avg.iloc[-2] and long_avg.iloc[-1] > short_avg.iloc[-1]:
64+
target_pos.set_target_volume(-3)
65+
if short_avg.iloc[-2] < long_avg.iloc[-2] and short_avg.iloc[-1] > long_avg.iloc[-1]:
66+
target_pos.set_target_volume(3)
67+
except BacktestFinished:
68+
api.close()
69+
print("SHORT=", SHORT, "最终权益=", acc.account.balance) # 每次回测结束时, 输出使用的参数和最终权益
70+
71+
72+
if __name__ == '__main__':
73+
multiprocessing.freeze_support()
74+
p = Pool(4) # 进程池, 建议小于cpu数
75+
for s in range(20, 40):
76+
p.apply_async(MyStrategy, args=(s,)) # 把20个回测任务交给进程池执行
77+
print('Waiting for all subprocesses done...')
78+
p.close()
79+
p.join()
80+
print('All subprocesses done.')
81+
82+
**注意: 由于服务器流控限制, 同时执行的回测任务请勿超过10个**

doc/advanced/dingding.rst

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
.. _dingding:
2+
3+
将程序信息推送到手机端
4+
=================================================
5+
TqSdk 并不提供专门的服务器来推送消息,但是你可以通过其他 SDK 来做到这个效果,在发生成交或者条件满足时,进行消息推送,以钉钉为例::
6+
7+
from datetime import datetime, time, timedelta
8+
import requests
9+
from json import dumps
10+
from tqsdk import TqApi, TqAuth, TargetPosTask
11+
12+
13+
def send_msg(content):
14+
"""钉钉消息提醒模块"""
15+
webhook = "设置自己的钉钉 webhook"
16+
17+
# 钉钉安全规则将 天勤量化 设为关键字
18+
msg = {"msgtype": "text",
19+
"text": {"content": "{}\n{}\n".format("天勤量化\n" + content,
20+
datetime.now().strftime("%Y-%m-%d %H:%M:%S"))}, }
21+
headers = {"content-type": "application/json;charset=utf-8"}
22+
body = dumps(msg)
23+
requests.post(webhook, data=body, headers=headers)
24+
print(content)
25+
26+
27+
api = TqApi(auth=TqAuth("信易账户", "账户密码"))
28+
quote = api.get_quote("SHFE.rb2109")
29+
target_pos = TargetPosTask(api, "SHFE.rb2110")
30+
send_msg("策略开始运行")
31+
a = 0
32+
while True:
33+
api.wait_update()
34+
# 通过本地变量 a 来避免多次发送钉钉消息触发流控
35+
if quote.last_price > 5110 and a == 0:
36+
send_msg("行情满足条件,开多头5手")
37+
target_pos.set_target_volume(5)
38+
a = 1
39+
40+
41+
具体说明,请参考 `钉钉操作手册 <https://developers.dingtalk.com/document/app/custom-robot-access>`_

doc/advanced/entry.rst

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
.. _entry:
2+
3+
策略程序的多种入口场景
4+
====================================================
5+
基于TqSdk开发的策略程序可能在多种场景下运行
6+
7+
用户自己在独立python环境下执行策略程序
8+
----------------------------------------------------
9+
一种常见的运行方式是用户自己运行python策略程序, 象这样::
10+
11+
$python3 my_prog.py
12+
13+
在这种场景下,用户需要在TqApi创建时提供必要的参数
14+
15+
TqApi 独立运行模拟交易
16+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
17+
创建 TqApi 实例时传入 TqSim ::
18+
19+
from tqsdk import TqApi, TqAuth, TqSim
20+
api = TqApi(TqSim(), auth=TqAuth("信易账户", "账户密码"))
21+
22+
或者不填其他参数, 默认为使用TqSim::
23+
24+
api = TqApi(auth=TqAuth("信易账户", "账户密码"))
25+
26+
27+
TqApi 独立运行实盘交易
28+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
29+
创建 TqApi 实例时传入 TqAccount ::
30+
31+
from tqsdk import TqApi, TqAuth, TqAccount
32+
api = TqApi(TqAccount("H海通期货", "022631", "123456"), auth=TqAuth("信易账户", "账户密码"))
33+
34+
特别的, 如果需要连接到期货公司的特定服务器, 可以在 TqAccount 中指定::
35+
36+
api = TqApi(TqAccount("H海通期货", "022631", "123456", front_broker="8888", front_url="tcp://134.232.123.33:41205"), auth=TqAuth("信易账户", "账户密码"))
37+
38+
如果要连接到自己架设的交易网关, 可以使用::
39+
40+
api = TqApi(TqAccount("H海通期货", "022631", "123456"), url="ws://202.33.21.34:7878/", auth=TqAuth("信易账户", "账户密码"))
41+
42+
43+
TqApi 独立运行回测
44+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
45+
创建 TqApi 实例时传入 TqBacktest ::
46+
47+
from tqsdk import TqApi, TqAuth, TqSim, TqBacktest
48+
api = TqApi(TqSim(), backtest=TqBacktest(start_dt=date(2018, 5, 1), end_dt=date(2018, 10, 1)), auth=TqAuth("信易账户", "账户密码"))
49+
50+
51+
由天勤拉起策略进程
52+
----------------------------------------------------
53+
策略程序由天勤拉起执行时, TqApi始终使用默认构造函数, 由天勤提供命令行参数设定策略程序运行方式. 命令行参数包括这些:
54+
55+
* _action : run/backtest/mdreplay, 指定运行方式
56+
* _tq_pid : int, 天勤进程ID. 策略进程会监控天勤进程的存活情况, 天勤进程退出时所有由天勤创建的策略进程都会自行终止
57+
* _tq_url : str, 天勤ws入口. 策略进程通过此端口与天勤通讯
58+
59+
当 _action == run 时, 策略程序按正常交易模式运行, 其它参数:
60+
61+
* _broker_id : str, 期货公司代码
62+
* _account_id : str, 用户账号
63+
* _password : str, 用户密码
64+
65+
当 _action == backtest 时, 策略程序按回测模式运行, 其它参数:
66+
67+
* _dt_start : YYYYMMDD, 回测起始日期
68+
* _dt_end : YYYYMMDD, 回测结束日期
69+
70+
当 _action == mdreplay 时, 策略程序按复盘模式运行, 其它参数:
71+
72+
* _ins_url : url, 合约服务地址
73+
* _md_url : url, 行情服务地址
74+
75+
76+
天勤发起实盘运行(含快期模拟)
77+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
78+
天勤通过命令行参数传递交易账户信息给策略进程::
79+
80+
$ python3 my_prog.py --_action=run --_tq_pid=3233 --_tq_url=ws://127.0.0.1:7777 --_broker_id=快期模拟 --_account_id=13012345678 --_password=123456
81+
82+
83+
天勤发起回测
84+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
85+
天勤通过命令行参数传递交易账户信息给策略进程::
86+
87+
$ python3 my_prog.py --_action=backtest --_tq_pid=3233 --_tq_url=ws://127.0.0.1:7777 --_dt_start=20180101 --_dt_end=20180630
88+
89+
90+
天勤发起复盘
91+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
92+
天勤先创建好复盘服务器, 再传递::
93+
94+
$ python3 my_prog.py --_action=mdreplay --_tq_pid=3233 --_tq_url=ws://127.0.0.1:7777 --_md_url=ws://239.12.212.34:43232/... --ins_url=http://123.23.12.34/...
95+
96+
97+
更复杂的情形
98+
----------------------------------------------------
99+
100+
将独立运行的策略进程连接到天勤作监控
101+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
102+
暂未支持
103+
104+

doc/advanced/evolution.rst

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
使用逐步完善的方式构建交易策略
2+
=================================================
3+
`TqSdk`_ 的目标是能尽可能减少编码环节引入的坑,而交易逻辑本身的坑则需要用户自己填,如果每次调整交易逻辑都需要大规模的代码重构会严重阻碍交易系统的演化。
4+
5+
`TqSdk`_ 鼓励使用线性的编码风格,因此可以做到小调交易逻辑只需小改,只有大调交易逻辑时才需要大改。以 `R-Breaker`_ 策略为例,
6+
第一版是留仓过夜,回测下来可能发现留仓过夜引入了很大的风险,却没有获得与风险对应的收益,因此修改交易策略,收盘前清仓离场,
7+
对应代码的修改只需在主循环中加入判断是否接近收盘并平仓::
8+
9+
if api.is_changing(quote, "datetime"):
10+
now = datetime.strptime(quote.datetime, "%Y-%m-%d %H:%M:%S.%f")
11+
if now.hour == close_hour and now.minute >= close_minute: # 到达平仓时间: 平仓
12+
print("临近本交易日收盘: 平仓")
13+
target_pos.set_target_volume(0) # 平仓
14+
deadline = time.time() + 60
15+
while api.wait_update(deadline=deadline): # 等待60秒
16+
pass
17+
api.close()
18+
break
19+
20+
上述代码在行情时间变化时判断是否接近收盘,如果是的话则将目标持仓设为0(即空仓)。由于下单之后不一定能立即成交,价格变化后可能还需撤单重下,
21+
因此等待一分钟后再退出,通常交易的合约不是太冷门的话一分钟应该足够了,如果不放心的话可以改为判断持仓手数是否为0。
22+
23+
更多的用例可以参见: https://doc.shinnytech.com/pysdk/latest/demo.html
24+
25+
26+
27+
28+
.. _TqSdk: https://doc.shinnytech.com/pysdk/latest/index.html
29+
.. _TqSim: https://doc.shinnytech.com/pysdk/latest/reference.html#tqsdk.sim.TqSim
30+
.. _get_kline_serial: https://doc.shinnytech.com/pysdk/latest/reference.html#tqsdk.api.TqApi.get_kline_serial
31+
.. _TargetPosTask: https://doc.shinnytech.com/pysdk/latest/reference.html#tqsdk.lib.TargetPosTask
32+
.. _wait_update: https://doc.shinnytech.com/pysdk/latest/reference.html#tqsdk.api.TqApi.wait_update
33+
.. _DIFF: https://doc.shinnytech.com/diff/latest/index.html
34+
.. _get_account: https://doc.shinnytech.com/pysdk/latest/reference.html#tqsdk.api.TqApi.get_account
35+
.. _get_quote: https://doc.shinnytech.com/pysdk/latest/reference.html#tqsdk.api.TqApi.get_quote
36+
.. _is_changing: https://doc.shinnytech.com/pysdk/latest/reference.html#tqsdk.api.TqApi.is_changing
37+
.. _TqBacktest: https://doc.shinnytech.com/pysdk/latest/reference.html#tqsdk.backtest.TqBacktest
38+
.. _R-Breaker: https://github.com/shinnytech/tqsdk-python/blob/master/tqsdk/demo/example/rbreaker.py

0 commit comments

Comments
 (0)