├── .gitignore
├── 1_数据获取
├── DataStruct(QA_fetch_adv).ipynb
├── JQDATA.ipynb
├── JQDATA.md
├── QAFetch.ipynb
├── QA_FINANCIAL.ipynb
└── 直接获取数据.ipynb
├── 2_类的测试与讲解
├── QAACCOUNT 保证金冻结释放测试.ipynb
├── QAAccount.ipynb
└── QAUSER.ipynb
├── 4_回测实盘交易
├── Monitor.ipynb
├── QATTS_caitong_test.py
├── QATTS_caitong_with_QAMarket.ipynb
├── QA_MARKETENGINE.py
├── TEST_ACCOUNT_SELLOPEN_T0.ipynb
└── 回测
│ ├── 期货回测
│ └── future_min_backtest.py
│ ├── 股票回测
│ ├── 基于QAMARKET的回测
│ │ ├── backtest.py
│ │ ├── minstrategy.py
│ │ └── strategy.py
│ ├── 多季度选股择时回测.py
│ ├── 简易回测
│ │ ├── MACD_JCSC.py
│ │ ├── simple_minbacktest.py
│ │ └── simplebacktest.py
│ └── 超级简化版回测
│ │ ├── MACD_JCSC.py
│ │ ├── simple_minbacktest.py
│ │ └── simplebacktest.py
│ └── 股票日内交易回测
│ └── T0backtest.py
├── QAMARKET 相关
├── MARKET.ipynb
├── QA_MARKETENGINE.ipynb
├── generate_trade.ipynb
└── 期货账户测试.ipynb
├── config
├── install_ubuntu.sh
├── readme.md
├── run_backend.sh
├── startjupyter.sh
├── ubuntu16.sh
├── update_all.py
├── update_data.py
├── update_x.py
└── windows_autojob_updatedata.md
├── readme.md
├── research
├── RNN_EXAMPLE
│ ├── RNN-example_using_keras.ipynb
│ └── RNN-example_using_keras.py
├── 一个VIX指标的实现.ipynb
├── 盘中涨停分析
│ ├── 盘中涨停_2018-07-13.ipynb
│ └── 盘中涨停_2018-07-13.md
└── 马科维茨有效前沿实现
│ ├── output_19_1.png
│ ├── output_34_1.png
│ ├── output_6_1.png
│ ├── output_9_1.png
│ ├── 马科维茨的QUANTAXIS实现.ipynb
│ └── 马科维茨的QUANTAXIS实现.md
├── startjupyter.bat
├── startjupyter.sh
└── test_backtest
├── FUTURE
├── TEST 期货的多空下单.ipynb
├── TEST_保证金账户.ipynb
├── test_开平仓.ipynb
├── 期货TEST.ipynb
└── 期货分钟线回测.ipynb
├── MIN LEVEL SIMPLE BACKTEST.ipynb
├── PERFORMANCE.ipynb
├── PERFORMANCE.py
├── QAMARKET_SyncOrderExample.py
├── QUANTAXIS回测分析全过程讲解.ipynb
├── T0backtest.ipynb
├── T0backtest.py
├── TEST_ ORDER(stock+T0+Future).ipynb
├── TEST_MARKET_SETTLE.ipynb
├── TEST_MARKET_SETTLE.py
├── TEST_MULTI_ACCOUNT_INSERT_ORDER.ipynb
├── backtest_debug.py
├── example
├── indicator
│ └── macd.py
└── simple_backtest_day.py
├── make_order.md
├── strategy_qsdd.py
├── test_insert_orderspeed.py
├── test_开平仓_保证金.ipynb
├── 关于1.1.0的quantaxis的账户,市场,实盘模拟盘回测.ipynb
└── 国产软件指数计算.ipynb
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | env/
12 | build/
13 | develop-eggs/
14 | dist/
15 | downloads/
16 | eggs/
17 | .eggs/
18 | lib/
19 | lib64/
20 | parts/
21 | sdist/
22 | var/
23 | wheels/
24 | *.egg-info/
25 | .installed.cfg
26 | *.egg
27 |
28 | # PyInstaller
29 | # Usually these files are written by a python script from a template
30 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
31 | *.manifest
32 | *.spec
33 |
34 | # Installer logs
35 | pip-log.txt
36 | pip-delete-this-directory.txt
37 |
38 | # Unit test / coverage reports
39 | htmlcov/
40 | .tox/
41 | .coverage
42 | .coverage.*
43 | .cache
44 | nosetests.xml
45 | coverage.xml
46 | *.cover
47 | .hypothesis/
48 |
49 | # Translations
50 | *.mo
51 | *.pot
52 |
53 | # Django stuff:
54 | *.log
55 | local_settings.py
56 |
57 | # Flask stuff:
58 | instance/
59 | .webassets-cache
60 |
61 | # Scrapy stuff:
62 | .scrapy
63 |
64 | # Sphinx documentation
65 | docs/_build/
66 |
67 | # PyBuilder
68 | target/
69 |
70 | # Jupyter Notebook
71 | .ipynb_checkpoints
72 |
73 | # pyenv
74 | .python-version
75 |
76 | # celery beat schedule file
77 | celerybeat-schedule
78 |
79 | # SageMath parsed files
80 | *.sage.py
81 |
82 | # dotenv
83 | .env
84 |
85 | # virtualenv
86 | .venv
87 | venv/
88 | ENV/
89 |
90 | # Spyder project settings
91 | .spyderproject
92 | .spyproject
93 |
94 | # Rope project settings
95 | .ropeproject
96 |
97 | # mkdocs documentation
98 | /site
99 |
100 | # mypy
101 | .mypy_cache/
102 |
103 | # html file generate by QUANTAXIS
104 | *.html
--------------------------------------------------------------------------------
/1_数据获取/JQDATA.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 1,
6 | "metadata": {},
7 | "outputs": [],
8 | "source": [
9 | "from jqdatasdk import *\n",
10 | "from pyecharts import Kline,Bar,Grid"
11 | ]
12 | },
13 | {
14 | "cell_type": "markdown",
15 | "metadata": {},
16 | "source": [
17 | "首先我们先应JQDATA 的活动演示一下如何调用pyecharts 画图"
18 | ]
19 | },
20 | {
21 | "cell_type": "code",
22 | "execution_count": 3,
23 | "metadata": {},
24 | "outputs": [
25 | {
26 | "name": "stdout",
27 | "output_type": "stream",
28 | "text": [
29 | "auth success\n"
30 | ]
31 | }
32 | ],
33 | "source": [
34 | "auth('acc','password')\n",
35 | "data=get_price('000001.XSHE')"
36 | ]
37 | },
38 | {
39 | "cell_type": "markdown",
40 | "metadata": {},
41 | "source": [
42 | "先打印下 data\n",
43 | "我们可以看到 jqdata返回的格式是 一个单index的Dataframe"
44 | ]
45 | },
46 | {
47 | "cell_type": "code",
48 | "execution_count": 9,
49 | "metadata": {},
50 | "outputs": [
51 | {
52 | "data": {
53 | "text/html": [
54 | "
\n",
55 | "\n",
68 | "
\n",
69 | " \n",
70 | " \n",
71 | " | \n",
72 | " open | \n",
73 | " close | \n",
74 | " high | \n",
75 | " low | \n",
76 | " volume | \n",
77 | " money | \n",
78 | "
\n",
79 | " \n",
80 | " \n",
81 | " \n",
82 | " 2015-01-05 | \n",
83 | " 10.53 | \n",
84 | " 10.55 | \n",
85 | " 10.72 | \n",
86 | " 10.27 | \n",
87 | " 434357784.0 | \n",
88 | " 4.565388e+09 | \n",
89 | "
\n",
90 | " \n",
91 | " 2015-01-06 | \n",
92 | " 10.44 | \n",
93 | " 10.39 | \n",
94 | " 10.79 | \n",
95 | " 10.24 | \n",
96 | " 328971478.0 | \n",
97 | " 3.453446e+09 | \n",
98 | "
\n",
99 | " \n",
100 | " 2015-01-07 | \n",
101 | " 10.25 | \n",
102 | " 10.19 | \n",
103 | " 10.42 | \n",
104 | " 10.08 | \n",
105 | " 258163619.0 | \n",
106 | " 2.634796e+09 | \n",
107 | "
\n",
108 | " \n",
109 | " 2015-01-08 | \n",
110 | " 10.21 | \n",
111 | " 9.85 | \n",
112 | " 10.25 | \n",
113 | " 9.81 | \n",
114 | " 213761656.0 | \n",
115 | " 2.128003e+09 | \n",
116 | "
\n",
117 | " \n",
118 | " 2015-01-09 | \n",
119 | " 9.81 | \n",
120 | " 9.93 | \n",
121 | " 10.45 | \n",
122 | " 9.69 | \n",
123 | " 380916192.0 | \n",
124 | " 3.835378e+09 | \n",
125 | "
\n",
126 | " \n",
127 | "
\n",
128 | "
"
129 | ],
130 | "text/plain": [
131 | " open close high low volume money\n",
132 | "2015-01-05 10.53 10.55 10.72 10.27 434357784.0 4.565388e+09\n",
133 | "2015-01-06 10.44 10.39 10.79 10.24 328971478.0 3.453446e+09\n",
134 | "2015-01-07 10.25 10.19 10.42 10.08 258163619.0 2.634796e+09\n",
135 | "2015-01-08 10.21 9.85 10.25 9.81 213761656.0 2.128003e+09\n",
136 | "2015-01-09 9.81 9.93 10.45 9.69 380916192.0 3.835378e+09"
137 | ]
138 | },
139 | "execution_count": 9,
140 | "metadata": {},
141 | "output_type": "execute_result"
142 | }
143 | ],
144 | "source": [
145 | "\n",
146 | "data.head()"
147 | ]
148 | },
149 | {
150 | "cell_type": "markdown",
151 | "metadata": {},
152 | "source": [
153 | "在画K线图的时候, 我们需要的是上下两个部分\n",
154 | ""
155 | ]
156 | },
157 | {
158 | "cell_type": "code",
159 | "execution_count": 12,
160 | "metadata": {},
161 | "outputs": [],
162 | "source": [
163 | "\n",
164 | "# 因此我们初始化2个部分\n",
165 | "\n",
166 | "kline=Kline(width=1360, height=700, page_title='000001')\n",
167 | "\n",
168 | "bar = Bar()\n",
169 | "\n"
170 | ]
171 | },
172 | {
173 | "cell_type": "markdown",
174 | "metadata": {},
175 | "source": [
176 | "然后我们需要对数据进行初步的处理:\n",
177 | "\n",
178 | "- 首先处理横坐标轴(时间轴)\n",
179 | "- 分别处理 价格轴/量轴"
180 | ]
181 | },
182 | {
183 | "cell_type": "code",
184 | "execution_count": 13,
185 | "metadata": {},
186 | "outputs": [],
187 | "source": [
188 | "import numpy as np\n",
189 | "import pandas as pd\n",
190 | "\n",
191 | "# 做横轴的处理\n",
192 | "datetime = np.array(data.index.map(str))"
193 | ]
194 | },
195 | {
196 | "cell_type": "code",
197 | "execution_count": 15,
198 | "metadata": {},
199 | "outputs": [],
200 | "source": [
201 | "ohlc = np.array(data.loc[:, ['open', 'close', 'low', 'high']])\n",
202 | "vol = np.array(data.volume)"
203 | ]
204 | },
205 | {
206 | "cell_type": "markdown",
207 | "metadata": {},
208 | "source": [
209 | "将数据加载到kline和bar中"
210 | ]
211 | },
212 | {
213 | "cell_type": "code",
214 | "execution_count": 17,
215 | "metadata": {},
216 | "outputs": [],
217 | "source": [
218 | "kline.add('000001', datetime, ohlc, mark_point=[\n",
219 | " \"max\", \"min\"], is_datazoom_show=False, datazoom_orient='horizontal')\n",
220 | "\n",
221 | "bar.add('000001', datetime, vol,\n",
222 | " is_datazoom_show=True,\n",
223 | " datazoom_xaxis_index=[0, 1])"
224 | ]
225 | },
226 | {
227 | "cell_type": "markdown",
228 | "metadata": {},
229 | "source": [
230 | "使用Grid组合两个图"
231 | ]
232 | },
233 | {
234 | "cell_type": "code",
235 | "execution_count": 19,
236 | "metadata": {},
237 | "outputs": [],
238 | "source": [
239 | "grid = Grid(width=1360, height=700, page_title='QUANTAXIS')\n",
240 | "grid.add(bar, grid_top=\"80%\")\n",
241 | "grid.add(kline, grid_bottom=\"30%\")\n"
242 | ]
243 | },
244 | {
245 | "cell_type": "code",
246 | "execution_count": 21,
247 | "metadata": {},
248 | "outputs": [],
249 | "source": [
250 | "grid.render('000001_plot.html')"
251 | ]
252 | },
253 | {
254 | "cell_type": "markdown",
255 | "metadata": {},
256 | "source": [
257 | "使用 webbrowser 打开并渲染这个图\n",
258 | ""
259 | ]
260 | },
261 | {
262 | "cell_type": "code",
263 | "execution_count": 23,
264 | "metadata": {},
265 | "outputs": [
266 | {
267 | "data": {
268 | "text/plain": [
269 | "True"
270 | ]
271 | },
272 | "execution_count": 23,
273 | "metadata": {},
274 | "output_type": "execute_result"
275 | }
276 | ],
277 | "source": [
278 | "import webbrowser\n",
279 | "webbrowser.open('000001_plot.html')"
280 | ]
281 | },
282 | {
283 | "cell_type": "code",
284 | "execution_count": 21,
285 | "metadata": {},
286 | "outputs": [
287 | {
288 | "data": {
289 | "text/plain": [
290 | "'\\n以上是jqdata和pyecharts的结合, 不过QUANTAXIS已经对于这些进行了封装 只需要转化jqdata获取回来的数据为QADataStruct即可\\n'"
291 | ]
292 | },
293 | "execution_count": 21,
294 | "metadata": {},
295 | "output_type": "execute_result"
296 | }
297 | ],
298 | "source": [
299 | "\"\"\"\n",
300 | "以上是jqdata和pyecharts的结合, 不过QUANTAXIS已经对于这些进行了封装 只需要转化jqdata获取回来的数据为QADataStruct即可\n",
301 | "\"\"\""
302 | ]
303 | },
304 | {
305 | "cell_type": "code",
306 | "execution_count": 22,
307 | "metadata": {},
308 | "outputs": [],
309 | "source": [
310 | "import QUANTAXIS as QA"
311 | ]
312 | },
313 | {
314 | "cell_type": "code",
315 | "execution_count": 23,
316 | "metadata": {},
317 | "outputs": [],
318 | "source": [
319 | "qads=QA.QAData.QA_DataStruct_Stock_day(data.assign(date=data.index,code='000001').set_index(['date','code']))"
320 | ]
321 | },
322 | {
323 | "cell_type": "code",
324 | "execution_count": 24,
325 | "metadata": {},
326 | "outputs": [
327 | {
328 | "data": {
329 | "text/plain": [
330 | "< QA_DataStruct_Stock_day with 1 securities >"
331 | ]
332 | },
333 | "execution_count": 24,
334 | "metadata": {},
335 | "output_type": "execute_result"
336 | }
337 | ],
338 | "source": [
339 | "qads"
340 | ]
341 | },
342 | {
343 | "cell_type": "code",
344 | "execution_count": 38,
345 | "metadata": {},
346 | "outputs": [
347 | {
348 | "name": "stderr",
349 | "output_type": "stream",
350 | "text": [
351 | "QUANTAXIS>> The Pic has been saved to your path: .\\QA_stock_day_000001_bfq.html\n"
352 | ]
353 | }
354 | ],
355 | "source": [
356 | "qads.plot('000001')"
357 | ]
358 | }
359 | ],
360 | "metadata": {
361 | "kernelspec": {
362 | "display_name": "Python 3",
363 | "language": "python",
364 | "name": "python3"
365 | },
366 | "language_info": {
367 | "codemirror_mode": {
368 | "name": "ipython",
369 | "version": 3
370 | },
371 | "file_extension": ".py",
372 | "mimetype": "text/x-python",
373 | "name": "python",
374 | "nbconvert_exporter": "python",
375 | "pygments_lexer": "ipython3",
376 | "version": "3.6.6"
377 | }
378 | },
379 | "nbformat": 4,
380 | "nbformat_minor": 2
381 | }
382 |
--------------------------------------------------------------------------------
/1_数据获取/JQDATA.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ```python
4 | from jqdatasdk import *
5 | from pyecharts import Kline,Bar,Grid
6 | ```
7 |
8 | 首先我们先应JQDATA 的活动演示一下如何调用pyecharts 画图
9 |
10 |
11 | ```python
12 | auth('acc','password')
13 | data=get_price('000001.XSHE')
14 | ```
15 |
16 | auth success
17 |
18 |
19 | 先打印下 data
20 | 我们可以看到 jqdata返回的格式是 一个单index的Dataframe
21 |
22 |
23 | ```python
24 |
25 | data.head()
26 | ```
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | |
37 | open |
38 | close |
39 | high |
40 | low |
41 | volume |
42 | money |
43 |
44 |
45 |
46 |
47 | 2015-01-05 |
48 | 10.53 |
49 | 10.55 |
50 | 10.72 |
51 | 10.27 |
52 | 434357784.0 |
53 | 4.565388e+09 |
54 |
55 |
56 | 2015-01-06 |
57 | 10.44 |
58 | 10.39 |
59 | 10.79 |
60 | 10.24 |
61 | 328971478.0 |
62 | 3.453446e+09 |
63 |
64 |
65 | 2015-01-07 |
66 | 10.25 |
67 | 10.19 |
68 | 10.42 |
69 | 10.08 |
70 | 258163619.0 |
71 | 2.634796e+09 |
72 |
73 |
74 | 2015-01-08 |
75 | 10.21 |
76 | 9.85 |
77 | 10.25 |
78 | 9.81 |
79 | 213761656.0 |
80 | 2.128003e+09 |
81 |
82 |
83 | 2015-01-09 |
84 | 9.81 |
85 | 9.93 |
86 | 10.45 |
87 | 9.69 |
88 | 380916192.0 |
89 | 3.835378e+09 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 | 在画K线图的时候, 我们需要的是上下两个部分
98 | 
99 |
100 |
101 | ```python
102 |
103 | # 因此我们初始化2个部分
104 |
105 | kline=Kline(width=1360, height=700, page_title='000001')
106 |
107 | bar = Bar()
108 |
109 |
110 | ```
111 |
112 | 然后我们需要对数据进行初步的处理:
113 |
114 | - 首先处理横坐标轴(时间轴)
115 | - 分别处理 价格轴/量轴
116 |
117 |
118 | ```python
119 | import numpy as np
120 | import pandas as pd
121 |
122 | # 做横轴的处理
123 | datetime = np.array(data.index.map(str))
124 | ```
125 |
126 |
127 | ```python
128 | ohlc = np.array(data.loc[:, ['open', 'close', 'low', 'high']])
129 | vol = np.array(data.volume)
130 | ```
131 |
132 | 将数据加载到kline和bar中
133 |
134 |
135 | ```python
136 | kline.add('000001', datetime, ohlc, mark_point=[
137 | "max", "min"], is_datazoom_show=False, datazoom_orient='horizontal')
138 |
139 | bar.add('000001', datetime, vol,
140 | is_datazoom_show=True,
141 | datazoom_xaxis_index=[0, 1])
142 | ```
143 |
144 | 使用Grid组合两个图
145 |
146 |
147 | ```python
148 | grid = Grid(width=1360, height=700, page_title='QUANTAXIS')
149 | grid.add(bar, grid_top="80%")
150 | grid.add(kline, grid_bottom="30%")
151 |
152 | ```
153 |
154 |
155 | ```python
156 | grid.render('000001_plot.html')
157 | ```
158 |
159 | 使用 webbrowser 打开并渲染这个图
160 | 
161 |
162 |
163 | ```python
164 | import webbrowser
165 | webbrowser.open('000001_plot.html')
166 | ```
167 |
168 |
169 |
170 |
171 | True
172 |
173 |
174 |
175 |
176 | ```python
177 | """
178 | 以上是jqdata和pyecharts的结合, 不过QUANTAXIS已经对于这些进行了封装 只需要转化jqdata获取回来的数据为QADataStruct即可
179 | """
180 | ```
181 |
182 |
183 |
184 |
185 | '\n以上是jqdata和pyecharts的结合, 不过QUANTAXIS已经对于这些进行了封装 只需要转化jqdata获取回来的数据为QADataStruct即可\n'
186 |
187 |
188 |
189 |
190 | ```python
191 | import QUANTAXIS as QA
192 | ```
193 |
194 |
195 | ```python
196 | qads=QA.QAData.QA_DataStruct_Stock_day(data.assign(date=data.index,code='000001').set_index(['date','code']))
197 | ```
198 |
199 |
200 | ```python
201 | qads
202 | ```
203 |
204 |
205 |
206 |
207 | < QA_DataStruct_Stock_day with 1 securities >
208 |
209 |
210 |
211 |
212 | ```python
213 | qads.plot('000001')
214 | ```
215 |
216 | QUANTAXIS>> The Pic has been saved to your path: .\QA_stock_day_000001_bfq.html
217 |
218 |
--------------------------------------------------------------------------------
/2_类的测试与讲解/QAAccount.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# QAACCOUNT 账户类"
8 | ]
9 | },
10 | {
11 | "cell_type": "markdown",
12 | "metadata": {},
13 | "source": [
14 | "QA_Account() 是quantaxis的核心类, 其作用是一个可以使用规则兼容各种市场的账户类\n"
15 | ]
16 | },
17 | {
18 | "cell_type": "markdown",
19 | "metadata": {},
20 | "source": [
21 | "## 调用方式"
22 | ]
23 | },
24 | {
25 | "cell_type": "code",
26 | "execution_count": 2,
27 | "metadata": {},
28 | "outputs": [
29 | {
30 | "data": {
31 | "text/plain": [
32 | "< QA_Account Acc_nPadcmUk market: stock_cn>"
33 | ]
34 | },
35 | "execution_count": 2,
36 | "metadata": {},
37 | "output_type": "execute_result"
38 | }
39 | ],
40 | "source": [
41 | "import QUANTAXIS as QA\n",
42 | "QA.QA_Account()"
43 | ]
44 | },
45 | {
46 | "cell_type": "markdown",
47 | "metadata": {},
48 | "source": [
49 | "## 参数详解"
50 | ]
51 | },
52 | {
53 | "cell_type": "code",
54 | "execution_count": null,
55 | "metadata": {},
56 | "outputs": [],
57 | "source": [
58 | "# strategy_name=None,\n",
59 | "# user_cookie=None,\n",
60 | "# portfolio_cookie=None,\n",
61 | "# account_cookie=None,\n",
62 | "# market_type=MARKET_TYPE.STOCK_CN,\n",
63 | "# frequence=FREQUENCE.DAY,\n",
64 | "# broker=BROKER_TYPE.BACKETEST,\n",
65 | "# init_hold={},\n",
66 | "# init_cash=1000000,\n",
67 | "# commission_coeff=0.00025,\n",
68 | "# tax_coeff=0.001,\n",
69 | "# margin_level={},\n",
70 | "# allow_t0=False,\n",
71 | "# allow_sellopen=False,\n",
72 | "# allow_margin=False,\n",
73 | "# running_environment=RUNNING_ENVIRONMENT.BACKETEST"
74 | ]
75 | },
76 | {
77 | "cell_type": "markdown",
78 | "metadata": {},
79 | "source": [
80 | "## 基于规则实例化\n",
81 | "\n",
82 | "基于不同市场的不同规则, 我们可以实例化不同的账户类\n",
83 | "\n",
84 | "- 允许保证金交易: allow_marigin = True\n",
85 | "\n",
86 | "- 允许买入后当日卖出: allow_t0 = True\n",
87 | "\n",
88 | "- 允许卖空开仓(裸卖空): allow_sellopen= True"
89 | ]
90 | },
91 | {
92 | "cell_type": "markdown",
93 | "metadata": {},
94 | "source": [
95 | "### 股票普通账户"
96 | ]
97 | },
98 | {
99 | "cell_type": "code",
100 | "execution_count": null,
101 | "metadata": {},
102 | "outputs": [],
103 | "source": [
104 | "stock_account= QA.QA_Account(allow_t0=False,allow_margin=False,allow_sellopen=False,running_environment=QA.MARKET_TYPE.STOCK_CN)"
105 | ]
106 | },
107 | {
108 | "cell_type": "markdown",
109 | "metadata": {},
110 | "source": [
111 | "### 股票融资融券账户"
112 | ]
113 | },
114 | {
115 | "cell_type": "code",
116 | "execution_count": null,
117 | "metadata": {},
118 | "outputs": [],
119 | "source": [
120 | "rzrq_account = QA.QA_Account(allow_t0=False,allow_margin=True,allow_sellopen=True,running_environment=QA.MARKET_TYPE.STOCK_CN)"
121 | ]
122 | },
123 | {
124 | "cell_type": "markdown",
125 | "metadata": {},
126 | "source": [
127 | "### 期货账户"
128 | ]
129 | },
130 | {
131 | "cell_type": "code",
132 | "execution_count": null,
133 | "metadata": {},
134 | "outputs": [],
135 | "source": [
136 | "future_account = QA.QA_Account(allow_t0=True,allow_margin=True,allow_sellopen=True, running_environment=QA.MARKET_TYPE.FUTURE_CN)"
137 | ]
138 | },
139 | {
140 | "cell_type": "markdown",
141 | "metadata": {},
142 | "source": [
143 | "### 期权账户"
144 | ]
145 | },
146 | {
147 | "cell_type": "code",
148 | "execution_count": null,
149 | "metadata": {},
150 | "outputs": [],
151 | "source": [
152 | "option_account = QA.QA_Account(allow_t0=True,allow_margin=True,allow_sellopen=True, running_environment=QA.MARKET_TYPE.OPTION_CN)"
153 | ]
154 | },
155 | {
156 | "cell_type": "markdown",
157 | "metadata": {},
158 | "source": [
159 | "### 其他市场账户\n"
160 | ]
161 | },
162 | {
163 | "cell_type": "code",
164 | "execution_count": null,
165 | "metadata": {},
166 | "outputs": [],
167 | "source": [
168 | "xxx = QA.QA_Account(allow_t0=True,allow_margin=True,allow_sellopen=True, running_environment=QA.MARKET_TYPE.CRYPTOCURRENCY)"
169 | ]
170 | },
171 | {
172 | "cell_type": "markdown",
173 | "metadata": {},
174 | "source": [
175 | "## 账户的初始资金/初始仓位\n",
176 | "\n",
177 | "默认账户是无仓位, 默认现金 1000000 RMB\n"
178 | ]
179 | },
180 | {
181 | "cell_type": "code",
182 | "execution_count": null,
183 | "metadata": {},
184 | "outputs": [],
185 | "source": [
186 | "stock_account.init_assets"
187 | ]
188 | },
189 | {
190 | "cell_type": "code",
191 | "execution_count": null,
192 | "metadata": {},
193 | "outputs": [],
194 | "source": [
195 | "stock_account.init_cash"
196 | ]
197 | },
198 | {
199 | "cell_type": "code",
200 | "execution_count": null,
201 | "metadata": {},
202 | "outputs": [],
203 | "source": [
204 | "stock_account.init_hold"
205 | ]
206 | },
207 | {
208 | "cell_type": "markdown",
209 | "metadata": {},
210 | "source": [
211 | "### 在实例化的时候初始化仓位信息\n",
212 | "\n",
213 | "使用json/dict的格式初始化 \n",
214 | "\n",
215 | "```python\n",
216 | "# init_hold参数\n",
217 | "init_hold={code1:amount1,code2:amount2}\n",
218 | "```\n",
219 | "\n",
220 | "实例化完 会显示在 account.hold中\n",
221 | "\n",
222 | "[注意] 在t+1的账户中, 初始化仓位依然可以当日交易"
223 | ]
224 | },
225 | {
226 | "cell_type": "code",
227 | "execution_count": null,
228 | "metadata": {},
229 | "outputs": [],
230 | "source": [
231 | "stock_account= QA.QA_Account(init_hold={'000001':500}, allow_t0=False,allow_margin=False,allow_sellopen=False,running_environment=QA.MARKET_TYPE.STOCK_CN)"
232 | ]
233 | },
234 | {
235 | "cell_type": "code",
236 | "execution_count": null,
237 | "metadata": {},
238 | "outputs": [],
239 | "source": [
240 | "stock_account.init_assets"
241 | ]
242 | },
243 | {
244 | "cell_type": "code",
245 | "execution_count": null,
246 | "metadata": {},
247 | "outputs": [],
248 | "source": [
249 | "stock_account.hold"
250 | ]
251 | },
252 | {
253 | "cell_type": "code",
254 | "execution_count": null,
255 | "metadata": {},
256 | "outputs": [],
257 | "source": [
258 | "stock_account.sell_available"
259 | ]
260 | },
261 | {
262 | "cell_type": "markdown",
263 | "metadata": {},
264 | "source": [
265 | "### 在实例化的时候初始现金信息\n",
266 | "\n",
267 | "```python\n",
268 | "# init_cash 参数\n",
269 | "init_cash= 200000\n",
270 | "```\n"
271 | ]
272 | },
273 | {
274 | "cell_type": "code",
275 | "execution_count": null,
276 | "metadata": {},
277 | "outputs": [],
278 | "source": [
279 | "stock_account= QA.QA_Account(init_cash= 200000,init_hold={'000002':500}, allow_t0=False,allow_margin=False,allow_sellopen=False,running_environment=QA.MARKET_TYPE.STOCK_CN)"
280 | ]
281 | },
282 | {
283 | "cell_type": "code",
284 | "execution_count": null,
285 | "metadata": {},
286 | "outputs": [],
287 | "source": [
288 | "stock_account.init_assets"
289 | ]
290 | },
291 | {
292 | "cell_type": "code",
293 | "execution_count": null,
294 | "metadata": {},
295 | "outputs": [],
296 | "source": [
297 | "stock_account.init_cash"
298 | ]
299 | },
300 | {
301 | "cell_type": "code",
302 | "execution_count": null,
303 | "metadata": {},
304 | "outputs": [],
305 | "source": [
306 | "stock_account.cash"
307 | ]
308 | },
309 | {
310 | "cell_type": "code",
311 | "execution_count": null,
312 | "metadata": {},
313 | "outputs": [],
314 | "source": [
315 | "stock_account.cash_available"
316 | ]
317 | },
318 | {
319 | "cell_type": "markdown",
320 | "metadata": {},
321 | "source": [
322 | "### 在已经实例化的账户中修改现金/ 重置现金操作\n",
323 | "\n",
324 | "此操作无法撤销\n",
325 | "\n",
326 | "- 现金记录全部消除\n",
327 | "- 账户的持仓不会消除\n",
328 | "\n"
329 | ]
330 | },
331 | {
332 | "cell_type": "code",
333 | "execution_count": null,
334 | "metadata": {},
335 | "outputs": [],
336 | "source": [
337 | "stock_account.reset_assets(init_cash=50000)"
338 | ]
339 | },
340 | {
341 | "cell_type": "code",
342 | "execution_count": null,
343 | "metadata": {},
344 | "outputs": [],
345 | "source": [
346 | "stock_account.init_assets"
347 | ]
348 | },
349 | {
350 | "cell_type": "code",
351 | "execution_count": null,
352 | "metadata": {},
353 | "outputs": [],
354 | "source": [
355 | "stock_account.cash"
356 | ]
357 | },
358 | {
359 | "cell_type": "code",
360 | "execution_count": null,
361 | "metadata": {},
362 | "outputs": [],
363 | "source": [
364 | "stock_account.cash_available"
365 | ]
366 | },
367 | {
368 | "cell_type": "markdown",
369 | "metadata": {},
370 | "source": [
371 | "## 买入/卖出操作\n",
372 | "\n",
373 | "有2种方式可以买入/卖出品种\n",
374 | "\n",
375 | "1. send_order 接口 + Order类调用receive_deal 接口\n",
376 | "2. receive_simpledeal 接口\n",
377 | "\n",
378 | "\n",
379 | "其中 \n",
380 | "- 1 是基于账户-发出订单- 订单成交回报的模式更新账户\n",
381 | "- 2 是直接修改账户的模式, 由用户自行确认和保证成交\n"
382 | ]
383 | },
384 | {
385 | "cell_type": "markdown",
386 | "metadata": {},
387 | "source": [
388 | "### 订单/更新账户的模式\n",
389 | "\n",
390 | "在此我们只演示订单/成交, 至于order.trade怎么成交, 则是市场类/broker类的问题, 在此不去演示"
391 | ]
392 | },
393 | {
394 | "cell_type": "markdown",
395 | "metadata": {},
396 | "source": [
397 | "#### 生成订单"
398 | ]
399 | },
400 | {
401 | "cell_type": "code",
402 | "execution_count": null,
403 | "metadata": {},
404 | "outputs": [],
405 | "source": [
406 | "order=stock_account.send_order(code='000001',amount=100,time='2019-01-19',\n",
407 | " amount_model=QA.AMOUNT_MODEL.BY_AMOUNT,order_model=QA.ORDER_MODEL.CLOSE,\n",
408 | " price=10,towards=QA.ORDER_DIRECTION.BUY)"
409 | ]
410 | },
411 | {
412 | "cell_type": "code",
413 | "execution_count": null,
414 | "metadata": {},
415 | "outputs": [],
416 | "source": [
417 | "future_order=future_account.send_order(code='RB1905',amount=100,time='2019-01-19',\n",
418 | " amount_model=QA.AMOUNT_MODEL.BY_AMOUNT,order_model=QA.ORDER_MODEL.CLOSE,\n",
419 | " price=3500,towards=QA.ORDER_DIRECTION.BUY_OPEN)"
420 | ]
421 | },
422 | {
423 | "cell_type": "markdown",
424 | "metadata": {},
425 | "source": [
426 | "#### 订单类 QA_Order"
427 | ]
428 | },
429 | {
430 | "cell_type": "code",
431 | "execution_count": null,
432 | "metadata": {},
433 | "outputs": [],
434 | "source": [
435 | "order"
436 | ]
437 | },
438 | {
439 | "cell_type": "code",
440 | "execution_count": null,
441 | "metadata": {},
442 | "outputs": [],
443 | "source": [
444 | "future_order"
445 | ]
446 | },
447 | {
448 | "cell_type": "markdown",
449 | "metadata": {},
450 | "source": [
451 | "#### 订单交易(成交在Market/Broker中判断,此处只演示成交回报)"
452 | ]
453 | },
454 | {
455 | "cell_type": "code",
456 | "execution_count": null,
457 | "metadata": {},
458 | "outputs": [],
459 | "source": [
460 | "order.trade(trade_price=10.1,trade_amount=100,trade_id='example_trade1',trade_time='2019-01-19 15:00:00')"
461 | ]
462 | },
463 | {
464 | "cell_type": "code",
465 | "execution_count": null,
466 | "metadata": {},
467 | "outputs": [],
468 | "source": [
469 | "future_order.trade(trade_price=3600,trade_amount=100,trade_id='example_trade2',trade_time='2019-01-19 21:00:00')"
470 | ]
471 | },
472 | {
473 | "cell_type": "markdown",
474 | "metadata": {},
475 | "source": [
476 | "#### 账户成交表 QA_Account.history/QA_Account.history_table"
477 | ]
478 | },
479 | {
480 | "cell_type": "code",
481 | "execution_count": null,
482 | "metadata": {},
483 | "outputs": [],
484 | "source": [
485 | "stock_account.history_table"
486 | ]
487 | },
488 | {
489 | "cell_type": "code",
490 | "execution_count": null,
491 | "metadata": {},
492 | "outputs": [],
493 | "source": [
494 | "future_account.history_table"
495 | ]
496 | },
497 | {
498 | "cell_type": "markdown",
499 | "metadata": {},
500 | "source": [
501 | "#### 账户现金表/ 期货账户还会冻结资金(保证金)"
502 | ]
503 | },
504 | {
505 | "cell_type": "code",
506 | "execution_count": null,
507 | "metadata": {},
508 | "outputs": [],
509 | "source": [
510 | "stock_account.cash"
511 | ]
512 | },
513 | {
514 | "cell_type": "code",
515 | "execution_count": null,
516 | "metadata": {},
517 | "outputs": [],
518 | "source": [
519 | "future_account.cash"
520 | ]
521 | },
522 | {
523 | "cell_type": "code",
524 | "execution_count": null,
525 | "metadata": {},
526 | "outputs": [],
527 | "source": [
528 | "future_account.frozen"
529 | ]
530 | },
531 | {
532 | "cell_type": "markdown",
533 | "metadata": {},
534 | "source": [
535 | "#### 账户可用现金"
536 | ]
537 | },
538 | {
539 | "cell_type": "code",
540 | "execution_count": null,
541 | "metadata": {},
542 | "outputs": [],
543 | "source": [
544 | "stock_account.cash_available"
545 | ]
546 | },
547 | {
548 | "cell_type": "code",
549 | "execution_count": null,
550 | "metadata": {},
551 | "outputs": [],
552 | "source": [
553 | "future_account.cash_available"
554 | ]
555 | },
556 | {
557 | "cell_type": "markdown",
558 | "metadata": {},
559 | "source": [
560 | "#### 账户持仓"
561 | ]
562 | },
563 | {
564 | "cell_type": "code",
565 | "execution_count": null,
566 | "metadata": {},
567 | "outputs": [],
568 | "source": [
569 | "stock_account.hold"
570 | ]
571 | },
572 | {
573 | "cell_type": "code",
574 | "execution_count": null,
575 | "metadata": {},
576 | "outputs": [],
577 | "source": [
578 | "future_account.hold"
579 | ]
580 | },
581 | {
582 | "cell_type": "markdown",
583 | "metadata": {},
584 | "source": [
585 | "#### 账户可卖余额(股票T+1 因此可卖部分不增加/ 期货账户 t+0 因此可卖部分增加)"
586 | ]
587 | },
588 | {
589 | "cell_type": "code",
590 | "execution_count": null,
591 | "metadata": {},
592 | "outputs": [],
593 | "source": [
594 | "stock_account.sell_available"
595 | ]
596 | },
597 | {
598 | "cell_type": "code",
599 | "execution_count": null,
600 | "metadata": {},
601 | "outputs": [],
602 | "source": [
603 | "future_account.sell_available"
604 | ]
605 | },
606 | {
607 | "cell_type": "markdown",
608 | "metadata": {},
609 | "source": [
610 | "### 直接操作账户模式\n",
611 | "\n",
612 | "该模式直接操作账户"
613 | ]
614 | },
615 | {
616 | "cell_type": "code",
617 | "execution_count": null,
618 | "metadata": {},
619 | "outputs": [],
620 | "source": [
621 | "stock_account.receive_simpledeal(code='000004',order_id='model2',realorder_id='model2_real',trade_id='trade2',trade_amount=1000,trade_price=16,trade_time='2019-01-21',trade_towards=QA.ORDER_DIRECTION.BUY,message='model2')"
622 | ]
623 | },
624 | {
625 | "cell_type": "code",
626 | "execution_count": null,
627 | "metadata": {},
628 | "outputs": [],
629 | "source": [
630 | "stock_account.history_table"
631 | ]
632 | },
633 | {
634 | "cell_type": "code",
635 | "execution_count": null,
636 | "metadata": {},
637 | "outputs": [],
638 | "source": [
639 | "stock_account.cash"
640 | ]
641 | },
642 | {
643 | "cell_type": "code",
644 | "execution_count": null,
645 | "metadata": {},
646 | "outputs": [],
647 | "source": [
648 | "stock_account.cash_available"
649 | ]
650 | },
651 | {
652 | "cell_type": "code",
653 | "execution_count": null,
654 | "metadata": {},
655 | "outputs": [],
656 | "source": [
657 | "stock_account.hold"
658 | ]
659 | },
660 | {
661 | "cell_type": "code",
662 | "execution_count": null,
663 | "metadata": {},
664 | "outputs": [],
665 | "source": [
666 | "stock_account.sell_available"
667 | ]
668 | },
669 | {
670 | "cell_type": "markdown",
671 | "metadata": {},
672 | "source": [
673 | "## 结算\n",
674 | "\n",
675 | "主要是股票账户的可卖股数的结算\n",
676 | "\n",
677 | "目前期货账户不采用逐日盯市的结算方式(及无结算价/无当日盈亏)"
678 | ]
679 | },
680 | {
681 | "cell_type": "code",
682 | "execution_count": null,
683 | "metadata": {},
684 | "outputs": [],
685 | "source": [
686 | "stock_account.settle()"
687 | ]
688 | },
689 | {
690 | "cell_type": "code",
691 | "execution_count": null,
692 | "metadata": {},
693 | "outputs": [],
694 | "source": [
695 | "stock_account.sell_available"
696 | ]
697 | },
698 | {
699 | "cell_type": "code",
700 | "execution_count": null,
701 | "metadata": {},
702 | "outputs": [],
703 | "source": [
704 | "future_account.settle()"
705 | ]
706 | },
707 | {
708 | "cell_type": "code",
709 | "execution_count": null,
710 | "metadata": {},
711 | "outputs": [],
712 | "source": [
713 | "## 关于账户存储和恢复"
714 | ]
715 | },
716 | {
717 | "cell_type": "code",
718 | "execution_count": null,
719 | "metadata": {},
720 | "outputs": [],
721 | "source": []
722 | },
723 | {
724 | "cell_type": "markdown",
725 | "metadata": {},
726 | "source": [
727 | "## 存储"
728 | ]
729 | },
730 | {
731 | "cell_type": "code",
732 | "execution_count": null,
733 | "metadata": {},
734 | "outputs": [],
735 | "source": [
736 | "#stock_account.save()"
737 | ]
738 | },
739 | {
740 | "cell_type": "code",
741 | "execution_count": null,
742 | "metadata": {},
743 | "outputs": [],
744 | "source": []
745 | },
746 | {
747 | "cell_type": "code",
748 | "execution_count": null,
749 | "metadata": {},
750 | "outputs": [],
751 | "source": []
752 | },
753 | {
754 | "cell_type": "code",
755 | "execution_count": null,
756 | "metadata": {},
757 | "outputs": [],
758 | "source": []
759 | },
760 | {
761 | "cell_type": "code",
762 | "execution_count": null,
763 | "metadata": {},
764 | "outputs": [],
765 | "source": []
766 | }
767 | ],
768 | "metadata": {
769 | "kernelspec": {
770 | "display_name": "Python 3",
771 | "language": "python",
772 | "name": "python3"
773 | },
774 | "language_info": {
775 | "codemirror_mode": {
776 | "name": "ipython",
777 | "version": 3
778 | },
779 | "file_extension": ".py",
780 | "mimetype": "text/x-python",
781 | "name": "python",
782 | "nbconvert_exporter": "python",
783 | "pygments_lexer": "ipython3",
784 | "version": "3.6.7"
785 | },
786 | "latex_envs": {
787 | "LaTeX_envs_menu_present": true,
788 | "autoclose": false,
789 | "autocomplete": true,
790 | "bibliofile": "biblio.bib",
791 | "cite_by": "apalike",
792 | "current_citInitial": 1,
793 | "eqLabelWithNumbers": true,
794 | "eqNumInitial": 1,
795 | "hotkeys": {
796 | "equation": "Ctrl-E",
797 | "itemize": "Ctrl-I"
798 | },
799 | "labels_anchors": false,
800 | "latex_user_defs": false,
801 | "report_style_numbering": false,
802 | "user_envs_cfg": false
803 | },
804 | "toc": {
805 | "base_numbering": 1,
806 | "nav_menu": {},
807 | "number_sections": true,
808 | "sideBar": true,
809 | "skip_h1_title": false,
810 | "title_cell": "Table of Contents",
811 | "title_sidebar": "Contents",
812 | "toc_cell": false,
813 | "toc_position": {},
814 | "toc_section_display": true,
815 | "toc_window_display": false
816 | },
817 | "varInspector": {
818 | "cols": {
819 | "lenName": 16,
820 | "lenType": 16,
821 | "lenVar": 40
822 | },
823 | "kernels_config": {
824 | "python": {
825 | "delete_cmd_postfix": "",
826 | "delete_cmd_prefix": "del ",
827 | "library": "var_list.py",
828 | "varRefreshCmd": "print(var_dic_list())"
829 | },
830 | "r": {
831 | "delete_cmd_postfix": ") ",
832 | "delete_cmd_prefix": "rm(",
833 | "library": "var_list.r",
834 | "varRefreshCmd": "cat(var_dic_list()) "
835 | }
836 | },
837 | "types_to_exclude": [
838 | "module",
839 | "function",
840 | "builtin_function_or_method",
841 | "instance",
842 | "_Feature"
843 | ],
844 | "window_display": false
845 | }
846 | },
847 | "nbformat": 4,
848 | "nbformat_minor": 2
849 | }
850 |
--------------------------------------------------------------------------------
/4_回测实盘交易/Monitor.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": null,
6 | "metadata": {
7 | "scrolled": true
8 | },
9 | "outputs": [],
10 | "source": [
11 | "#\n",
12 | "import datetime\n",
13 | "import QUANTAXIS as QA\n",
14 | "import time\n"
15 | ]
16 | },
17 | {
18 | "cell_type": "code",
19 | "execution_count": null,
20 | "metadata": {},
21 | "outputs": [],
22 | "source": [
23 | "market = QA.QA_Market(if_start_orderthreading=True)\n",
24 | "market.connect(QA.BROKER_TYPE.SHIPANE)\n",
25 | "market.start()\n",
26 | "haitong_acc = 'account:141'\n",
27 | "moni = 'account:1391'"
28 | ]
29 | },
30 | {
31 | "cell_type": "code",
32 | "execution_count": null,
33 | "metadata": {},
34 | "outputs": [],
35 | "source": [
36 | "market.connect(QA.BROKER_TYPE.BACKETEST)\n"
37 | ]
38 | },
39 | {
40 | "cell_type": "code",
41 | "execution_count": null,
42 | "metadata": {},
43 | "outputs": [],
44 | "source": [
45 | "#market.register('木偶',QA.QA_BacktestBroker())"
46 | ]
47 | },
48 | {
49 | "cell_type": "code",
50 | "execution_count": null,
51 | "metadata": {},
52 | "outputs": [],
53 | "source": [
54 | "#market.broker"
55 | ]
56 | },
57 | {
58 | "cell_type": "code",
59 | "execution_count": null,
60 | "metadata": {},
61 | "outputs": [],
62 | "source": [
63 | "#market.login('木偶', '睿瞳深邃')\n",
64 | "#market.login(QA.BROKER_TYPE.BACKETEST, 'account_2')"
65 | ]
66 | },
67 | {
68 | "cell_type": "code",
69 | "execution_count": null,
70 | "metadata": {},
71 | "outputs": [],
72 | "source": [
73 | "market.login(QA.BROKER_TYPE.SHIPANE, haitong_acc)"
74 | ]
75 | },
76 | {
77 | "cell_type": "code",
78 | "execution_count": null,
79 | "metadata": {},
80 | "outputs": [],
81 | "source": [
82 | "market.session"
83 | ]
84 | },
85 | {
86 | "cell_type": "code",
87 | "execution_count": null,
88 | "metadata": {},
89 | "outputs": [],
90 | "source": [
91 | "market.get_account(haitong_acc).init_assets"
92 | ]
93 | },
94 | {
95 | "cell_type": "code",
96 | "execution_count": null,
97 | "metadata": {},
98 | "outputs": [],
99 | "source": [
100 | "market.login(QA.BROKER_TYPE.SHIPANE, moni)"
101 | ]
102 | },
103 | {
104 | "cell_type": "code",
105 | "execution_count": null,
106 | "metadata": {},
107 | "outputs": [],
108 | "source": [
109 | "market.broker[QA.BROKER_TYPE.SHIPANE].query_orders(moni,'')"
110 | ]
111 | },
112 | {
113 | "cell_type": "code",
114 | "execution_count": null,
115 | "metadata": {},
116 | "outputs": [],
117 | "source": [
118 | "market._sync_orders()"
119 | ]
120 | },
121 | {
122 | "cell_type": "code",
123 | "execution_count": null,
124 | "metadata": {},
125 | "outputs": [],
126 | "source": [
127 | "market.sync_order_and_deal()"
128 | ]
129 | },
130 | {
131 | "cell_type": "code",
132 | "execution_count": null,
133 | "metadata": {},
134 | "outputs": [],
135 | "source": [
136 | "rx=market.get_account(moni)"
137 | ]
138 | },
139 | {
140 | "cell_type": "code",
141 | "execution_count": null,
142 | "metadata": {},
143 | "outputs": [],
144 | "source": [
145 | "rx"
146 | ]
147 | },
148 | {
149 | "cell_type": "code",
150 | "execution_count": null,
151 | "metadata": {},
152 | "outputs": [],
153 | "source": [
154 | "rx.hold_table()"
155 | ]
156 | },
157 | {
158 | "cell_type": "code",
159 | "execution_count": null,
160 | "metadata": {},
161 | "outputs": [],
162 | "source": [
163 | "rx.init_assets"
164 | ]
165 | },
166 | {
167 | "cell_type": "code",
168 | "execution_count": null,
169 | "metadata": {},
170 | "outputs": [],
171 | "source": [
172 | "rx.cash"
173 | ]
174 | },
175 | {
176 | "cell_type": "code",
177 | "execution_count": null,
178 | "metadata": {},
179 | "outputs": [],
180 | "source": [
181 | "market.get_account_cookie()"
182 | ]
183 | },
184 | {
185 | "cell_type": "code",
186 | "execution_count": null,
187 | "metadata": {},
188 | "outputs": [],
189 | "source": [
190 | "market.order_handler.order_status"
191 | ]
192 | },
193 | {
194 | "cell_type": "code",
195 | "execution_count": null,
196 | "metadata": {},
197 | "outputs": [],
198 | "source": [
199 | "market.order_handler.deal_status"
200 | ]
201 | },
202 | {
203 | "cell_type": "code",
204 | "execution_count": null,
205 | "metadata": {},
206 | "outputs": [],
207 | "source": []
208 | },
209 | {
210 | "cell_type": "code",
211 | "execution_count": null,
212 | "metadata": {},
213 | "outputs": [],
214 | "source": []
215 | },
216 | {
217 | "cell_type": "code",
218 | "execution_count": null,
219 | "metadata": {},
220 | "outputs": [],
221 | "source": []
222 | },
223 | {
224 | "cell_type": "code",
225 | "execution_count": null,
226 | "metadata": {},
227 | "outputs": [],
228 | "source": []
229 | },
230 | {
231 | "cell_type": "code",
232 | "execution_count": null,
233 | "metadata": {},
234 | "outputs": [],
235 | "source": [
236 | "res2 = market.insert_order(moni, code='601318', amount=1600, amount_model=QA.AMOUNT_MODEL.BY_AMOUNT, order_model=QA.ORDER_MODEL.LIMIT,\n",
237 | " frequence=QA.FREQUENCE.CURRENT, broker_name=QA.BROKER_TYPE.SHIPANE, market_type=QA.MARKET_TYPE.STOCK_CN,\n",
238 | " towards=QA.ORDER_DIRECTION.BUY, price=0, time=datetime.datetime.now())\n",
239 | "\n"
240 | ]
241 | },
242 | {
243 | "cell_type": "code",
244 | "execution_count": null,
245 | "metadata": {},
246 | "outputs": [],
247 | "source": [
248 | "rx.orders.order_list"
249 | ]
250 | },
251 | {
252 | "cell_type": "code",
253 | "execution_count": null,
254 | "metadata": {},
255 | "outputs": [],
256 | "source": [
257 | "res2 = market.insert_order(moni, code='000001', amount=1000, amount_model=QA.AMOUNT_MODEL.BY_AMOUNT, order_model=QA.ORDER_MODEL.LIMIT,\n",
258 | " frequence=QA.FREQUENCE.CURRENT, broker_name=QA.BROKER_TYPE.SHIPANE, market_type=QA.MARKET_TYPE.STOCK_CN,\n",
259 | " towards=QA.ORDER_DIRECTION.BUY, price=8.9, time=datetime.datetime.now())\n",
260 | "\n",
261 | "\n"
262 | ]
263 | },
264 | {
265 | "cell_type": "code",
266 | "execution_count": null,
267 | "metadata": {},
268 | "outputs": [],
269 | "source": [
270 | "# res1= market.insert_order(moni, code='000001', amount=1450, amount_model=QA.AMOUNT_MODEL.BY_AMOUNT, order_model=QA.ORDER_MODEL.LIMIT,\n",
271 | "# frequence=QA.FREQUENCE.CURRENT, broker_name=QA.BROKER_TYPE.SHIPANE, market_type=QA.MARKET_TYPE.STOCK_CN,\n",
272 | "# towards=QA.ORDER_DIRECTION.SELL, price=8.91, time=datetime.datetime.now())\n",
273 | "\n",
274 | "\n"
275 | ]
276 | },
277 | {
278 | "cell_type": "code",
279 | "execution_count": null,
280 | "metadata": {},
281 | "outputs": [],
282 | "source": [
283 | "market.stop_sync_order_and_deal()"
284 | ]
285 | },
286 | {
287 | "cell_type": "code",
288 | "execution_count": null,
289 | "metadata": {},
290 | "outputs": [],
291 | "source": [
292 | "market.sync_order_and_deal()"
293 | ]
294 | },
295 | {
296 | "cell_type": "code",
297 | "execution_count": null,
298 | "metadata": {},
299 | "outputs": [],
300 | "source": [
301 | "#market.order_handler.deal_status.loc['account:141','3112'].trade_id"
302 | ]
303 | },
304 | {
305 | "cell_type": "code",
306 | "execution_count": null,
307 | "metadata": {},
308 | "outputs": [],
309 | "source": [
310 | "market.order_handler.order_status"
311 | ]
312 | },
313 | {
314 | "cell_type": "code",
315 | "execution_count": null,
316 | "metadata": {},
317 | "outputs": [],
318 | "source": [
319 | "z=market.get_account(moni).history_table"
320 | ]
321 | },
322 | {
323 | "cell_type": "code",
324 | "execution_count": null,
325 | "metadata": {},
326 | "outputs": [],
327 | "source": [
328 | "z=market.get_account(moni)"
329 | ]
330 | },
331 | {
332 | "cell_type": "code",
333 | "execution_count": null,
334 | "metadata": {},
335 | "outputs": [],
336 | "source": [
337 | "z.orders.order_list"
338 | ]
339 | },
340 | {
341 | "cell_type": "code",
342 | "execution_count": null,
343 | "metadata": {},
344 | "outputs": [],
345 | "source": [
346 | "#order=market.order_handler.order_queue.pending[1]"
347 | ]
348 | },
349 | {
350 | "cell_type": "code",
351 | "execution_count": null,
352 | "metadata": {},
353 | "outputs": [],
354 | "source": []
355 | },
356 | {
357 | "cell_type": "code",
358 | "execution_count": null,
359 | "metadata": {},
360 | "outputs": [],
361 | "source": []
362 | },
363 | {
364 | "cell_type": "code",
365 | "execution_count": null,
366 | "metadata": {},
367 | "outputs": [],
368 | "source": [
369 | "#order.transact_time"
370 | ]
371 | },
372 | {
373 | "cell_type": "code",
374 | "execution_count": null,
375 | "metadata": {},
376 | "outputs": [],
377 | "source": [
378 | "# for index, deal in market.order_handler.deal_status.loc[order.account_cookie,order.realorder_id].iterrows():\n",
379 | "# order.trade(str(deal.trade_id),float(deal.trade_price),int(deal.trade_amount))"
380 | ]
381 | },
382 | {
383 | "cell_type": "code",
384 | "execution_count": null,
385 | "metadata": {},
386 | "outputs": [],
387 | "source": [
388 | "# for order in market.order_handler.order_queue.pending:\n",
389 | "# if order.realorder_id in market.order_handler.deal_status.index.levels[1]:\n",
390 | "# # 此时有成交推送(但可能是多条)\n",
391 | "# market.order_handler.deal_status.loc[order.account_cookie,order.realorder_id]\n"
392 | ]
393 | },
394 | {
395 | "cell_type": "code",
396 | "execution_count": null,
397 | "metadata": {},
398 | "outputs": [],
399 | "source": [
400 | "# res1= market.insert_order(moni, code='600521', amount=1500, amount_model=QA.AMOUNT_MODEL.BY_AMOUNT, order_model=QA.ORDER_MODEL.LIMIT,\n",
401 | "# frequence=QA.FREQUENCE.CURRENT, broker_name=QA.BROKER_TYPE.SHIPANE, market_type=QA.MARKET_TYPE.STOCK_CN,\n",
402 | "# towards=QA.ORDER_DIRECTION.SELL, price=19.82, time=datetime.datetime.now())\n",
403 | "\n",
404 | "\n"
405 | ]
406 | }
407 | ],
408 | "metadata": {
409 | "kernelspec": {
410 | "display_name": "Python 3",
411 | "language": "python",
412 | "name": "python3"
413 | },
414 | "language_info": {
415 | "codemirror_mode": {
416 | "name": "ipython",
417 | "version": 3
418 | },
419 | "file_extension": ".py",
420 | "mimetype": "text/x-python",
421 | "name": "python",
422 | "nbconvert_exporter": "python",
423 | "pygments_lexer": "ipython3",
424 | "version": "3.6.6"
425 | }
426 | },
427 | "nbformat": 4,
428 | "nbformat_minor": 2
429 | }
430 |
--------------------------------------------------------------------------------
/4_回测实盘交易/QATTS_caitong_test.py:
--------------------------------------------------------------------------------
1 | import QUANTAXIS as QA
2 |
3 | if __name__ == '__main__':
4 | api = QA.QA_TTSBroker()
5 |
6 | print("Check API Server, Ping...")
7 | result = api.ping()
8 | print("Check API Server, Result")
9 | print(result)
10 |
11 | if result["success"]:
12 | for i in (0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 13, 14, 15):
13 | print("---查询信息 cate=%d--" % i)
14 | print(api.data_to_df(api.query_data(i)))
15 |
16 | print('==============================下面是下单部分========================')
17 | print('即将演示的是 下单000001 数量100股 价格9.8 的限价单模式')
18 |
19 | if str(input('我已知晓, 并下单 按y继续 n 退出'))[0] == 'y':
20 |
21 | # 市价单可能需要开通权限
22 | # order_model=QA.ORDER_MODEL.LIMIT 限价单
23 | print(
24 | api.send_order(
25 | code='000001',
26 | price=1.0,
27 | amount=100,
28 | towards=QA.ORDER_DIRECTION.BUY,
29 | order_model=QA.ORDER_MODEL.LIMIT
30 | )
31 | )
32 |
33 | print("---登出---")
34 | print(api.logoff())
35 |
--------------------------------------------------------------------------------
/4_回测实盘交易/QATTS_caitong_with_QAMarket.ipynb:
--------------------------------------------------------------------------------
1 | {"cells":[{"source":"# Change directory to VSCode workspace root so that relative path loads work correctly. Turn this addition off with the DataScience.changeDirOnImportExport setting\r\nimport os\r\ntry:\r\n\tos.chdir(os.path.join(os.getcwd(), 'github\\ToBeQuanter'))\r\n\tprint(os.getcwd())\r\nexcept:\r\n\tpass\r\n","cell_type":"code","outputs":[],"metadata":{},"execution_count":0},{"cell_type":"code","execution_count":1,"metadata":{},"outputs":[],"source":["import QUANTAXIS as QA\n","import datetime\n","\n","account = QA.QA_Account(\n"," user_cookie='tts',\n"," portfolio_cookie='tts',\n"," account_cookie='tts',\n"," broker=QA.BROKER_TYPE.TTS, \n"," running_environment=QA.RUNNING_ENVIRONMENT.TTS\n",")\n","\n",""]},{"cell_type":"code","execution_count":2,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":"subscribe\n[<_MainThread(MainThread, started 17540)>, , , , , , , , , ]\n"}],"source":["market = QA.QA_Market(if_start_orderthreading=True)\n","market.connect(QA.BROKER_TYPE.TTS)\n","market.login(QA.BROKER_TYPE.TTS, account_cookie=account.account_cookie, account=account)\n","market.start()\n","\n",""]},{"cell_type":"code","execution_count":3,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":"184707.03\n"}],"source":["print(market.query_cash(account.account_cookie))\n","\n",""]},{"cell_type":"code","execution_count":4,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":"{'cash': 184707.03, 'hold': {'510050': 0.0, '510300': 0.0, '600612': 1200.0, '600886': 0.0, '002697': 5400.0}}\n"}],"source":["print(market.query_assets(account.account_cookie))\n","\n",""]},{"cell_type":"code","execution_count":5,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":" order_time code name towards trade_price \\\nrealorder_id \n11378 2019-04-02 10:12:55 002697 红旗连锁 1 0.000 \n12246 2019-04-02 10:23:13 510050 50ETF -1 0.000 \n12307 2019-04-02 10:23:44 510300 300ETF -1 0.000 \n12359 2019-04-02 10:24:21 002697 红旗连锁 1 0.000 \n12384 2019-04-02 10:24:39 600886 国投电力 -1 8.430 \n1256 2019-04-02 09:22:44 600886 国投电力 -1 0.000 \n1316 2019-04-02 09:23:40 510300 300ETF -1 0.000 \n1362 2019-04-02 09:24:03 510300 300ETF -1 0.000 \n13962 2019-04-02 10:48:20 510050 50ETF -1 0.000 \n14011 2019-04-02 10:49:10 510300 300ETF -1 3.956 \n14019 2019-04-02 10:49:17 510050 50ETF -1 2.863 \n1430 2019-04-02 09:24:32 510050 50ETF -1 0.000 \n1479 2019-04-02 09:24:54 510050 50ETF -1 0.000 \n1613 2019-04-02 09:26:05 002697 红旗连锁 1 5.800 \n1730 2019-04-02 09:27:12 002697 红旗连锁 1 5.740 \n1791 2019-04-02 09:27:40 002697 红旗连锁 1 0.000 \n24310 2019-04-02 14:53:22 002697 红旗连锁 1 0.000 \n2791 2019-04-02 09:32:27 002697 红旗连锁 1 5.790 \n\n order_price status order_amount trade_amount \\\nrealorder_id \n11378 5.680 cancel_all 2700.0 0.0 \n12246 2.889 cancel_all 7200.0 0.0 \n12307 3.988 cancel_all 5400.0 0.0 \n12359 5.680 cancel_all 2700.0 0.0 \n12384 8.430 success_all 2400.0 2400.0 \n1256 8.460 cancel_all 2400.0 0.0 \n1316 3.996 cancel_all 2700.0 0.0 \n1362 4.020 cancel_all 2700.0 0.0 \n13962 2.869 cancel_all 7200.0 0.0 \n14011 1.000 success_all 5400.0 5400.0 \n14019 1.000 success_all 7200.0 7200.0 \n1430 2.893 cancel_all 3600.0 0.0 \n1479 2.912 cancel_all 3600.0 0.0 \n1613 5.800 success_all 1800.0 1800.0 \n1730 5.740 success_all 1800.0 1800.0 \n1791 5.680 cancel_all 1800.0 0.0 \n24310 5.720 queued 2700.0 0.0 \n2791 5.800 success_all 1800.0 1800.0 \n\n cancel_amount \nrealorder_id \n11378 0 \n12246 0 \n12307 0 \n12359 0 \n12384 0 \n1256 0 \n1316 0 \n1362 0 \n13962 0 \n14011 0 \n14019 0 \n1430 0 \n1479 0 \n1613 0 \n1730 0 \n1791 0 \n24310 0 \n2791 0 \n"}],"source":["print(market.query_orders(account.account_cookie))\n",""]},{"cell_type":"code","execution_count":6,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":"order_time 2019-04-02 10:24:39\ncode 600886\nname 国投电力\ntowards -1\ntrade_price 8.43\norder_price 8.43\nstatus success_all\norder_amount 2400\ntrade_amount 2400\ncancel_amount 0\nName: (tts, 12384), dtype: object\n"}],"source":["print(market.query_order(account.account_cookie, '12384'))\n",""]},{"cell_type":"code","execution_count":7,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":"code\n002697 5400.0\n600612 1200.0\nName: amount, dtype: float64\n"}],"source":["print(market.query_position(account.account_cookie))\n",""]},{"cell_type":"code","execution_count":8,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":">-----------------------insert_order-----------------------------> QA_Market.insert_order\n100 by_amount 2019-04-02 16:35:22.004487 600825 1 LIMIT 1 None\nFAILED FOR CREATE ORDER tts failed\n< QA_Order realorder_id Order_CItwbsoq datetime:2019-04-02 09:31:00 code:600825 amount:100 price:1 towards:1 btype:stock_cn order_id:Order_CItwbsoq account:tts status:failed >\nfailed\n"}],"source":["market.insert_order(account_cookie=account.account_cookie, code='600825', amount=100, amount_model=QA.AMOUNT_MODEL.BY_AMOUNT, order_model=QA.ORDER_MODEL.LIMIT,\n"," frequence=QA.FREQUENCE.CURRENT, broker_name=account.broker, market_type=account.market_type,\n"," towards=QA.ORDER_DIRECTION.BUY, price=1, time=datetime.datetime.now())\n",""]},{"cell_type":"code","execution_count":9,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":"None\n"}],"source":["print(market.query_trade(account.account_cookie))\n","\n",""]},{"cell_type":"code","execution_count":10,"metadata":{},"outputs":[],"source":""}],"nbformat":4,"nbformat_minor":2,"metadata":{"language_info":{"name":"python","codemirror_mode":{"name":"ipython","version":3}},"orig_nbformat":2,"file_extension":".py","mimetype":"text/x-python","name":"python","npconvert_exporter":"python","pygments_lexer":"ipython3","version":3}}
--------------------------------------------------------------------------------
/4_回测实盘交易/QA_MARKETENGINE.py:
--------------------------------------------------------------------------------
1 | #%% Change working directory from the workspace root to the ipynb file location. Turn this addition off with the DataScience.changeDirOnImportExport setting
2 | import os
3 | try:
4 | os.chdir(os.path.join(os.getcwd(), 'EXAMPLE\QAMARKET 相关'))
5 | print(os.getcwd())
6 | except:
7 | pass
8 |
9 | #%%
10 | import QUANTAXIS as QA
11 | import threading
12 | import pandas as pd
13 |
14 |
15 | #%%
16 | user = QA.QA_User(username='admin',password='940809x')
17 | portfolio = user.new_portfolio('example')
18 | # 创建两个account
19 | #这里是创建一个资产组合,然后在组合里面创建两个account 你可以想象成股票里面的两个策略账户
20 | #然后返回的是这个账户的id
21 | a_1 = portfolio.new_account(account_cookie='a1')
22 | a_2 = portfolio.new_account(account_cookie='a2')
23 |
24 |
25 | #%%
26 | a_1
27 |
28 |
29 | #%%
30 | """
31 | 然后这里 是创建一个交易前置 你可以理解成 创建了一个无界面的通达信客户端
32 | 然后start()开启这个客户端
33 | 连接到backtest的broker上 这个broker可以更换
34 | """
35 | # 创建一个交易前置
36 | market = QA.QA_Market()
37 | # 交易前置连接broker
38 | market.start()
39 | market.connect(QA.RUNNING_ENVIRONMENT.BACKETEST)
40 |
41 | # 打印market
42 | print(market)
43 |
44 |
45 | #%%
46 |
47 | """
48 | 登陆到这个交易前置上 把你刚才的两个账户
49 | """
50 | # 登陆交易
51 | market.login(QA.BROKER_TYPE.BACKETEST,a_1.account_cookie, a_1)
52 | market.login(QA.BROKER_TYPE.BACKETEST,a_2.account_cookie, a_2)
53 | # 打印市场中的交易账户
54 | print(market.get_account_cookie())
55 |
56 |
57 | #%%
58 | #然后这里 往交易前置里面添加订单 这个操作是异步的
59 |
60 |
61 | #%%
62 | market.insert_order(account_cookie=a_1.account_cookie, money=100000, amount=None,price=None, amount_model=QA.AMOUNT_MODEL.BY_MONEY,time='2017-12-01', code='600010',
63 | order_model=QA.ORDER_MODEL.CLOSE, towards=QA.ORDER_DIRECTION.BUY,market_type=QA.MARKET_TYPE.STOCK_CN,
64 | frequence=QA.FREQUENCE.DAY,broker_name=QA.BROKER_TYPE.BACKETEST)
65 |
66 |
67 | #%%
68 | market.insert_order(account_cookie=a_1.account_cookie, amount=100,price=None, amount_model=QA.AMOUNT_MODEL.BY_AMOUNT,time='2017-12-01', code='000001',
69 | order_model=QA.ORDER_MODEL.CLOSE, towards=QA.ORDER_DIRECTION.BUY,market_type=QA.MARKET_TYPE.STOCK_CN,
70 | frequence=QA.FREQUENCE.DAY,broker_name=QA.BROKER_TYPE.BACKETEST)
71 |
72 |
73 | #%%
74 | #
75 | """
76 | 下单以后 现金不会减少 但是可用现金会被扣除
77 | 因为如果是市价单 你的成交价未定
78 | 没法直接减少现金
79 | 可用现金减少 cash不减少 等到settle 等到成功交易的时候 才会扣cash
80 |
81 | """
82 |
83 |
84 | #%%
85 | market.session[a_1.account_cookie].cash_available
86 |
87 |
88 | #%%
89 | market.session[a_1.account_cookie].cash
90 |
91 |
92 | #%%
93 | """
94 | 这里是交易前置内部的订单队列
95 | """
96 |
97 |
98 | #%%
99 | market.order_handler.order_queue()
100 |
101 |
102 |
103 |
104 | #%%
105 | market.order_handler.order_queue.order_list
106 |
107 |
108 | #%%
109 | #pending 是指的待成交列表
110 |
111 |
112 | #%%
113 | market.order_handler.order_queue.pending
114 |
115 |
116 | #%%
117 | """
118 | 这个_trade是一个私有方法 只有模拟盘和回测才会有 实盘就是真的交易了
119 | 这个_trade是backtest类去调用的
120 |
121 | """
122 | #market._trade(QA.QA_Event(broker_name=QA.BROKER_TYPE.BACKETEST,after_success=None))
123 |
124 |
125 | #%%
126 | """下面这两个是 查询 一个是异步查询 一个是同步的(no_wait)
127 | 异步不会阻塞当前线程 同步会阻塞"""
128 |
129 |
130 | #%%
131 | market.query_data(broker_name=QA.BROKER_TYPE.BACKETEST,frequence=QA.FREQUENCE.DAY,market_type=QA.MARKET_TYPE.STOCK_CN,
132 | code='600010',start='2017-12-01')
133 |
134 |
135 | #%%
136 | market.query_data_no_wait(broker_name=QA.BROKER_TYPE.BACKETEST,frequence=QA.FREQUENCE.DAY,market_type=QA.MARKET_TYPE.STOCK_CN,
137 | code='000001',start='2017-12-14')
138 |
139 |
140 | #%%
141 | """成交了以后 你可以看到账户的资产变化了"""
142 | market.session[a_1.account_cookie]
143 |
144 |
145 | #%%
146 | """待成交列表被清空"""
147 |
148 |
149 | #%%
150 | market.order_handler.order_queue.pending
151 |
152 |
153 | #%%
154 | """待成交队列清空"""
155 |
156 |
157 | #%%
158 | market.order_handler.order_queue.order_list
159 |
160 |
161 | #%%
162 | market.order_handler.order_queue()
163 |
164 |
165 | #%%
166 | """
167 | cash 现金减少
168 | """
169 | market.session[a_1.account_cookie].cash
170 |
171 |
172 | #%%
173 | """
174 | 因为没有触发每日结算时间 在T+1的市场 即使买入了也没有可卖的
175 | """
176 | market.session[a_1.account_cookie].sell_available
177 |
178 |
179 | #%%
180 | sa=market.session[a_1.account_cookie].sell_available
181 |
182 |
183 | #%%
184 | ac=market.session[a_1.account_cookie]
185 |
186 |
187 | #%%
188 | ac.hold
189 |
190 |
191 | #%%
192 | sa
193 |
194 |
195 | #%%
196 | market.session[a_1.account_cookie].history
197 |
198 |
199 | #%%
200 | """
201 | 持仓表增加
202 | """
203 | market.session[a_1.account_cookie].hold
204 |
205 |
206 | #%%
207 | """
208 | 账户信息
209 |
210 | 可以看到 减少的资产 主要是因为收了手续费
211 | """
212 | market.session[a_1.account_cookie].message
213 |
214 |
215 | #%%
216 | """结算事件"""
217 | market._settle(QA.BROKER_TYPE.BACKETEST)
218 |
219 |
220 | #%%
221 | """
222 | 结算完以后 可卖数量就会变成和持仓数一样
223 | """
224 |
225 |
226 | #%%
227 | market.session[a_1.account_cookie].hold
228 |
229 |
230 | #%%
231 | market.session[a_1.account_cookie].sell_available
232 |
233 |
234 | #%%
235 | """
236 | 结算完以后 待成交队列也被清空
237 | """
238 |
239 |
240 | #%%
241 | market.order_handler.order_queue()
242 |
243 |
244 | #%%
245 | market.insert_order(account_cookie=a_1.account_cookie, amount=market.session[a_1.account_cookie].sell_available.get('600010',0),price=None, amount_model=QA.AMOUNT_MODEL.BY_AMOUNT,time='2017-12-05', code='600010',
246 | order_model=QA.ORDER_MODEL.CLOSE, towards=QA.ORDER_DIRECTION.SELL,market_type=QA.MARKET_TYPE.STOCK_CN,
247 | frequence=QA.FREQUENCE.DAY,broker_name=QA.BROKER_TYPE.BACKETEST)
248 |
249 |
250 | #%%
251 | market.order_handler.order_queue.order_list
252 |
253 |
254 | #%%
255 | market.order_handler.order_queue()
256 |
257 |
258 | #%%
259 | market.session[a_1.account_cookie].sell_available
260 |
261 |
262 | #%%
263 | #market._trade(QA.QA_Event(broker_name=QA.BROKER_TYPE.BACKETEST,after_success=None))
264 |
265 |
266 | #%%
267 | market.session[a_1.account_cookie].cash
268 |
269 |
270 | #%%
271 | market.session[a_1.account_cookie].history
272 |
273 |
274 | #%%
275 | ac.save()
276 |
277 |
278 |
--------------------------------------------------------------------------------
/4_回测实盘交易/TEST_ACCOUNT_SELLOPEN_T0.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 1,
6 | "metadata": {},
7 | "outputs": [
8 | {
9 | "name": "stderr",
10 | "output_type": "stream",
11 | "text": [
12 | "QUANTAXIS>> start QUANTAXIS\n",
13 | "QUANTAXIS>> Welcome to QUANTAXIS, the Version is 1.1.0\n",
14 | "QUANTAXIS>> \n",
15 | " ```````````````````````````````````````````````````````````````````````````````````````````````````````````````````````` \n",
16 | " ``########`````##````````##``````````##`````````####````````##```##########````````#``````##``````###```##`````######`` \n",
17 | " `##``````## ```##````````##`````````####````````##`##```````##```````##```````````###``````##````##`````##```##`````##` \n",
18 | " ##````````##```##````````##````````##`##````````##``##``````##```````##``````````####```````#```##``````##```##``````## \n",
19 | " ##````````##```##````````##```````##```##```````##```##`````##```````##`````````##`##```````##`##```````##````##``````` \n",
20 | " ##````````##```##````````##``````##`````##``````##````##````##```````##````````##``###```````###````````##`````##`````` \n",
21 | " ##````````##```##````````##``````##``````##`````##`````##```##```````##```````##````##```````###````````##``````###```` \n",
22 | " ##````````##```##````````##`````##````````##````##``````##``##```````##``````##``````##`````##`##```````##````````##``` \n",
23 | " ##````````##```##````````##````#############````##```````##`##```````##`````###########`````##``##``````##`````````##`` \n",
24 | " ###```````##```##````````##```##```````````##```##```````##`##```````##````##`````````##```##```##``````##```##`````##` \n",
25 | " `##``````###````##``````###``##`````````````##``##````````####```````##```##``````````##``###````##`````##````##`````## \n",
26 | " ``#########``````########```##``````````````###`##``````````##```````##``##````````````##`##``````##````##`````###``### \n",
27 | " ````````#####`````````````````````````````````````````````````````````````````````````````````````````````````````##`` \n",
28 | " ``````````````````````````````````````````````````````````````````````````````````````````````````````````````````````` \n",
29 | " ``````````````````````````Copyright``yutiansut``2018``````QUANTITATIVE FINANCIAL FRAMEWORK````````````````````````````` \n",
30 | " ``````````````````````````````````````````````````````````````````````````````````````````````````````````````````````` \n",
31 | " ```````````````````````````````````````````````````````````````````````````````````````````````````````````````````````` \n",
32 | " ```````````````````````````````````````````````````````````````````````````````````````````````````````````````````````` \n",
33 | " \n"
34 | ]
35 | }
36 | ],
37 | "source": [
38 | "import QUANTAXIS as QA"
39 | ]
40 | },
41 | {
42 | "cell_type": "code",
43 | "execution_count": 2,
44 | "metadata": {},
45 | "outputs": [],
46 | "source": [
47 | "account=QA.QA_Account(account_cookie='future_1',allow_t0=True,allow_sellopen=True)"
48 | ]
49 | },
50 | {
51 | "cell_type": "code",
52 | "execution_count": 5,
53 | "metadata": {},
54 | "outputs": [
55 | {
56 | "data": {
57 | "text/plain": [
58 | "{'source': 'account',\n",
59 | " 'account_cookie': 'future_1',\n",
60 | " 'portfolio_cookie': None,\n",
61 | " 'user_cookie': None,\n",
62 | " 'broker': 'backtest',\n",
63 | " 'market_type': 'stock_cn',\n",
64 | " 'strategy_name': None,\n",
65 | " 'current_time': 'None',\n",
66 | " 'allow_sellopen': True,\n",
67 | " 'allow_t0': True,\n",
68 | " 'margin_level': False,\n",
69 | " 'init_assets': {'cash': 1000000, 'hold': {}},\n",
70 | " 'commission_coeff': 0.00025,\n",
71 | " 'tax_coeff': 0.0015,\n",
72 | " 'cash': [1000000],\n",
73 | " 'history': [],\n",
74 | " 'trade_index': [],\n",
75 | " 'running_time': '2018-08-23 09:54:14.005020',\n",
76 | " 'quantaxis_version': '1.1.0',\n",
77 | " 'running_environment': 'backtest'}"
78 | ]
79 | },
80 | "execution_count": 5,
81 | "metadata": {},
82 | "output_type": "execute_result"
83 | }
84 | ],
85 | "source": [
86 | "account.message"
87 | ]
88 | },
89 | {
90 | "cell_type": "code",
91 | "execution_count": 9,
92 | "metadata": {},
93 | "outputs": [
94 | {
95 | "data": {
96 | "text/plain": [
97 | "< QA_Order realorder_id Order_pgXJEKQY datetime:2018-08-23 09:31:00 code:RB1810 amount:1000 price:800 towards:-1 btype:stock_cn order_id:Order_pgXJEKQY account:future_1 status:queued >"
98 | ]
99 | },
100 | "execution_count": 9,
101 | "metadata": {},
102 | "output_type": "execute_result"
103 | }
104 | ],
105 | "source": [
106 | "account.send_order('RB1810',amount=1000,time='2018-08-23 9:50:00',towards=QA.ORDER_DIRECTION.SELL_OPEN,price=800,order_model=QA.ORDER_MODEL.LIMIT,amount_model=QA.AMOUNT_MODEL.BY_AMOUNT)"
107 | ]
108 | },
109 | {
110 | "cell_type": "code",
111 | "execution_count": 15,
112 | "metadata": {},
113 | "outputs": [
114 | {
115 | "data": {
116 | "text/html": [
117 | "\n",
118 | "\n",
131 | "
\n",
132 | " \n",
133 | " \n",
134 | " | \n",
135 | " datetime | \n",
136 | " active1 | \n",
137 | " active2 | \n",
138 | " last_close | \n",
139 | " code | \n",
140 | " open | \n",
141 | " high | \n",
142 | " low | \n",
143 | " price | \n",
144 | " cur_vol | \n",
145 | " ... | \n",
146 | " bid3 | \n",
147 | " bid_vol3 | \n",
148 | " ask4 | \n",
149 | " ask_vol4 | \n",
150 | " bid4 | \n",
151 | " bid_vol4 | \n",
152 | " ask5 | \n",
153 | " ask_vol5 | \n",
154 | " bid5 | \n",
155 | " bid_vol5 | \n",
156 | "
\n",
157 | " \n",
158 | " code | \n",
159 | " | \n",
160 | " | \n",
161 | " | \n",
162 | " | \n",
163 | " | \n",
164 | " | \n",
165 | " | \n",
166 | " | \n",
167 | " | \n",
168 | " | \n",
169 | " | \n",
170 | " | \n",
171 | " | \n",
172 | " | \n",
173 | " | \n",
174 | " | \n",
175 | " | \n",
176 | " | \n",
177 | " | \n",
178 | " | \n",
179 | " | \n",
180 | "
\n",
181 | " \n",
182 | " \n",
183 | " \n",
184 | " 000001 | \n",
185 | " 2018-08-23 10:09:40.716973 | \n",
186 | " 770 | \n",
187 | " 770 | \n",
188 | " 9.29 | \n",
189 | " 000001 | \n",
190 | " 9.3 | \n",
191 | " 9.42 | \n",
192 | " 9.3 | \n",
193 | " 9.34 | \n",
194 | " 70 | \n",
195 | " ... | \n",
196 | " 9.31 | \n",
197 | " 1865 | \n",
198 | " 9.37 | \n",
199 | " 1967 | \n",
200 | " 9.3 | \n",
201 | " 2282 | \n",
202 | " 9.38 | \n",
203 | " 2740 | \n",
204 | " 9.29 | \n",
205 | " 3788 | \n",
206 | "
\n",
207 | " \n",
208 | "
\n",
209 | "
1 rows × 33 columns
\n",
210 | "
"
211 | ],
212 | "text/plain": [
213 | " datetime active1 active2 last_close code open \\\n",
214 | "code \n",
215 | "000001 2018-08-23 10:09:40.716973 770 770 9.29 000001 9.3 \n",
216 | "\n",
217 | " high low price cur_vol ... bid3 bid_vol3 ask4 ask_vol4 \\\n",
218 | "code ... \n",
219 | "000001 9.42 9.3 9.34 70 ... 9.31 1865 9.37 1967 \n",
220 | "\n",
221 | " bid4 bid_vol4 ask5 ask_vol5 bid5 bid_vol5 \n",
222 | "code \n",
223 | "000001 9.3 2282 9.38 2740 9.29 3788 \n",
224 | "\n",
225 | "[1 rows x 33 columns]"
226 | ]
227 | },
228 | "execution_count": 15,
229 | "metadata": {},
230 | "output_type": "execute_result"
231 | }
232 | ],
233 | "source": [
234 | "QA.QA_fetch_get_stock_realtime('tdx','000001')"
235 | ]
236 | }
237 | ],
238 | "metadata": {
239 | "kernelspec": {
240 | "display_name": "Python 3",
241 | "language": "python",
242 | "name": "python3"
243 | },
244 | "language_info": {
245 | "codemirror_mode": {
246 | "name": "ipython",
247 | "version": 3
248 | },
249 | "file_extension": ".py",
250 | "mimetype": "text/x-python",
251 | "name": "python",
252 | "nbconvert_exporter": "python",
253 | "pygments_lexer": "ipython3",
254 | "version": "3.6.6"
255 | }
256 | },
257 | "nbformat": 4,
258 | "nbformat_minor": 2
259 | }
260 |
--------------------------------------------------------------------------------
/4_回测实盘交易/回测/期货回测/future_min_backtest.py:
--------------------------------------------------------------------------------
1 | # %% Change working directory from the workspace root to the ipynb file location. Turn this addition off with the DataScience.changeDirOnImportExport setting
2 | import os
3 | try:
4 | os.chdir(os.path.join(os.getcwd(), 'EXAMPLE\test_backtest\FUTURE'))
5 | print(os.getcwd())
6 | except:
7 | pass
8 |
9 | # %%
10 | import QUANTAXIS as QA
11 | import sys
12 |
13 |
14 | # %%
15 | user = QA.QA_User(username='quantaxis', password='quantaxis')
16 | portfolio = user.new_portfolio('qatestportfolio')
17 | Account = portfolio.new_account(allow_sellopen=True, allow_margin=True, init_cash=5000, allow_t0=True,
18 | account_cookie='future_test', market_type=QA.MARKET_TYPE.FUTURE_CN, frequence=QA.FREQUENCE.FIFTEEN_MIN)
19 |
20 |
21 | # %%
22 | Broker = QA.QA_BacktestBroker()
23 |
24 |
25 | # %%
26 | rb_ds = QA.QA_fetch_future_min_adv(
27 | 'RBL8', '2018-01-01', '2018-08-28', frequence='15min')
28 |
29 |
30 | # %%
31 | import numpy as np
32 | import pandas as pd
33 |
34 |
35 | def MACD_JCSC(dataframe, SHORT=12, LONG=26, M=9):
36 | """
37 | 1.DIF向上突破DEA,买入信号参考。
38 | 2.DIF向下跌破DEA,卖出信号参考。
39 | """
40 | CLOSE = dataframe.close
41 | DIFF = QA.EMA(CLOSE, SHORT) - QA.EMA(CLOSE, LONG)
42 | DEA = QA.EMA(DIFF, M)
43 | MACD = 2*(DIFF-DEA)
44 |
45 | CROSS_JC = QA.CROSS(DIFF, DEA)
46 | CROSS_SC = QA.CROSS(DEA, DIFF)
47 | ZERO = 0
48 | return pd.DataFrame({'DIFF': DIFF, 'DEA': DEA, 'MACD': MACD, 'CROSS_JC': CROSS_JC, 'CROSS_SC': CROSS_SC, 'ZERO': ZERO})
49 |
50 |
51 | ind = rb_ds.add_func(MACD_JCSC)
52 |
53 |
54 | # %%
55 | _date = None
56 | for items in rb_ds.panel_gen:
57 | if _date != items.date[0]:
58 | print('try to settle')
59 | _date = items.date[0]
60 | Account.settle()
61 |
62 | for item in items.security_gen:
63 | daily_ind = ind.loc[item.index]
64 | if daily_ind.CROSS_JC.iloc[0] > 0:
65 | order = Account.send_order(
66 | code=item.code[0],
67 | time=item.datetime[0],
68 | amount=1,
69 | towards=QA.ORDER_DIRECTION.BUY_OPEN,
70 | price=0,
71 | order_model=QA.ORDER_MODEL.CLOSE,
72 | amount_model=QA.AMOUNT_MODEL.BY_AMOUNT
73 | )
74 |
75 | if order:
76 | print(order)
77 | print(item)
78 | Broker.receive_order(QA.QA_Event(
79 | order=order, market_data=item))
80 |
81 | trade_mes = Broker.query_orders(
82 | Account.account_cookie, 'filled')
83 | res = trade_mes.loc[order.account_cookie, order.realorder_id]
84 | order.trade(res.trade_id, res.trade_price,
85 | res.trade_amount, res.trade_time)
86 | elif daily_ind.CROSS_SC.iloc[0] > 0:
87 | if Account.sell_available.get(item.code[0], 0) > 0:
88 | order = Account.send_order(
89 | code=item.code[0],
90 | time=item.datetime[0],
91 | amount=Account.sell_available.get(item.code[0], 0),
92 | towards=QA.ORDER_DIRECTION.SELL_CLOSE,
93 | price=0,
94 | order_model=QA.ORDER_MODEL.MARKET,
95 | amount_model=QA.AMOUNT_MODEL.BY_AMOUNT
96 | )
97 | if order:
98 | Broker.receive_order(QA.QA_Event(
99 | order=order, market_data=item))
100 |
101 | trade_mes = Broker.query_orders(
102 | Account.account_cookie, 'filled')
103 | res = trade_mes.loc[order.account_cookie,
104 | order.realorder_id]
105 | order.trade(res.trade_id, res.trade_price,
106 | res.trade_amount, res.trade_time)
107 | Account.settle()
108 |
109 |
110 | # %%
111 | Risk = QA.QA_Risk(Account)
112 |
113 |
114 | # %%
115 | Risk.plot_assets_curve()
116 |
117 |
118 | # %%
119 | Risk.profit_construct
120 |
121 |
122 | Account.save()
123 | Risk.save()
124 |
--------------------------------------------------------------------------------
/4_回测实盘交易/回测/股票回测/基于QAMARKET的回测/backtest.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8
2 | #
3 | # The MIT License (MIT)
4 | #
5 | # Copyright (c) 2016-2018 yutiansut/QUANTAXIS
6 | #
7 | # Permission is hereby granted, free of charge, to any person obtaining a copy
8 | # of this software and associated documentation files (the "Software"), to deal
9 | # in the Software without restriction, including without limitation the rights
10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | # copies of the Software, and to permit persons to whom the Software is
12 | # furnished to do so, subject to the following conditions:
13 | #
14 | # The above copyright notice and this permission notice shall be included in all
15 | # copies or substantial portions of the Software.
16 | #
17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | # SOFTWARE.
24 |
25 |
26 | from QUANTAXIS.QAARP.QARisk import QA_Risk
27 | from QUANTAXIS.QAARP.QAUser import QA_User
28 | from QUANTAXIS.QAApplication.QABacktest import QA_Backtest
29 | from QUANTAXIS.QAUtil.QALogs import QA_util_log_info
30 | from QUANTAXIS.QAUtil.QAParameter import FREQUENCE, MARKET_TYPE
31 | from minstrategy import MAMINStrategy
32 | from strategy import MAStrategy
33 |
34 |
35 | class Backtest(QA_Backtest):
36 | '''
37 | 多线程模式回测示例
38 |
39 | '''
40 |
41 | def __init__(self, market_type, frequence, start, end, code_list, commission_fee):
42 | super().__init__(market_type, frequence, start, end, code_list, commission_fee)
43 | mastrategy = MAStrategy(user_cookie=self.user.user_cookie, portfolio_cookie= self.portfolio.portfolio_cookie, account_cookie= 'mastrategy')
44 | #maminstrategy = MAMINStrategy()
45 | self.account = self.portfolio.add_account(mastrategy)
46 |
47 | def after_success(self):
48 | QA_util_log_info(self.account.history_table)
49 | risk = QA_Risk(self.account, benchmark_code='000300',
50 | benchmark_type=MARKET_TYPE.INDEX_CN)
51 |
52 | print(risk().T)
53 | fig=risk.plot_assets_curve()
54 | fig.show()
55 | fig=risk.plot_dailyhold()
56 | fig.show()
57 | fig=risk.plot_signal()
58 | fig.show()
59 | self.account.save()
60 | risk.save()
61 |
62 |
63 | def run_daybacktest():
64 | import QUANTAXIS as QA
65 | backtest = Backtest(market_type=MARKET_TYPE.STOCK_CN,
66 | frequence=FREQUENCE.DAY,
67 | start='2017-01-01',
68 | end='2017-02-10',
69 | code_list=QA.QA_fetch_stock_block_adv().code[0:5],
70 | commission_fee=0.00015)
71 | print(backtest.account)
72 | backtest.start_market()
73 |
74 | backtest.run()
75 | backtest.stop()
76 |
77 |
78 | def run_minbacktest():
79 | import QUANTAXIS as QA
80 | backtest = Backtest(market_type=MARKET_TYPE.STOCK_CN,
81 | frequence=FREQUENCE.FIFTEEN_MIN,
82 | start='2017-11-01',
83 | end='2017-11-10',
84 | code_list=QA.QA_fetch_stock_block_adv().code[0:5],
85 | commission_fee=0.00015)
86 | backtest.start_market()
87 |
88 | backtest.run()
89 | backtest.stop()
90 |
91 |
92 | if __name__ == '__main__':
93 | run_daybacktest()
94 | #run_minbacktest()
95 |
96 |
--------------------------------------------------------------------------------
/4_回测实盘交易/回测/股票回测/基于QAMARKET的回测/minstrategy.py:
--------------------------------------------------------------------------------
1 | # utf-8
2 | from QUANTAXIS.QAARP.QAStrategy import QA_Strategy
3 | from QUANTAXIS.QAUtil.QAParameter import (AMOUNT_MODEL, MARKET_TYPE,
4 | FREQUENCE, ORDER_DIRECTION,
5 | ORDER_MODEL)
6 |
7 |
8 | class MAMINStrategy(QA_Strategy):
9 | def __init__(self):
10 | super().__init__()
11 | self.frequence = FREQUENCE.FIFTEEN_MIN
12 | self.market_type = MARKET_TYPE.STOCK_CN
13 |
14 | def on_bar(self, event):
15 | try:
16 | # 新数据推送进来
17 | for item in event.market_data.code:
18 | # 如果持仓
19 | if self.sell_available.get(item, 0) > 0:
20 | # 全部卖出
21 | event.send_order(account_cookie=self.account_cookie,
22 | amount=self.sell_available[item], amount_model=AMOUNT_MODEL.BY_AMOUNT,
23 | time=self.current_time, code=item, price=0,
24 | order_model=ORDER_MODEL.MARKET, towards=ORDER_DIRECTION.SELL,
25 | market_type=self.market_type, frequence=self.frequence,
26 | broker_name=self.broker
27 | )
28 | else: # 如果不持仓
29 | # 买入1000股
30 | event.send_order(account_cookie=self.account_cookie,
31 | amount=100, amount_model=AMOUNT_MODEL.BY_AMOUNT,
32 | time=self.current_time, code=item, price=0,
33 | order_model=ORDER_MODEL.MARKET, towards=ORDER_DIRECTION.BUY,
34 | market_type=self.market_type, frequence=self.frequence,
35 | broker_name=self.broker)
36 | except:
37 | pass
38 |
--------------------------------------------------------------------------------
/4_回测实盘交易/回测/股票回测/基于QAMARKET的回测/strategy.py:
--------------------------------------------------------------------------------
1 | # utf-8
2 | import time
3 | import threading
4 | from QUANTAXIS.QAARP.QAAccount import QA_Account
5 | from QUANTAXIS.QAUtil.QALogs import QA_util_log_info
6 | from QUANTAXIS.QAUtil.QAParameter import (AMOUNT_MODEL, FREQUENCE, MARKET_TYPE,
7 | ORDER_DIRECTION, ORDER_MODEL)
8 |
9 |
10 | class MAStrategy(QA_Account):
11 | def __init__(self, user_cookie, portfolio_cookie, account_cookie, init_cash=100000, init_hold={}):
12 | super().__init__(user_cookie=user_cookie, portfolio_cookie=portfolio_cookie, account_cookie= account_cookie,
13 | init_cash=init_cash, init_hold=init_hold)
14 | self.frequence = FREQUENCE.DAY
15 | self.market_type = MARKET_TYPE.STOCK_CN
16 | self.commission_coeff = 0.00015
17 | self.tax_coeff = 0.0001
18 | self.reset_assets(100000) # 这是第二种修改办法
19 |
20 | def on_bar(self, event):
21 | print(threading.enumerate())
22 | sellavailable = self.sell_available
23 | try:
24 | for item in event.market_data.code:
25 | if sellavailable.get(item, 0) > 0:
26 | event.send_order(account_cookie=self.account_cookie,
27 | amount=sellavailable[item], amount_model=AMOUNT_MODEL.BY_AMOUNT,
28 | time=self.current_time, code=item, price=0,
29 | order_model=ORDER_MODEL.MARKET, towards=ORDER_DIRECTION.SELL,
30 | market_type=self.market_type, frequence=self.frequence,
31 | broker_name=self.broker
32 | )
33 | else:
34 | event.send_order(account_cookie=self.account_cookie,
35 | amount=100, amount_model=AMOUNT_MODEL.BY_AMOUNT,
36 | time=self.current_time, code=item, price=0,
37 | order_model=ORDER_MODEL.MARKET, towards=ORDER_DIRECTION.BUY,
38 | market_type=self.market_type, frequence=self.frequence,
39 | broker_name=self.broker)
40 |
41 | except Exception as e:
42 | print(e)
43 |
--------------------------------------------------------------------------------
/4_回测实盘交易/回测/股票回测/多季度选股择时回测.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8
2 | #
3 | # The MIT License (MIT)
4 | #
5 | # Copyright (c) 2016-2018 yutiansut/QUANTAXIS
6 | #
7 | # Permission is hereby granted, free of charge, to any person obtaining a copy
8 | # of this software and associated documentation files (the "Software"), to deal
9 | # in the Software without restriction, including without limitation the rights
10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | # copies of the Software, and to permit persons to whom the Software is
12 | # furnished to do so, subject to the following conditions:
13 | #
14 | # The above copyright notice and this permission notice shall be included in all
15 | # copies or substantial portions of the Software.
16 | #
17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | # SOFTWARE.
24 |
25 |
26 | import QUANTAXIS as QA
27 | import random
28 | """
29 | 单线程模式回测示例
30 | 该代码旨在给出一个极其容易实现的小回测 高效 无事件驱动
31 | """
32 | Broker = QA.QA_BacktestBroker()
33 | User = QA.QA_User(username='quantaxis', password='quantaxis')
34 | Portfolio = User.new_portfolio('qatestportfolio')
35 | AC = Portfolio.new_account(account_cookie='supersimple', init_cash=200000)
36 | """
37 | # 账户设置初始资金
38 | AC.reset_assets(assets)
39 |
40 | # 发送订单
41 | Order=AC.send_order(code='000001',amount=1000,time='2018-03-21',towards=QA.ORDER_DIRECTION.BUY,price=0,order_model=QA.ORDER_MODEL.MARKET,amount_model=QA.AMOUNT_MODEL.BY_AMOUNT)
42 | # 撮合订单
43 | B.receive_order(QA.QA_Event(order=Order,market_data=data))
44 |
45 | # 查询账户的订单状态
46 | trade_mes=Broker.query_orders(AC.account_cookie, 'filled')
47 | res=trade_mes.loc[order.account_cookie, order.realorder_id]
48 |
49 | # 更新订单
50 |
51 | order.trade(res.trade_id, res.trade_price,res.trade_amount, res.trade_time)
52 |
53 | # 查询订单的状态
54 |
55 | order.status
56 |
57 |
58 | # 分析结果
59 |
60 | risk=QA.QA_Risk(AC)
61 |
62 | """
63 |
64 | QA.QA_SU_save_strategy('test','test_day',AC.account_cookie,if_save=True)
65 |
66 |
67 | def select_code(report_date):
68 | QA.QA_fetch_financial_report
69 |
70 | def simple_backtest(AC, code, start, end):
71 | DATA = QA.QA_fetch_stock_day_adv(code, start, end).to_qfq()
72 | for items in DATA.panel_gen: # 一天过去了
73 |
74 | for item in items.security_gen:
75 | if random.random() > 0.5: # 加入一个随机 模拟买卖的
76 | if AC.sell_available.get(item.code[0], 0) == 0:
77 | order = AC.send_order(
78 | code=item.code[0], time=item.date[0], amount=1000, towards=QA.ORDER_DIRECTION.BUY, price=0, order_model=QA.ORDER_MODEL.MARKET, amount_model=QA.AMOUNT_MODEL.BY_AMOUNT
79 | )
80 | if order:
81 | order.trade('unknownTrade', order.price,
82 | order.amount, order.datetime)
83 |
84 | else:
85 | order = AC.send_order(
86 | code=item.code[0], time=item.date[0], amount=1000, towards=QA.ORDER_DIRECTION.SELL, price=0, order_model=QA.ORDER_MODEL.MARKET, amount_model=QA.AMOUNT_MODEL.BY_AMOUNT
87 | )
88 | if order:
89 | order.trade('unknownTrade', order.price,
90 | order.amount, order.datetime)
91 | AC.settle()
92 |
93 | # 先选股
94 | code = select_code('2012-03')
95 |
96 | simple_backtest(AC, QA.QA_fetch_stock_block_adv(
97 | ).code, '2012-01-01', '2012-03-31')
98 |
99 | code = select_code('2012-06')
100 |
101 | simple_backtest(AC, QA.QA_fetch_stock_block_adv(
102 | ).code, '2012-04-01', '2012-06-30')
103 |
104 |
105 | print(AC.message)
106 | AC.save()
107 | risk = QA.QA_Risk(AC)
108 | print(risk.message)
109 | risk.save()
--------------------------------------------------------------------------------
/4_回测实盘交易/回测/股票回测/简易回测/MACD_JCSC.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Demo: MACD strategy
3 | # src: ./test_backtest/MACD_JCSC.py
4 | # jupyter: ./test_backtest/QUANTAXIS回测分析全过程讲解.ipynb
5 | # paper: ./test_backtest/QUANTAXIS回测分析全过程讲解.md
6 |
7 | import QUANTAXIS as QA
8 | import numpy as np
9 | import pandas as pd
10 | import datetime
11 | st1 = datetime.datetime.now()
12 | # define the MACD strategy
13 |
14 |
15 | def MACD_JCSC(dataframe, SHORT=12, LONG=26, M=9):
16 | """
17 | 1.DIF向上突破DEA,买入信号参考。
18 | 2.DIF向下跌破DEA,卖出信号参考。
19 | """
20 | CLOSE = dataframe.close
21 | DIFF = QA.EMA(CLOSE, SHORT) - QA.EMA(CLOSE, LONG)
22 | DEA = QA.EMA(DIFF, M)
23 | MACD = 2*(DIFF-DEA)
24 |
25 | CROSS_JC = QA.CROSS(DIFF, DEA)
26 | CROSS_SC = QA.CROSS(DEA, DIFF)
27 | ZERO = 0
28 | return pd.DataFrame({'DIFF': DIFF, 'DEA': DEA, 'MACD': MACD, 'CROSS_JC': CROSS_JC, 'CROSS_SC': CROSS_SC, 'ZERO': ZERO})
29 |
30 |
31 | # create account
32 | user = QA.QA_User(username='quantaxis', password='quantaxis')
33 | portfolio = user.new_portfolio('qatestportfolio')
34 |
35 |
36 | Account = portfolio.new_account(account_cookie='macd_stock', init_cash=1000000)
37 | Broker = QA.QA_BacktestBroker()
38 |
39 |
40 | QA.QA_SU_save_strategy('MACD_JCSC', 'Indicator',
41 | Account.account_cookie, if_save=True)
42 | # get data from mongodb
43 | data = QA.QA_fetch_stock_day_adv(
44 | ['000001', '000002', '000004', '600000'], '2017-09-01', '2018-05-20')
45 | data = data.to_qfq()
46 |
47 | # add indicator
48 | ind = data.add_func(MACD_JCSC)
49 | # ind.xs('000001',level=1)['2018-01'].plot()
50 |
51 | data_forbacktest = data.select_time('2018-01-01', '2018-05-01')
52 |
53 |
54 | for items in data_forbacktest.panel_gen:
55 | for item in items.security_gen:
56 | daily_ind = ind.loc[item.index]
57 |
58 | if daily_ind.CROSS_JC.iloc[0] > 0:
59 | order = Account.send_order(
60 | code=item.code[0],
61 | time=item.date[0],
62 | amount=1000,
63 | towards=QA.ORDER_DIRECTION.BUY,
64 | price=0,
65 | order_model=QA.ORDER_MODEL.CLOSE,
66 | amount_model=QA.AMOUNT_MODEL.BY_AMOUNT
67 | )
68 | # print(item.to_json()[0])
69 | Broker.receive_order(QA.QA_Event(order=order, market_data=item))
70 | trade_mes = Broker.query_orders(Account.account_cookie, 'filled')
71 | res = trade_mes.loc[order.account_cookie, order.realorder_id]
72 | order.trade(res.trade_id, res.trade_price,
73 | res.trade_amount, res.trade_time)
74 | elif daily_ind.CROSS_SC.iloc[0] > 0:
75 | # print(item.code)
76 | if Account.sell_available.get(item.code[0], 0) > 0:
77 | order = Account.send_order(
78 | code=item.code[0],
79 | time=item.date[0],
80 | amount=Account.sell_available.get(item.code[0], 0),
81 | towards=QA.ORDER_DIRECTION.SELL,
82 | price=0,
83 | order_model=QA.ORDER_MODEL.MARKET,
84 | amount_model=QA.AMOUNT_MODEL.BY_AMOUNT
85 | )
86 | # print
87 | Broker.receive_order(QA.QA_Event(
88 | order=order, market_data=item))
89 | trade_mes = Broker.query_orders(
90 | Account.account_cookie, 'filled')
91 | res = trade_mes.loc[order.account_cookie, order.realorder_id]
92 | order.trade(res.trade_id, res.trade_price,
93 | res.trade_amount, res.trade_time)
94 | Account.settle()
95 |
96 | print('TIME -- {}'.format(datetime.datetime.now()-st1))
97 | print(Account.history)
98 | print(Account.history_table)
99 | print(Account.daily_hold)
100 |
101 | # create Risk analysis
102 | Risk = QA.QA_Risk(Account)
103 |
104 | Account.save()
105 | Risk.save()
106 |
107 |
108 | # print(Risk.message)
109 | # print(Risk.assets)
110 | # Risk.plot_assets_curve()
111 | # plt=Risk.plot_dailyhold()
112 | # plt.show()
113 | # plt1=Risk.plot_signal()
114 | # plt.show()
115 |
116 | # performance=QA.QA_Performance(Account)
117 | # plt=performance.plot_pnlmoney(performance.pnl_fifo)
118 | # plt.show()
119 | # Risk.assets.plot()
120 | # Risk.benchmark_assets.plot()
121 |
122 | # save result
123 |
124 | #account_info = QA.QA_fetch_account({'account_cookie': 'user_admin_macd'})
125 | #account = QA.QA_Account().from_message(account_info[0])
126 | # print(account)
127 |
--------------------------------------------------------------------------------
/4_回测实盘交易/回测/股票回测/简易回测/simple_minbacktest.py:
--------------------------------------------------------------------------------
1 |
2 | # coding: utf-8
3 |
4 | # In[21]:
5 |
6 |
7 | import QUANTAXIS as QA
8 | import pandas as pd
9 |
10 | data = QA.QA_fetch_stock_min_adv('601318', '2018-03-22', '2018-08-23', '30min')
11 |
12 |
13 |
14 | res = data.add_func(QA.QA_indicator_KDJ)
15 | sig = QA.CROSS(res.KDJ_J, res.KDJ_K)
16 | sig2 = QA.CROSS(res.KDJ_K, res.KDJ_J)
17 |
18 | User = QA.QA_User(username='quantaxis', password='quantaxis')
19 | Portfolio = User.new_portfolio('qatestportfolio')
20 | Account = Portfolio.new_account(account_cookie='macdmin_601318' ,init_cash=20000,
21 | frequence=QA.FREQUENCE.THIRTY_MIN)
22 | Broker = QA.QA_BacktestBroker()
23 |
24 | QA.QA_SU_save_strategy(Account.account_cookie,
25 | Account.portfolio_cookie, Account.account_cookie, if_save=True)
26 |
27 | _date = None
28 | for items in data.panel_gen:
29 | if _date != items.date[0]:
30 | print('try to settle')
31 | _date = items.date[0]
32 | Account.settle()
33 |
34 | for item in items.security_gen:
35 | if sig[item.index].iloc[0] > 0:
36 | order = Account.send_order(
37 | code=item.code[0],
38 | time=item.datetime[0],
39 | amount=100,
40 | towards=QA.ORDER_DIRECTION.BUY,
41 | price=0,
42 | order_model=QA.ORDER_MODEL.CLOSE,
43 | amount_model=QA.AMOUNT_MODEL.BY_AMOUNT
44 | )
45 | if order:
46 | Broker.receive_order(QA.QA_Event(order=order, market_data=item))
47 | trade_mes = Broker.query_orders(Account.account_cookie, 'filled')
48 | res = trade_mes.loc[order.account_cookie, order.realorder_id]
49 | print('buy')
50 | order.trade(res.trade_id, res.trade_price,
51 | res.trade_amount, res.trade_time)
52 | elif sig2[item.index].iloc[0] > 0:
53 | if Account.sell_available.get(item.code[0], 0) > 0:
54 | order1 = Account.send_order(
55 | code=item.code[0],
56 | time=item.datetime[0],
57 | amount=100,
58 | towards=QA.ORDER_DIRECTION.SELL,
59 | price=0,
60 | order_model=QA.ORDER_MODEL.CLOSE,
61 | amount_model=QA.AMOUNT_MODEL.BY_AMOUNT
62 | )
63 | if order1:
64 | Broker.receive_order(QA.QA_Event(
65 | order=order1, market_data=item))
66 | trade_mes = Broker.query_orders(
67 | Account.account_cookie, 'filled')
68 | res = trade_mes.loc[order1.account_cookie, order1.realorder_id]
69 | print('sell')
70 | order1.trade(res.trade_id, res.trade_price,
71 | res.trade_amount, res.trade_time)
72 |
73 |
74 | print(Account.history_table)
75 |
76 |
77 | r = QA.QA_Risk(Account)
78 |
79 |
80 | r.plot_assets_curve().show()
81 |
82 | print(r.profit_construct)
83 |
84 | Account.save()
85 | r.save()
86 |
--------------------------------------------------------------------------------
/4_回测实盘交易/回测/股票回测/简易回测/simplebacktest.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8
2 | #
3 | # The MIT License (MIT)
4 | #
5 | # Copyright (c) 2016-2018 yutiansut/QUANTAXIS
6 | #
7 | # Permission is hereby granted, free of charge, to any person obtaining a copy
8 | # of this software and associated documentation files (the "Software"), to deal
9 | # in the Software without restriction, including without limitation the rights
10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | # copies of the Software, and to permit persons to whom the Software is
12 | # furnished to do so, subject to the following conditions:
13 | #
14 | # The above copyright notice and this permission notice shall be included in all
15 | # copies or substantial portions of the Software.
16 | #
17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | # SOFTWARE.
24 |
25 |
26 | import QUANTAXIS as QA
27 | import random
28 | """
29 | 单线程模式回测示例
30 | 该代码旨在给出一个极其容易实现的小回测 高效 无事件驱动
31 | """
32 | Broker = QA.QA_BacktestBroker()
33 | User = QA.QA_User(username='quantaxis', password='quantaxis')
34 | Portfolio = User.new_portfolio('qatestportfolio')
35 | AC = Portfolio.new_account(account_cookie='simplebacktest', init_cash=200000)
36 | """
37 | # 账户设置初始资金
38 | AC.reset_assets(assets)
39 |
40 | # 发送订单
41 | Order=AC.send_order(code='000001',amount=1000,time='2018-03-21',towards=QA.ORDER_DIRECTION.BUY,price=0,order_model=QA.ORDER_MODEL.MARKET,amount_model=QA.AMOUNT_MODEL.BY_AMOUNT)
42 | # 撮合订单
43 | B.receive_order(QA.QA_Event(order=Order,market_data=data))
44 |
45 | # 查询账户的订单状态
46 | trade_mes=Broker.query_orders(AC.account_cookie, 'filled')
47 | res=trade_mes.loc[order.account_cookie, order.realorder_id]
48 |
49 | # 更新订单
50 |
51 | order.trade(res.trade_id, res.trade_price,res.trade_amount, res.trade_time)
52 |
53 | # 查询订单的状态
54 |
55 | order.status
56 |
57 |
58 | # 分析结果
59 |
60 | risk=QA.QA_Risk(AC)
61 |
62 | """
63 |
64 | QA.QA_SU_save_strategy('test','test_day',AC.account_cookie,if_save=True)
65 |
66 | def simple_backtest(AC, code, start, end):
67 | DATA = QA.QA_fetch_stock_day_adv(code, start, end).to_qfq()
68 | for items in DATA.panel_gen: # 一天过去了
69 |
70 | for item in items.security_gen:
71 | if random.random() > 0.5: # 加入一个随机 模拟买卖的
72 | if AC.sell_available.get(item.code[0], 0) == 0:
73 | order = AC.send_order(
74 | code=item.code[0], time=item.date[0], amount=1000, towards=QA.ORDER_DIRECTION.BUY, price=0, order_model=QA.ORDER_MODEL.MARKET, amount_model=QA.AMOUNT_MODEL.BY_AMOUNT
75 | )
76 | if order:
77 | Broker.receive_order(QA.QA_Event(
78 | order=order, market_data=item))
79 | trade_mes = Broker.query_orders(
80 | AC.account_cookie, 'filled')
81 | res = trade_mes.loc[order.account_cookie,
82 | order.realorder_id]
83 | print('order {} {} {} {}'.format(
84 | res.trade_id, res.trade_price, res.trade_amount, res.trade_time))
85 | order.trade(res.trade_id, res.trade_price,
86 | res.trade_amount, res.trade_time)
87 |
88 | else:
89 | order = AC.send_order(
90 | code=item.code[0], time=item.date[0], amount=1000, towards=QA.ORDER_DIRECTION.SELL, price=0, order_model=QA.ORDER_MODEL.MARKET, amount_model=QA.AMOUNT_MODEL.BY_AMOUNT
91 | )
92 | if order:
93 | Broker.receive_order(QA.QA_Event(
94 | order=order, market_data=item))
95 | trade_mes = Broker.query_orders(
96 | AC.account_cookie, 'filled')
97 | res = trade_mes.loc[order.account_cookie,
98 | order.realorder_id]
99 | print('order {} {} {} {}'.format(
100 | res.trade_id, res.trade_price, res.trade_amount, res.trade_time))
101 | order.trade(res.trade_id, res.trade_price,
102 | res.trade_amount, res.trade_time)
103 | AC.settle()
104 |
105 |
106 | simple_backtest(AC, QA.QA_fetch_stock_block_adv(
107 | ).code[0:10], '2017-01-01', '2018-01-31')
108 | print(AC.message)
109 | AC.save()
110 | risk = QA.QA_Risk(AC)
111 | print(risk.message)
112 | risk.save()
113 |
--------------------------------------------------------------------------------
/4_回测实盘交易/回测/股票回测/超级简化版回测/MACD_JCSC.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Demo: MACD strategy
3 | # src: ./test_backtest/MACD_JCSC.py
4 | # jupyter: ./test_backtest/QUANTAXIS回测分析全过程讲解.ipynb
5 | # paper: ./test_backtest/QUANTAXIS回测分析全过程讲解.md
6 |
7 | import QUANTAXIS as QA
8 | import numpy as np
9 | import pandas as pd
10 | import datetime
11 | st1=datetime.datetime.now()
12 | # define the MACD strategy
13 | def MACD_JCSC(dataframe, SHORT=12, LONG=26, M=9):
14 | """
15 | 1.DIF向上突破DEA,买入信号参考。
16 | 2.DIF向下跌破DEA,卖出信号参考。
17 | """
18 | CLOSE = dataframe.close
19 | DIFF = QA.EMA(CLOSE, SHORT) - QA.EMA(CLOSE, LONG)
20 | DEA = QA.EMA(DIFF, M)
21 | MACD = 2*(DIFF-DEA)
22 |
23 | CROSS_JC = QA.CROSS(DIFF, DEA)
24 | CROSS_SC = QA.CROSS(DEA, DIFF)
25 | ZERO = 0
26 | return pd.DataFrame({'DIFF': DIFF, 'DEA': DEA, 'MACD': MACD, 'CROSS_JC': CROSS_JC, 'CROSS_SC': CROSS_SC, 'ZERO': ZERO})
27 |
28 |
29 | # create account
30 | user = QA.QA_User(username='quantaxis', password='quantaxis')
31 | portfolio = user.new_portfolio('qatestportfolio')
32 |
33 |
34 | Account = portfolio.new_account(account_cookie='macd_stock', init_cash=1000000)
35 | Broker = QA.QA_BacktestBroker()
36 |
37 | QA.QA_SU_save_strategy('MACD_JCSC','Indicator',Account.account_cookie)
38 | # get data from mongodb
39 | QA.QA_SU_save_strategy('MACD_JCSC', 'Indicator',
40 | Account.account_cookie, if_save=True)
41 | data = QA.QA_fetch_stock_day_adv(
42 | ['000001', '000002', '000004', '600000'], '2017-09-01', '2018-05-20')
43 | data = data.to_qfq()
44 |
45 | # add indicator
46 | ind = data.add_func(MACD_JCSC)
47 | # ind.xs('000001',level=1)['2018-01'].plot()
48 |
49 | data_forbacktest=data.select_time('2018-01-01','2018-05-01')
50 |
51 |
52 | for items in data_forbacktest.panel_gen:
53 | for item in items.security_gen:
54 | daily_ind=ind.loc[item.index]
55 |
56 | if daily_ind.CROSS_JC.iloc[0]>0:
57 | order=Account.send_order(
58 | code=item.code[0],
59 | time=item.date[0],
60 | amount=1000,
61 | towards=QA.ORDER_DIRECTION.BUY,
62 | price=0,
63 | order_model=QA.ORDER_MODEL.CLOSE,
64 | amount_model=QA.AMOUNT_MODEL.BY_AMOUNT
65 | )
66 | #print(item.to_json()[0])
67 | Broker.receive_order(QA.QA_Event(order=order,market_data=item))
68 | trade_mes=Broker.query_orders(Account.account_cookie,'filled')
69 | res=trade_mes.loc[order.account_cookie,order.realorder_id]
70 | order.trade(res.trade_id,res.trade_price,res.trade_amount,res.trade_time)
71 | elif daily_ind.CROSS_SC.iloc[0]>0:
72 | #print(item.code)
73 | if Account.sell_available.get(item.code[0], 0)>0:
74 | order=Account.send_order(
75 | code=item.code[0],
76 | time=item.date[0],
77 | amount=Account.sell_available.get(item.code[0], 0),
78 | towards=QA.ORDER_DIRECTION.SELL,
79 | price=0,
80 | order_model=QA.ORDER_MODEL.MARKET,
81 | amount_model=QA.AMOUNT_MODEL.BY_AMOUNT
82 | )
83 | #print
84 | Broker.receive_order(QA.QA_Event(order=order,market_data=item))
85 | trade_mes=Broker.query_orders(Account.account_cookie,'filled')
86 | res=trade_mes.loc[order.account_cookie,order.realorder_id]
87 | order.trade(res.trade_id,res.trade_price,res.trade_amount,res.trade_time)
88 | Account.settle()
89 |
90 | print('TIME -- {}'.format(datetime.datetime.now()-st1))
91 | print(Account.history)
92 | print(Account.history_table)
93 | print(Account.daily_hold)
94 |
95 | # create Risk analysis
96 | Risk = QA.QA_Risk(Account)
97 |
98 | Account.save()
99 | Risk.save()
100 |
101 |
102 | # print(Risk.message)
103 | # print(Risk.assets)
104 | # Risk.plot_assets_curve()
105 | # plt=Risk.plot_dailyhold()
106 | # plt.show()
107 | # plt1=Risk.plot_signal()
108 | # plt.show()
109 |
110 | # performance=QA.QA_Performance(Account)
111 | # plt=performance.plot_pnlmoney(performance.pnl_fifo)
112 | # plt.show()
113 | # Risk.assets.plot()
114 | # Risk.benchmark_assets.plot()
115 |
116 | # save result
117 |
118 | #account_info = QA.QA_fetch_account({'account_cookie': 'user_admin_macd'})
119 | #account = QA.QA_Account().from_message(account_info[0])
120 | #print(account)
121 |
--------------------------------------------------------------------------------
/4_回测实盘交易/回测/股票回测/超级简化版回测/simple_minbacktest.py:
--------------------------------------------------------------------------------
1 |
2 | # coding: utf-8
3 |
4 | # In[21]:
5 |
6 |
7 | import QUANTAXIS as QA
8 | import pandas as pd
9 |
10 | data = QA.QA_fetch_stock_min_adv('601318', '2018-03-22', '2018-08-23', '30min')
11 |
12 |
13 | res = data.add_func(QA.QA_indicator_KDJ)
14 | sig = QA.CROSS(res.KDJ_J, res.KDJ_K)
15 | sig2 = QA.CROSS(res.KDJ_K, res.KDJ_J)
16 |
17 | User = QA.QA_User(username='quantaxis', password='quantaxis')
18 | Portfolio = User.new_portfolio('qatestportfolio')
19 | Account = Portfolio.new_account(account_cookie='supersimple', init_cash=100000, init_hold={'601318': 1000},
20 | frequence=QA.FREQUENCE.THIRTY_MIN)
21 | Broker = QA.QA_BacktestBroker()
22 | QA.QA_SU_save_strategy(Account.account_cookie,
23 | Account.portfolio_cookie, Account.account_cookie, if_save=True)
24 |
25 | _date = None
26 | for items in data.panel_gen:
27 | if _date != items.date[0]:
28 | print('try to settle')
29 | _date = items.date[0]
30 | Account.settle()
31 |
32 | for item in items.security_gen:
33 | if sig[item.index].iloc[0] > 0:
34 | order = Account.send_order(
35 | code=item.code[0],
36 | time=item.datetime[0],
37 | amount=1000,
38 | towards=QA.ORDER_DIRECTION.BUY,
39 | price=0,
40 | order_model=QA.ORDER_MODEL.CLOSE,
41 | amount_model=QA.AMOUNT_MODEL.BY_AMOUNT
42 | )
43 | if order:
44 | order.trade('unknownTrade', order.price,
45 | order.amount, order.datetime)
46 | elif sig2[item.index].iloc[0] > 0:
47 | if Account.sell_available.get(item.code[0], 0) > 0:
48 | order1 = Account.send_order(
49 | code=item.code[0],
50 | time=item.datetime[0],
51 | amount=1000,
52 | towards=QA.ORDER_DIRECTION.SELL,
53 | price=0,
54 | order_model=QA.ORDER_MODEL.CLOSE,
55 | amount_model=QA.AMOUNT_MODEL.BY_AMOUNT
56 | )
57 | if order1:
58 | order1.trade('unknownTrade', order1.price,
59 | order1.amount, order1.datetime)
60 |
61 |
62 | print(Account.history_table)
63 |
64 |
65 | r = QA.QA_Risk(Account)
66 |
67 |
68 | r.plot_assets_curve().show()
69 |
70 | print(r.profit_construct)
71 |
72 | Account.save()
73 | r.save()
74 |
--------------------------------------------------------------------------------
/4_回测实盘交易/回测/股票回测/超级简化版回测/simplebacktest.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8
2 | #
3 | # The MIT License (MIT)
4 | #
5 | # Copyright (c) 2016-2018 yutiansut/QUANTAXIS
6 | #
7 | # Permission is hereby granted, free of charge, to any person obtaining a copy
8 | # of this software and associated documentation files (the "Software"), to deal
9 | # in the Software without restriction, including without limitation the rights
10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | # copies of the Software, and to permit persons to whom the Software is
12 | # furnished to do so, subject to the following conditions:
13 | #
14 | # The above copyright notice and this permission notice shall be included in all
15 | # copies or substantial portions of the Software.
16 | #
17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | # SOFTWARE.
24 |
25 |
26 | import QUANTAXIS as QA
27 | import random
28 | """
29 | 单线程模式回测示例
30 | 该代码旨在给出一个极其容易实现的小回测 高效 无事件驱动
31 | """
32 | Broker = QA.QA_BacktestBroker()
33 | User = QA.QA_User(username='quantaxis', password='quantaxis')
34 | Portfolio = User.new_portfolio('qatestportfolio')
35 | AC = Portfolio.new_account(account_cookie='supersimple', init_cash=200000)
36 | """
37 | # 账户设置初始资金
38 | AC.reset_assets(assets)
39 |
40 | # 发送订单
41 | Order=AC.send_order(code='000001',amount=1000,time='2018-03-21',towards=QA.ORDER_DIRECTION.BUY,price=0,order_model=QA.ORDER_MODEL.MARKET,amount_model=QA.AMOUNT_MODEL.BY_AMOUNT)
42 | # 撮合订单
43 | B.receive_order(QA.QA_Event(order=Order,market_data=data))
44 |
45 | # 查询账户的订单状态
46 | trade_mes=Broker.query_orders(AC.account_cookie, 'filled')
47 | res=trade_mes.loc[order.account_cookie, order.realorder_id]
48 |
49 | # 更新订单
50 |
51 | order.trade(res.trade_id, res.trade_price,res.trade_amount, res.trade_time)
52 |
53 | # 查询订单的状态
54 |
55 | order.status
56 |
57 |
58 | # 分析结果
59 |
60 | risk=QA.QA_Risk(AC)
61 |
62 | """
63 |
64 | QA.QA_SU_save_strategy('test','test_day',AC.account_cookie,if_save=True)
65 |
66 | def simple_backtest(AC, code, start, end):
67 | DATA = QA.QA_fetch_stock_day_adv(code, start, end).to_qfq()
68 | for items in DATA.panel_gen: # 一天过去了
69 |
70 | for item in items.security_gen:
71 | if random.random() > 0.5: # 加入一个随机 模拟买卖的
72 | if AC.sell_available.get(item.code[0], 0) == 0:
73 | order = AC.send_order(
74 | code=item.code[0], time=item.date[0], amount=1000, towards=QA.ORDER_DIRECTION.BUY, price=0, order_model=QA.ORDER_MODEL.MARKET, amount_model=QA.AMOUNT_MODEL.BY_AMOUNT
75 | )
76 | if order:
77 | order.trade('unknownTrade', order.price,
78 | order.amount, order.datetime)
79 |
80 | else:
81 | order = AC.send_order(
82 | code=item.code[0], time=item.date[0], amount=1000, towards=QA.ORDER_DIRECTION.SELL, price=0, order_model=QA.ORDER_MODEL.MARKET, amount_model=QA.AMOUNT_MODEL.BY_AMOUNT
83 | )
84 | if order:
85 | order.trade('unknownTrade', order.price,
86 | order.amount, order.datetime)
87 | AC.settle()
88 |
89 |
90 | simple_backtest(AC, QA.QA_fetch_stock_block_adv(
91 | ).code[0:10], '2017-01-01', '2018-01-31')
92 | print(AC.message)
93 | AC.save()
94 | risk = QA.QA_Risk(AC)
95 | print(risk.message)
96 | risk.save()
97 |
--------------------------------------------------------------------------------
/4_回测实盘交易/回测/股票日内交易回测/T0backtest.py:
--------------------------------------------------------------------------------
1 |
2 | # coding: utf-8
3 |
4 | # In[1]:
5 |
6 |
7 | from QUANTAXIS.QAARP.QAStrategy import QA_Strategy
8 | from QUANTAXIS.QAARP.QAAccount import QA_Account
9 | from QUANTAXIS.QAUtil.QAParameter import (AMOUNT_MODEL, MARKET_TYPE,
10 | FREQUENCE, ORDER_DIRECTION,
11 | ORDER_MODEL, RUNNING_ENVIRONMENT)
12 |
13 |
14 | import random
15 |
16 |
17 | # In[2]:
18 |
19 |
20 | class MAMINT0Strategy(QA_Account):
21 | def __init__(self, user_cookie='default', portfolio_cookie='default', init_hold={'000001': 10000}):
22 | super().__init__(user_cookie, portfolio_cookie, init_hold=init_hold)
23 | self.account_cookie = 'T0BACKTEST'
24 | self.running_environment = RUNNING_ENVIRONMENT.TZERO
25 | self.frequence = FREQUENCE.ONE_MIN
26 | self.market_type = MARKET_TYPE.STOCK_CN
27 |
28 | self.result = {}
29 |
30 | def on_bar(self, event):
31 |
32 | # min5= self.market_data.min5
33 | # min15= self.market_data.min15
34 |
35 | # min5macd=QA.QA_indicator_MACD(min5)
36 | # min15macd=QA.QA_indicator_MACD(min15)
37 | # self.result['min5macd']=min5macd
38 |
39 | # self.cash_available # 当前剩余现金
40 | # self.sell_available # 当前可卖股票
41 | # self.history_table # 当前的历史交易
42 | # self.hold_time # 当前的持仓时间
43 | # self.hold_price # 当前持仓的成本价格
44 | # self.get_orders # 获取历史订单
45 | # self.allow_sellopen # 账户是否允许卖空
46 | # self.allow_t0 # 账户是否允许t0
47 | # self.commission_coeff # 账户的手续费(可自行调整)
48 |
49 | try:
50 | for item in event.market_data.code:
51 |
52 | print('================')
53 | print(self.sell_available)
54 | print('================')
55 | print(self.hold_available)
56 | if self.sell_available.get(item, 0) > 0:
57 | event.send_order(account_cookie=self.account_cookie,
58 | amount=self.sell_available[item], amount_model=AMOUNT_MODEL.BY_AMOUNT,
59 | time=self.current_time, code=item, price=0,
60 | order_model=ORDER_MODEL.MARKET, towards=ORDER_DIRECTION.SELL,
61 | market_type=self.market_type, frequence=self.frequence,
62 | broker_name=self.broker
63 | )
64 | else:
65 | event.send_order(account_cookie=self.account_cookie,
66 | amount=100, amount_model=AMOUNT_MODEL.BY_AMOUNT,
67 | time=self.current_time, code=item, price=0,
68 | order_model=ORDER_MODEL.MARKET, towards=ORDER_DIRECTION.BUY,
69 | market_type=self.market_type, frequence=self.frequence,
70 | broker_name=self.broker)
71 | except:
72 | pass
73 |
74 |
75 | # In[3]:
76 |
77 |
78 | from QUANTAXIS.QAARP.QARisk import QA_Risk
79 | from QUANTAXIS.QAARP.QAUser import QA_User
80 | from QUANTAXIS.QAApplication.QABacktest import QA_Backtest
81 | from QUANTAXIS.QAUtil.QALogs import QA_util_log_info
82 | from QUANTAXIS.QAUtil.QAParameter import FREQUENCE, MARKET_TYPE
83 |
84 |
85 | class Backtest(QA_Backtest):
86 | '''
87 | 多线程模式回测示例
88 |
89 | '''
90 |
91 | def __init__(self, market_type, frequence, start, end, code_list, commission_fee):
92 | super().__init__(market_type, frequence, start, end, code_list, commission_fee)
93 | self.account = self.portfolio.add_account( MAMINT0Strategy(user_cookie=self.user.user_cookie, portfolio_cookie= self.portfolio.portfolio_cookie))
94 |
95 | def after_success(self):
96 | QA_util_log_info(self.account.history_table)
97 | risk = QA_Risk(self.account, benchmark_code='000300',
98 | benchmark_type=MARKET_TYPE.INDEX_CN)
99 |
100 | print(risk().T)
101 | self.account.save()
102 | risk.save()
103 | risk.plot_assets_curve()
104 | print(risk.profit_construct)
105 |
106 |
107 | # In[4]:
108 |
109 |
110 | import QUANTAXIS as QA
111 | backtest = Backtest(market_type=MARKET_TYPE.STOCK_CN,
112 | frequence=FREQUENCE.FIFTEEN_MIN,
113 | start='2018-11-01',
114 | end='2018-12-10',
115 | code_list=['000001'],
116 | commission_fee=0.00015)
117 | backtest.start_market()
118 |
119 | backtest.run()
120 | backtest.stop()
121 |
122 |
123 | # In[5]:
124 |
125 |
126 | print(backtest.account.history_table)
127 |
--------------------------------------------------------------------------------
/config/install_ubuntu.sh:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QUANTAXIS/QADemoOLD/ed8cc09fc373fe665459e0e8e3d362d5d48894f3/config/install_ubuntu.sh
--------------------------------------------------------------------------------
/config/readme.md:
--------------------------------------------------------------------------------
1 | # 配置/脚本区
2 |
3 | - ubuntu16.sh ubuntu 16 一键安装脚本
4 | - startjupyter.sh 开启jupyter notebook
5 | - run_backend.sh 开启mongod后台,WEBKIT前后台
6 | - update_data.py 更新数据脚本
7 |
--------------------------------------------------------------------------------
/config/run_backend.sh:
--------------------------------------------------------------------------------
1 | # run mongo
2 |
3 | service mongod restart
4 |
5 | # nohup mongod &
6 |
7 |
8 | cd ../QUANTAXIS_WEBKIT/backend
9 | forever start bin/www
10 |
11 | cd ../web
12 | forever start build/dev-server.js
--------------------------------------------------------------------------------
/config/startjupyter.sh:
--------------------------------------------------------------------------------
1 | #sudo python3.6 -m pip install jupyter -i https://pypi.doubanio.com/simple
2 |
3 | cd ../jupyterexample
4 | jupyter notebook --ip=0.0.0.0 --allow-root
5 |
--------------------------------------------------------------------------------
/config/ubuntu16.sh:
--------------------------------------------------------------------------------
1 | echo 'INSTALL_QUANTAXIS'
2 |
3 | echo 'USING ALIYUN deb'
4 |
5 | echo "deb-src http://archive.ubuntu.com/ubuntu xenial main restricted #Added by software-properties
6 | deb http://mirrors.aliyun.com/ubuntu/ xenial main restricted
7 | deb-src http://mirrors.aliyun.com/ubuntu/ xenial main restricted multiverse universe #Added by software-properties
8 | deb http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted
9 | deb-src http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted multiverse universe #Added by software-properties
10 | deb http://mirrors.aliyun.com/ubuntu/ xenial universe
11 | deb http://mirrors.aliyun.com/ubuntu/ xenial-updates universe
12 | deb http://mirrors.aliyun.com/ubuntu/ xenial multiverse
13 | deb http://mirrors.aliyun.com/ubuntu/ xenial-updates multiverse
14 | deb http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse
15 | deb-src http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse #Added by software-properties
16 | deb http://archive.canonical.com/ubuntu xenial partner
17 | deb-src http://archive.canonical.com/ubuntu xenial partner
18 | deb http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted
19 | deb-src http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted multiverse universe #Added by software-properties
20 | deb http://mirrors.aliyun.com/ubuntu/ xenial-security universe
21 | deb http://mirrors.aliyun.com/ubuntu/ xenial-security multiverse " | tee /etc/apt/sources.list.d/sources.list
22 |
23 | apt-get update
24 |
25 | apt install software-properties-common
26 |
27 | # add-apt-repository ppa:jonathonf/python-3.6
28 | # apt-get update
29 |
30 |
31 | # apt-get install python3.6-dev
32 | wget https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/Anaconda3-5.1.0-Linux-x86_64.sh
33 | bash Anaconda3-5.1.0-Linux-x86_64.sh
34 |
35 | source ~/.bashrc
36 |
37 | wget https://bootstrap.pypa.io/get-pip.py
38 |
39 | python get-pip.py
40 |
41 |
42 | apt-get install libxml2-dev libxslt-dev
43 | apt-get install git
44 | cd ~
45 | git clone https://github.com/yutiansut/quantaxis
46 | # add some permission for quantaxis
47 | chmod -R 777 ./quantaxis
48 | cd ~/quantaxis
49 | python -m pip install pillow -i https://pypi.doubanio.com/simple
50 | python -m pip install -r requirements.txt -i https://pypi.doubanio.com/simple
51 | python -m pip install tushare
52 | python -m pip install pytdx
53 | python -m pip install -e .
54 |
55 |
56 |
57 | apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 2930ADAE8CAF5059EE73BB4B58712A2291FA4AD5
58 | # Ubuntu 16.04
59 | echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.6 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.6.list
60 |
61 | # 更新
62 | apt-get update
63 | # 安装MongoDB
64 | apt-get install -y mongodb-org --allow-unauthenticated
65 | cd /
66 | mkdir data
67 | cd data
68 | mkdir data
69 | mkdir log
70 |
71 | # 开启MongoDB服务
72 | service mongod start
73 |
74 | apt-get install curl
75 | curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
76 | apt-get install -y nodejs
77 | apt-get install npm
78 | npm install npm -g #更新npm
79 | npm install forever -g #安装一个全局的forever 用于之后启动
80 | npm install cnpm -g
81 |
82 | cd ~/quantaxis/QUANTAXIS_Webkit/backend
83 | npm install
84 |
85 |
86 | cd ~/quantaxis/QUANTAXIS_Webkit/web
87 | npm install
88 |
89 |
90 |
--------------------------------------------------------------------------------
/config/update_all.py:
--------------------------------------------------------------------------------
1 | #coding :utf-8
2 | #
3 | # The MIT License (MIT)
4 | #
5 | # Copyright (c) 2016-2018 yutiansut/QUANTAXIS
6 | #
7 | # Permission is hereby granted, free of charge, to any person obtaining a copy
8 | # of this software and associated documentation files (the "Software"), to deal
9 | # in the Software without restriction, including without limitation the rights
10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | # copies of the Software, and to permit persons to whom the Software is
12 | # furnished to do so, subject to the following conditions:
13 | #
14 | # The above copyright notice and this permission notice shall be included in all
15 | # copies or substantial portions of the Software.
16 | #
17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | # SOFTWARE.
24 |
25 |
26 | """对应于save all
27 | """
28 |
29 | from QUANTAXIS.QASU.main import (QA_SU_save_etf_day, QA_SU_save_etf_min,
30 | QA_SU_save_financialfiles,
31 | QA_SU_save_index_day, QA_SU_save_index_min,
32 | QA_SU_save_stock_block, QA_SU_save_stock_day,
33 | QA_SU_save_stock_info,
34 | QA_SU_save_stock_info_tushare,
35 | QA_SU_save_stock_list, QA_SU_save_stock_min,
36 | QA_SU_save_stock_xdxr)
37 | from QUANTAXIS.QASU.save_binance import (QA_SU_save_binance,
38 | QA_SU_save_binance_1day,
39 | QA_SU_save_binance_1hour,
40 | QA_SU_save_binance_1min,
41 | QA_SU_save_binance_symbol)
42 |
43 |
44 | QA_SU_save_stock_day('tdx')
45 | QA_SU_save_stock_xdxr('tdx')
46 | # QA_SU_save_stock_min('tdx')
47 | QA_SU_save_index_day('tdx')
48 | # QA_SU_save_index_min('tdx')
49 | # QA_SU_save_etf_day('tdx')
50 | # QA_SU_save_etf_min('tdx')
51 | QA_SU_save_stock_list('tdx')
52 | QA_SU_save_stock_block('tdx')
53 | # QA_SU_save_stock_info('tdx')
--------------------------------------------------------------------------------
/config/update_data.py:
--------------------------------------------------------------------------------
1 | #coding :utf-8
2 | #
3 | # The MIT License (MIT)
4 | #
5 | # Copyright (c) 2016-2018 yutiansut/QUANTAXIS
6 | #
7 | # Permission is hereby granted, free of charge, to any person obtaining a copy
8 | # of this software and associated documentation files (the "Software"), to deal
9 | # in the Software without restriction, including without limitation the rights
10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | # copies of the Software, and to permit persons to whom the Software is
12 | # furnished to do so, subject to the following conditions:
13 | #
14 | # The above copyright notice and this permission notice shall be included in all
15 | # copies or substantial portions of the Software.
16 | #
17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | # SOFTWARE.
24 |
25 | import datetime
26 | from QUANTAXIS import (QA_SU_save_etf_day, QA_SU_save_index_day, QA_SU_save_stock_min,
27 | QA_SU_save_stock_block, QA_SU_save_stock_day,QA_SU_save_etf_min,
28 | QA_SU_save_stock_list, QA_SU_save_stock_xdxr,
29 | QA_util_log_info)
30 |
31 | print('SAVE/UPDATE {}'.format(datetime.datetime.now()))
32 |
33 | QA_SU_save_stock_day('tdx')
34 | QA_SU_save_stock_xdxr('tdx')
35 | QA_SU_save_etf_day('tdx')
36 | QA_SU_save_index_day('tdx')
37 | QA_SU_save_stock_list('tdx')
38 | QA_SU_save_stock_block('tdx')
39 |
--------------------------------------------------------------------------------
/config/update_x.py:
--------------------------------------------------------------------------------
1 | #coding :utf-8
2 | #
3 | # The MIT License (MIT)
4 | #
5 | # Copyright (c) 2016-2018 yutiansut/QUANTAXIS
6 | #
7 | # Permission is hereby granted, free of charge, to any person obtaining a copy
8 | # of this software and associated documentation files (the "Software"), to deal
9 | # in the Software without restriction, including without limitation the rights
10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | # copies of the Software, and to permit persons to whom the Software is
12 | # furnished to do so, subject to the following conditions:
13 | #
14 | # The above copyright notice and this permission notice shall be included in all
15 | # copies or substantial portions of the Software.
16 | #
17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | # SOFTWARE.
24 |
25 |
26 | """对应于save x
27 | """
28 | from QUANTAXIS.QASU.main import (QA_SU_save_etf_day, QA_SU_save_etf_min,
29 | QA_SU_save_financialfiles,
30 | QA_SU_save_index_day, QA_SU_save_index_min,
31 | QA_SU_save_stock_block, QA_SU_save_stock_day,
32 | QA_SU_save_stock_info,
33 | QA_SU_save_stock_info_tushare,
34 | QA_SU_save_stock_list, QA_SU_save_stock_min,
35 | QA_SU_save_stock_xdxr)
36 | from QUANTAXIS.QASU.save_binance import (QA_SU_save_binance,
37 | QA_SU_save_binance_1day,
38 | QA_SU_save_binance_1hour,
39 | QA_SU_save_binance_1min,
40 | QA_SU_save_binance_symbol)
41 |
42 |
43 | QA_SU_save_stock_day('tdx')
44 | QA_SU_save_stock_xdxr('tdx')
45 | QA_SU_save_stock_min('tdx')
46 | QA_SU_save_index_day('tdx')
47 | QA_SU_save_index_min('tdx')
48 | QA_SU_save_etf_day('tdx')
49 | QA_SU_save_etf_min('tdx')
50 | QA_SU_save_stock_list('tdx')
51 | QA_SU_save_stock_block('tdx')
52 | QA_SU_save_stock_info('tdx')
--------------------------------------------------------------------------------
/config/windows_autojob_updatedata.md:
--------------------------------------------------------------------------------
1 | # WINDOWS开启自动脚本
2 |
3 |
4 |
5 | - [WINDOWS开启自动脚本](#windows开启自动脚本)
6 | - [打开控制面板-系统和安全-管理工具](#打开控制面板-系统和安全-管理工具)
7 | - [打开计划任务程序](#打开计划任务程序)
8 | - [在计划任务程序中,新建任务](#在计划任务程序中新建任务)
9 | - [创建QUANTAXIS_Update任务](#创建quantaxis_update任务)
10 | - [选择运行时间/频率](#选择运行时间频率)
11 | - [选择执行的命令](#选择执行的命令)
12 | - [配置完毕](#配置完毕)
13 |
14 |
15 |
16 | 我们使用计划任务来开启自动更新任务:
17 |
18 |
19 | ## 打开控制面板-系统和安全-管理工具
20 | 
21 |
22 | ## 打开计划任务程序
23 | 
24 |
25 | ## 在计划任务程序中,新建任务
26 | 
27 |
28 | ## 创建QUANTAXIS_Update任务
29 | 
30 |
31 | ## 选择运行时间/频率
32 | 
33 |
34 | ## 选择执行的命令
35 | 
36 |
37 | ## 配置完毕
38 | 
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # QUANTAXIS DEMO
2 |
3 | quantaxis的一些使用示例
4 |
5 |
6 | ## 使用方法:
7 |
8 | 先将此项目 ```FORK```到你自己的账户中
9 |
10 |
11 | ```bash
12 | git clone https://github.com/[你的github账号]/qademo
13 | ```
14 |
15 | ## 后台运行脚本
16 |
17 | ```
18 | sudo chmod -R 777 ./qademo
19 | cd qademo
20 | sudo nohup ./startjupyter.sh &
21 | ```
22 |
23 | ## 更新代码
24 |
25 | 通过从 yutiansut/qademo 向你的项目推```pull request```来对项目进行更新
26 |
27 | ## 贡献代码
28 |
29 | 通过从 你的项目 向 yutiansut/qademo 推 ```pull request``` 来贡献你的代码
--------------------------------------------------------------------------------
/research/RNN_EXAMPLE/RNN-example_using_keras.py:
--------------------------------------------------------------------------------
1 |
2 | # coding: utf-8
3 |
4 | # In[3]:
5 |
6 |
7 | import keras
8 | import numpy as np
9 | import matplotlib.pyplot as plt
10 | import pandas as pd
11 | from pandas import datetime
12 | import math
13 | import time
14 | import itertools
15 | from sklearn import preprocessing
16 | import datetime
17 | from operator import itemgetter
18 | from sklearn.metrics import mean_squared_error
19 | from math import sqrt
20 | from keras.models import Sequential
21 | from keras.layers.core import Dense, Dropout, Activation
22 | from keras.layers.recurrent import LSTM
23 | import QUANTAXIS as QA
24 |
25 |
26 | # In[23]:
27 |
28 |
29 | # load data function
30 | def load_data(stock, seq_len):
31 | # stock 是一个input的dataframe
32 | amount_of_features = len(stock.columns)
33 | data = stock.as_matrix() # pd.DataFrame(stock)
34 | sequence_length = seq_len + 1
35 | result = []
36 | for index in range(len(data) - sequence_length):
37 | result.append(data[index: index + sequence_length])
38 |
39 | result = np.array(result)
40 | row = round(0.9 * result.shape[0])
41 | train = result[:int(row), :]
42 | x_train = train[:, :-1]
43 | y_train = train[:, -1][:, -1]
44 | x_test = result[int(row):, :-1]
45 | y_test = result[int(row):, -1][:, -1]
46 |
47 | x_train = np.reshape(
48 | x_train, (x_train.shape[0], x_train.shape[1], amount_of_features))
49 | x_test = np.reshape(
50 | x_test, (x_test.shape[0], x_test.shape[1], amount_of_features))
51 |
52 | return [x_train, y_train, x_test, y_test]
53 |
54 |
55 | def build_model(layers):
56 | model = Sequential()
57 |
58 | model.add(LSTM(
59 | input_dim=layers[0],
60 | output_dim=layers[1],
61 | return_sequences=True))
62 | model.add(Dropout(0.2))
63 |
64 | model.add(LSTM(
65 | layers[2],
66 | return_sequences=False))
67 | model.add(Dropout(0.2))
68 |
69 | model.add(Dense(
70 | output_dim=layers[2]))
71 | model.add(Activation("linear"))
72 |
73 | start = time.time()
74 | model.compile(loss="mse", optimizer="rmsprop", metrics=['accuracy'])
75 | print("Compilation Time : ", time.time() - start)
76 | return model
77 |
78 |
79 | def build_model2(layers):
80 | d = 0.2
81 | model = Sequential()
82 | model.add(LSTM(128, input_shape=(
83 | layers[1], layers[0]), return_sequences=True))
84 | model.add(Dropout(d))
85 | model.add(LSTM(64, input_shape=(
86 | layers[1], layers[0]), return_sequences=False))
87 | model.add(Dropout(d))
88 | model.add(Dense(16, init='uniform', activation='relu'))
89 | model.add(Dense(1, init='uniform', activation='relu'))
90 | model.compile(loss='mse', optimizer='adam', metrics=['accuracy'])
91 | return model
92 |
93 |
94 | # In[10]:
95 |
96 |
97 | data = QA.QA_fetch_stock_day_adv('000001', '2000-01-01', '2018-01-31').to_qfq()
98 |
99 |
100 | # In[14]:
101 |
102 |
103 | data.plot()
104 |
105 |
106 | # In[21]:
107 |
108 |
109 | used_data = pd.concat([data.open, data.high, data.close], axis=1)
110 |
111 |
112 | # In[25]:
113 |
114 |
115 | window = 5
116 | X_train, y_train, X_test, y_test = load_data(used_data[::-1], window)
117 |
118 |
119 | # In[27]:
120 |
121 |
122 | X_train
123 |
124 |
125 | # In[28]:
126 |
127 |
128 | model = build_model2([3, window, 1])
129 |
130 |
131 | # In[29]:
132 |
133 |
134 | model.fit(
135 | X_train,
136 | y_train,
137 | batch_size=512,
138 | nb_epoch=500,
139 | validation_split=0.1,
140 | verbose=0)
141 |
142 |
143 | # In[30]:
144 |
145 |
146 | # print(X_test[-1])
147 | diff = []
148 | ratio = []
149 | p = model.predict(X_test)
150 | for u in range(len(y_test)):
151 | pr = p[u][0]
152 | ratio.append((y_test[u]/pr)-1)
153 | diff.append(abs(y_test[u] - pr))
154 | #print(u, y_test[u], pr, (y_test[u]/pr)-1, abs(y_test[u]- pr))
155 |
156 |
157 | # In[31]:
158 |
159 |
160 | import matplotlib.pyplot as plt2
161 |
162 | plt2.plot(p, color='red', label='prediction')
163 | plt2.plot(y_test, color='blue', label='y_test')
164 | plt2.legend(loc='upper left')
165 | plt2.show()
166 |
--------------------------------------------------------------------------------
/research/马科维茨有效前沿实现/output_19_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QUANTAXIS/QADemoOLD/ed8cc09fc373fe665459e0e8e3d362d5d48894f3/research/马科维茨有效前沿实现/output_19_1.png
--------------------------------------------------------------------------------
/research/马科维茨有效前沿实现/output_34_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QUANTAXIS/QADemoOLD/ed8cc09fc373fe665459e0e8e3d362d5d48894f3/research/马科维茨有效前沿实现/output_34_1.png
--------------------------------------------------------------------------------
/research/马科维茨有效前沿实现/output_6_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QUANTAXIS/QADemoOLD/ed8cc09fc373fe665459e0e8e3d362d5d48894f3/research/马科维茨有效前沿实现/output_6_1.png
--------------------------------------------------------------------------------
/research/马科维茨有效前沿实现/output_9_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QUANTAXIS/QADemoOLD/ed8cc09fc373fe665459e0e8e3d362d5d48894f3/research/马科维茨有效前沿实现/output_9_1.png
--------------------------------------------------------------------------------
/research/马科维茨有效前沿实现/马科维茨的QUANTAXIS实现.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ```python
4 | import pandas as pd
5 | import numpy as np
6 | import statsmodels.api as sm
7 | import scipy.stats as scs
8 | import matplotlib.pyplot as plt
9 | import QUANTAXIS as QA
10 | ```
11 |
12 | QUANTAXIS>> start QUANTAXIS
13 | QUANTAXIS>> Welcome to QUANTAXIS, the Version is 1.0.66
14 | QUANTAXIS>>
15 | ````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````
16 | ``########`````##````````##``````````##`````````####````````##```##########````````#``````##``````###```##`````######``
17 | `##``````## ```##````````##`````````####````````##`##```````##```````##```````````###``````##````##`````##```##`````##`
18 | ##````````##```##````````##````````##`##````````##``##``````##```````##``````````####```````#```##``````##```##``````##
19 | ##````````##```##````````##```````##```##```````##```##`````##```````##`````````##`##```````##`##```````##````##```````
20 | ##````````##```##````````##``````##`````##``````##````##````##```````##````````##``###```````###````````##`````##``````
21 | ##````````##```##````````##``````##``````##`````##`````##```##```````##```````##````##```````###````````##``````###````
22 | ##````````##```##````````##`````##````````##````##``````##``##```````##``````##``````##`````##`##```````##````````##```
23 | ##````````##```##````````##````#############````##```````##`##```````##`````###########`````##``##``````##`````````##``
24 | ###```````##```##````````##```##```````````##```##```````##`##```````##````##`````````##```##```##``````##```##`````##`
25 | `##``````###````##``````###``##`````````````##``##````````####```````##```##``````````##``###````##`````##````##`````##
26 | ``#########``````########```##``````````````###`##``````````##```````##``##````````````##`##``````##````##`````###``###
27 | ````````#####`````````````````````````````````````````````````````````````````````````````````````````````````````##``
28 | ```````````````````````````````````````````````````````````````````````````````````````````````````````````````````````
29 | ``````````````````````````Copyright``yutiansut``2018``````QUANTITATIVE FINANCIAL FRAMEWORK`````````````````````````````
30 | ```````````````````````````````````````````````````````````````````````````````````````````````````````````````````````
31 | ````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````
32 | ````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````
33 |
34 |
35 |
36 | # 1. 获取股票, 并选取close 进行初步分析
37 |
38 |
39 | ```python
40 | # 获取上证50中的四根票
41 | code=QA.QA_fetch_stock_block_adv().get_block('上证50').code[0:4]
42 | ```
43 |
44 |
45 | ```python
46 | data=QA.QA_fetch_stock_day_adv(code,'2018-01-01','2018-07-16').to_qfq()
47 | ```
48 |
49 |
50 | ```python
51 |
52 | # 选择close序列, 进行pivot成表
53 | close=data.pivot('close')
54 |
55 | close.head()
56 | ```
57 |
58 |
59 |
60 |
61 |
62 |
75 |
76 |
77 |
78 | code |
79 | 600000 |
80 | 600016 |
81 | 600019 |
82 | 600028 |
83 |
84 |
85 | date |
86 | |
87 | |
88 | |
89 | |
90 |
91 |
92 |
93 |
94 | 2018-01-02 |
95 | 12.587085 |
96 | 7.006029 |
97 | 8.521262 |
98 | 6.008582 |
99 |
100 |
101 | 2018-01-03 |
102 | 12.527712 |
103 | 7.055368 |
104 | 8.492731 |
105 | 6.102908 |
106 |
107 |
108 | 2018-01-04 |
109 | 12.527712 |
110 | 7.022475 |
111 | 8.502242 |
112 | 6.508511 |
113 |
114 |
115 | 2018-01-05 |
116 | 12.557398 |
117 | 7.071814 |
118 | 8.435669 |
119 | 6.659433 |
120 |
121 |
122 | 2018-01-08 |
123 | 12.547503 |
124 | 7.170490 |
125 | 8.835103 |
126 | 6.650000 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 | ## 使用基准价格比较股票
135 |
136 |
137 | ```python
138 | (close/close.iloc[0]*100).plot(figsize = (18,16))
139 | ```
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 | 
150 |
151 |
152 | ## 计算收益率
153 |
154 |
155 | ```python
156 | log_returns=np.log(close/close.shift(1))
157 | log_returns.head()
158 | ```
159 |
160 |
161 |
162 |
163 |
164 |
177 |
178 |
179 |
180 | code |
181 | 600000 |
182 | 600016 |
183 | 600019 |
184 | 600028 |
185 |
186 |
187 | date |
188 | |
189 | |
190 | |
191 | |
192 |
193 |
194 |
195 |
196 | 2018-01-02 |
197 | NaN |
198 | NaN |
199 | NaN |
200 | NaN |
201 |
202 |
203 | 2018-01-03 |
204 | -0.004728 |
205 | 0.007018 |
206 | -0.003354 |
207 | 0.015577 |
208 |
209 |
210 | 2018-01-04 |
211 | 0.000000 |
212 | -0.004673 |
213 | 0.001119 |
214 | 0.064345 |
215 |
216 |
217 | 2018-01-05 |
218 | 0.002367 |
219 | 0.007001 |
220 | -0.007861 |
221 | 0.022924 |
222 |
223 |
224 | 2018-01-08 |
225 | -0.000788 |
226 | 0.013857 |
227 | 0.046264 |
228 | -0.001417 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 | ```python
238 | log_returns.hist(bins = 50, figsize = (19,16))
239 | ```
240 |
241 |
242 |
243 |
244 | array([[,
245 | ],
246 | [,
247 | ]],
248 | dtype=object)
249 |
250 |
251 |
252 |
253 | 
254 |
255 |
256 |
257 | ```python
258 | log_returns.cov()*252
259 | ```
260 |
261 |
262 |
263 |
264 |
265 |
278 |
279 |
280 |
281 | code |
282 | 600000 |
283 | 600016 |
284 | 600019 |
285 | 600028 |
286 |
287 |
288 | code |
289 | |
290 | |
291 | |
292 | |
293 |
294 |
295 |
296 |
297 | 600000 |
298 | 0.046201 |
299 | 0.030160 |
300 | 0.037957 |
301 | 0.028727 |
302 |
303 |
304 | 600016 |
305 | 0.030160 |
306 | 0.040633 |
307 | 0.036671 |
308 | 0.032252 |
309 |
310 |
311 | 600019 |
312 | 0.037957 |
313 | 0.036671 |
314 | 0.135902 |
315 | 0.046658 |
316 |
317 |
318 | 600028 |
319 | 0.028727 |
320 | 0.032252 |
321 | 0.046658 |
322 | 0.096903 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 | ```python
332 | noa=len(code)
333 | ```
334 |
335 | ## 给不同股票随意分配权重
336 |
337 |
338 | ```python
339 | weights = np.random.random(noa)
340 | weights /= np.sum(weights)
341 | weights
342 | ```
343 |
344 |
345 |
346 |
347 | array([0.21942895, 0.14466788, 0.17803594, 0.45786723])
348 |
349 |
350 |
351 | ## 计算预期组合年化收益、组合方差和组合标准差
352 |
353 |
354 | ```python
355 | np.sum(log_returns.mean()*weights)*252
356 | ```
357 |
358 |
359 |
360 |
361 | -0.16519203884200712
362 |
363 |
364 |
365 |
366 | ```python
367 | np.dot(weights.T, np.dot(log_returns.cov()*252,weights))
368 | ```
369 |
370 |
371 |
372 |
373 | 0.05211897463039171
374 |
375 |
376 |
377 |
378 | ```python
379 | np.sqrt(np.dot(weights.T, np.dot(log_returns.cov()* 252,weights)))
380 | ```
381 |
382 |
383 |
384 |
385 | 0.2282958051090552
386 |
387 |
388 |
389 | ## 用蒙特卡洛模拟产生大量随机组合
390 |
391 | 进行到此,我们最想知道的是给定的一个股票池(证券组合)如何找到风险和收益平衡的位置。
392 |
393 | 下面通过一次蒙特卡洛模拟,产生大量随机的权重向量,并记录随机组合的预期收益和方差。
394 |
395 |
396 | ```python
397 | port_returns = []
398 | port_variance = []
399 | for p in range(4000):
400 | weights = np.random.random(noa)
401 | weights /=np.sum(weights)
402 | port_returns.append(np.sum(log_returns.mean()*252*weights))
403 | port_variance.append(np.sqrt(np.dot(weights.T, np.dot(log_returns.cov()*252, weights))))
404 |
405 | port_returns = np.array(port_returns)
406 | port_variance = np.array(port_variance)
407 |
408 | #无风险利率设定为4%
409 | risk_free = 0.04
410 | plt.figure(figsize = (8,4))
411 | plt.scatter(port_variance, port_returns, c=(port_returns-risk_free)/port_variance, marker = 'o')
412 | plt.grid(True)
413 | plt.xlabel('excepted volatility')
414 | plt.ylabel('expected return')
415 | plt.colorbar(label = 'Sharpe ratio')
416 | ```
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 | 
427 |
428 |
429 | # 投资组合优化1——sharpe最大
430 |
431 | 建立statistics函数来记录重要的投资组合统计数据(收益,方差和夏普比)
432 |
433 | 通过对约束最优问题的求解,得到最优解。其中约束是权重总和为1。
434 |
435 |
436 | ```python
437 | def statistics(weights):
438 | weights = np.array(weights)
439 | port_returns = np.sum(log_returns.mean()*weights)*252
440 | port_variance = np.sqrt(np.dot(weights.T, np.dot(log_returns.cov()*252,weights)))
441 | return np.array([port_returns, port_variance, port_returns/port_variance])
442 |
443 | #最优化投资组合的推导是一个约束最优化问题
444 | import scipy.optimize as sco
445 |
446 | #最小化夏普指数的负值
447 | def min_sharpe(weights):
448 | return -statistics(weights)[2]
449 |
450 | #约束是所有参数(权重)的总和为1。这可以用minimize函数的约定表达如下
451 | cons = ({'type':'eq', 'fun':lambda x: np.sum(x)-1})
452 |
453 | #我们还将参数值(权重)限制在0和1之间。这些值以多个元组组成的一个元组形式提供给最小化函数
454 | bnds = tuple((0,1) for x in range(noa))
455 |
456 | #优化函数调用中忽略的唯一输入是起始参数列表(对权重的初始猜测)。我们简单的使用平均分布。
457 | opts = sco.minimize(min_sharpe, noa*[1./noa,], method = 'SLSQP', bounds = bnds, constraints = cons)
458 | opts
459 | ```
460 |
461 |
462 |
463 |
464 | fun: -0.3395589843140905
465 | jac: array([1.88688774, 1.29688912, 0.85391124, 0. ])
466 | message: 'Optimization terminated successfully.'
467 | nfev: 12
468 | nit: 2
469 | njev: 2
470 | status: 0
471 | success: True
472 | x: array([7.21644966e-16, 0.00000000e+00, 0.00000000e+00, 1.00000000e+00])
473 |
474 |
475 |
476 |
477 | 得到的最优组合权重向量为:
478 |
479 |
480 | ```python
481 | opts['x'].round(3)
482 | ```
483 |
484 |
485 |
486 |
487 | array([0., 0., 0., 1.])
488 |
489 |
490 |
491 | sharpe最大的组合3个统计数据分别为:
492 |
493 |
494 | ```python
495 | #预期收益率、预期波动率、最优夏普指数
496 | statistics(opts['x']).round(3)
497 | ```
498 |
499 |
500 |
501 |
502 | array([0.106, 0.311, 0.34 ])
503 |
504 |
505 |
506 | ## 投资组合优化2——方差最小
507 | 接下来,我们通过方差最小来选出最优投资组合。
508 |
509 |
510 | ```python
511 | #但是我们定义一个函数对 方差进行最小化
512 | def min_variance(weights):
513 | return statistics(weights)[1]
514 |
515 | optv = sco.minimize(min_variance, noa*[1./noa,],method = 'SLSQP', bounds = bnds, constraints = cons)
516 | optv
517 | ```
518 |
519 |
520 |
521 |
522 | fun: 0.18986885342564985
523 | jac: array([0.18988797, 0.18988497, 0.19980709, 0.18966556])
524 | message: 'Optimization terminated successfully.'
525 | nfev: 48
526 | nit: 8
527 | njev: 8
528 | status: 0
529 | success: True
530 | x: array([0.37442787, 0.54700915, 0. , 0.07856297])
531 |
532 |
533 |
534 | 方差最小的最优组合权重向量及组合的统计数据分别为:
535 |
536 |
537 | ```python
538 | optv['x'].round(3)
539 | ```
540 |
541 |
542 |
543 |
544 | array([0.374, 0.547, 0. , 0.079])
545 |
546 |
547 |
548 |
549 | ```python
550 | #得到的预期收益率、波动率和夏普指数
551 | statistics(optv['x']).round(3)
552 | ```
553 |
554 |
555 |
556 |
557 | array([-0.401, 0.19 , -2.115])
558 |
559 |
560 |
561 | ## 组合的有效前沿
562 | 有效前沿有既定的目标收益率下方差最小的投资组合构成。
563 |
564 | 在最优化时采用两个约束,1.给定目标收益率,2.投资组合权重和为1。
565 |
566 |
567 | ```python
568 |
569 | def min_variancemin_varia (weights):
570 | return statistics(weights)[1]
571 |
572 | #在不同目标收益率水平(target_returns)循环时,最小化的一个约束条件会变化。
573 | target_returns = np.linspace(0.0,0.5,50)
574 | target_variance = []
575 | for tar in target_returns:
576 | cons = ({'type':'eq','fun':lambda x:statistics(x)[0]-tar},{'type':'eq','fun':lambda x:np.sum(x)-1})
577 | res = sco.minimize(min_variance, noa*[1./noa,],method = 'SLSQP', bounds = bnds, constraints = cons)
578 | target_variance.append(res['fun'])
579 |
580 | target_variance = np.array(target_variance)
581 | ```
582 |
583 | 下面是最优化结果的展示。
584 |
585 | 叉号:构成的曲线是有效前沿(目标收益率下最优的投资组合)
586 |
587 | 红星:sharpe最大的投资组合
588 |
589 | 黄星:方差最小的投资组合
590 |
591 |
592 | ```python
593 | plt.figure(figsize = (8,4))
594 | #圆圈:蒙特卡洛随机产生的组合分布
595 | plt.scatter(port_variance, port_returns, c = port_returns/port_variance,marker = 'o')
596 | #叉号:有效前沿
597 | plt.scatter(target_variance,target_returns, c = target_returns/target_variance, marker = 'x')
598 | #红星:标记最高sharpe组合
599 | plt.plot(statistics(opts['x'])[1], statistics(opts['x'])[0], 'r*', markersize = 15.0)
600 | #黄星:标记最小方差组合
601 | plt.plot(statistics(optv['x'])[1], statistics(optv['x'])[0], 'y*', markersize = 15.0)
602 | plt.grid(True)
603 | plt.xlabel('expected volatility')
604 | plt.ylabel('expected return')
605 | plt.colorbar(label = 'Sharpe ratio')
606 | ```
607 |
608 |
609 |
610 |
611 |
612 |
613 |
614 |
615 |
616 | 
617 |
618 |
--------------------------------------------------------------------------------
/startjupyter.bat:
--------------------------------------------------------------------------------
1 | jupyter notebook
--------------------------------------------------------------------------------
/startjupyter.sh:
--------------------------------------------------------------------------------
1 | echo 'start jupter notebook'
2 |
3 | jupyter notebook --ip=0.0.0.0 --allow-root -y
--------------------------------------------------------------------------------
/test_backtest/FUTURE/TEST 期货的多空下单.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 1,
6 | "metadata": {},
7 | "outputs": [],
8 | "source": [
9 | "import QUANTAXIS as QA"
10 | ]
11 | },
12 | {
13 | "cell_type": "code",
14 | "execution_count": 2,
15 | "metadata": {},
16 | "outputs": [],
17 | "source": [
18 | "acc=QA.QA_Account(allow_sellopen=True,init_cash=10000,allow_t0=True,account_cookie='future_test',market_type=QA.MARKET_TYPE.FUTURE_CN,frequence=QA.FREQUENCE.FIFTEEN_MIN)"
19 | ]
20 | },
21 | {
22 | "cell_type": "code",
23 | "execution_count": 3,
24 | "metadata": {},
25 | "outputs": [],
26 | "source": [
27 | "order=acc.send_order(code='RB1901', amount=1, time='2018-12-28 09:30:00', towards=QA.ORDER_DIRECTION.BUY_OPEN, price=3420, money=None, order_model=QA.ORDER_MODEL.MARKET, amount_model=QA.AMOUNT_MODEL.BY_AMOUNT)"
28 | ]
29 | },
30 | {
31 | "cell_type": "code",
32 | "execution_count": 4,
33 | "metadata": {},
34 | "outputs": [
35 | {
36 | "data": {
37 | "text/plain": [
38 | "6579.1449999999995"
39 | ]
40 | },
41 | "execution_count": 4,
42 | "metadata": {},
43 | "output_type": "execute_result"
44 | }
45 | ],
46 | "source": [
47 | "acc.cash_available"
48 | ]
49 | },
50 | {
51 | "cell_type": "code",
52 | "execution_count": 5,
53 | "metadata": {},
54 | "outputs": [
55 | {
56 | "data": {
57 | "text/plain": [
58 | "[10000]"
59 | ]
60 | },
61 | "execution_count": 5,
62 | "metadata": {},
63 | "output_type": "execute_result"
64 | }
65 | ],
66 | "source": [
67 | "acc.cash"
68 | ]
69 | },
70 | {
71 | "cell_type": "code",
72 | "execution_count": 6,
73 | "metadata": {},
74 | "outputs": [],
75 | "source": [
76 | "order2=acc.send_order(code='RB1901', amount=1, time='2018-12-28 09:30:00', towards=QA.ORDER_DIRECTION.SELL_OPEN, price=3420, money=None, order_model=QA.ORDER_MODEL.MARKET, amount_model=QA.AMOUNT_MODEL.BY_AMOUNT)"
77 | ]
78 | },
79 | {
80 | "cell_type": "code",
81 | "execution_count": 7,
82 | "metadata": {},
83 | "outputs": [
84 | {
85 | "data": {
86 | "text/plain": [
87 | "6579.1449999999995"
88 | ]
89 | },
90 | "execution_count": 7,
91 | "metadata": {},
92 | "output_type": "execute_result"
93 | }
94 | ],
95 | "source": [
96 | "acc.cash_available"
97 | ]
98 | },
99 | {
100 | "cell_type": "code",
101 | "execution_count": 8,
102 | "metadata": {},
103 | "outputs": [
104 | {
105 | "data": {
106 | "text/plain": [
107 | "[10000]"
108 | ]
109 | },
110 | "execution_count": 8,
111 | "metadata": {},
112 | "output_type": "execute_result"
113 | }
114 | ],
115 | "source": [
116 | "acc.cash"
117 | ]
118 | },
119 | {
120 | "cell_type": "code",
121 | "execution_count": 9,
122 | "metadata": {},
123 | "outputs": [
124 | {
125 | "data": {
126 | "text/plain": [
127 | "3"
128 | ]
129 | },
130 | "execution_count": 9,
131 | "metadata": {},
132 | "output_type": "execute_result"
133 | }
134 | ],
135 | "source": [
136 | "QA.ORDER_DIRECTION.BUY_CLOSE"
137 | ]
138 | },
139 | {
140 | "cell_type": "code",
141 | "execution_count": 10,
142 | "metadata": {},
143 | "outputs": [
144 | {
145 | "name": "stdout",
146 | "output_type": "stream",
147 | "text": [
148 | "0\n",
149 | "ERROR : CODE RB1901 TIME 2018-12-28 09:30:00 AMOUNT 1 TOWARDS 3\n",
150 | "空单仓位不足\n"
151 | ]
152 | }
153 | ],
154 | "source": [
155 | "order3=acc.send_order(code='RB1901', amount=1, time='2018-12-28 09:30:00', towards=QA.ORDER_DIRECTION.BUY_CLOSE, price=3420, money=None, order_model=QA.ORDER_MODEL.MARKET, amount_model=QA.AMOUNT_MODEL.BY_AMOUNT)"
156 | ]
157 | },
158 | {
159 | "cell_type": "code",
160 | "execution_count": 11,
161 | "metadata": {},
162 | "outputs": [
163 | {
164 | "data": {
165 | "text/plain": [
166 | "6579.1449999999995"
167 | ]
168 | },
169 | "execution_count": 11,
170 | "metadata": {},
171 | "output_type": "execute_result"
172 | }
173 | ],
174 | "source": [
175 | "acc.cash_available"
176 | ]
177 | },
178 | {
179 | "cell_type": "code",
180 | "execution_count": 12,
181 | "metadata": {},
182 | "outputs": [
183 | {
184 | "data": {
185 | "text/plain": [
186 | "Series([], Name: amount, dtype: float64)"
187 | ]
188 | },
189 | "execution_count": 12,
190 | "metadata": {},
191 | "output_type": "execute_result"
192 | }
193 | ],
194 | "source": [
195 | "acc.hold_available"
196 | ]
197 | },
198 | {
199 | "cell_type": "code",
200 | "execution_count": 13,
201 | "metadata": {},
202 | "outputs": [
203 | {
204 | "name": "stdout",
205 | "output_type": "stream",
206 | "text": [
207 | "ERROR : CODE RB1901 TIME 2018-12-28 09:30:00 AMOUNT 1 TOWARDS -3\n",
208 | "卖出仓位不足\n"
209 | ]
210 | }
211 | ],
212 | "source": [
213 | "order4=acc.send_order(code='RB1901', amount=1, time='2018-12-28 09:30:00', towards=QA.ORDER_DIRECTION.SELL_CLOSE, price=3420, money=None, order_model=QA.ORDER_MODEL.MARKET, amount_model=QA.AMOUNT_MODEL.BY_AMOUNT)"
214 | ]
215 | },
216 | {
217 | "cell_type": "code",
218 | "execution_count": null,
219 | "metadata": {},
220 | "outputs": [],
221 | "source": []
222 | },
223 | {
224 | "cell_type": "code",
225 | "execution_count": null,
226 | "metadata": {},
227 | "outputs": [],
228 | "source": []
229 | }
230 | ],
231 | "metadata": {
232 | "kernelspec": {
233 | "display_name": "Python 3",
234 | "language": "python",
235 | "name": "python3"
236 | },
237 | "language_info": {
238 | "codemirror_mode": {
239 | "name": "ipython",
240 | "version": 3
241 | },
242 | "file_extension": ".py",
243 | "mimetype": "text/x-python",
244 | "name": "python",
245 | "nbconvert_exporter": "python",
246 | "pygments_lexer": "ipython3",
247 | "version": "3.6.7"
248 | }
249 | },
250 | "nbformat": 4,
251 | "nbformat_minor": 2
252 | }
253 |
--------------------------------------------------------------------------------
/test_backtest/PERFORMANCE.py:
--------------------------------------------------------------------------------
1 |
2 | # coding: utf-8
3 |
4 | # In[2]:
5 |
6 |
7 | import QUANTAXIS as QA
8 |
9 |
10 | # In[4]:
11 |
12 |
13 | AC=QA.QA_Account().from_message(QA.QA_fetch_account()[-1])
14 |
15 |
16 | # In[6]:
17 |
18 |
19 | pr=QA.QA_Performance(AC)
20 |
21 |
22 | # In[8]:
23 |
24 |
25 | pr.pnl_fifo
26 |
27 |
28 | # In[11]:
29 |
30 |
31 | pr.plot_pnlmoney(pr.pnl_fifo)
32 |
33 |
34 | # In[12]:
35 |
36 |
37 | pr.plot_pnlratio(pr.pnl_fifo)
38 |
39 |
--------------------------------------------------------------------------------
/test_backtest/QAMARKET_SyncOrderExample.py:
--------------------------------------------------------------------------------
1 |
2 | # coding: utf-8
3 |
4 | # In[1]:
5 |
6 |
7 | import QUANTAXIS as QA
8 | from QUANTAXIS.QAMarket import QA_Market
9 | from QUANTAXIS.QAMarket.QAShipaneBroker import QA_SPEBroker
10 | from QUANTAXIS.QAMarket.QABacktestBroker import QA_BacktestBroker
11 | from concurrent import futures
12 | import threading
13 | import asyncio
14 |
15 | import datetime
16 | import pandas as pd
17 |
18 |
19 | # In[3]:
20 |
21 |
22 | market = QA_Market(if_start_orderthreading=True)
23 |
24 |
25 | # In[4]:
26 |
27 |
28 | market.start()
29 |
30 |
31 | # In[5]:
32 |
33 |
34 |
35 | market.connect(QA.BROKER_TYPE.SHIPANE)
36 |
37 |
38 | # In[6]:
39 |
40 |
41 | market.login(QA.BROKER_TYPE.SHIPANE,'account:1391')
42 |
43 |
44 | # In[7]:
45 |
46 |
47 | market.login(QA.BROKER_TYPE.SHIPANE,'account:141')
48 |
49 |
50 | # In[8]:
51 |
52 |
53 | market.login(QA.BROKER_TYPE.SHIPANE,'account:813')
54 |
55 |
56 | # In[9]:
57 |
58 |
59 | market.get_account_cookie()
60 |
61 |
62 | # In[10]:
63 |
64 |
65 | #data
66 | market._sync_orders()
67 |
68 |
69 | # In[12]:
70 |
71 |
72 | market.order_handler.order_status
73 |
74 |
75 | # In[13]:
76 |
77 |
78 | market.order_handler.deal_status
79 |
80 |
--------------------------------------------------------------------------------
/test_backtest/T0backtest.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 1,
6 | "metadata": {},
7 | "outputs": [
8 | {
9 | "name": "stderr",
10 | "output_type": "stream",
11 | "text": [
12 | "QUANTAXIS>> start QUANTAXIS\n",
13 | "QUANTAXIS>> Welcome to QUANTAXIS, the Version is 1.1.0\n",
14 | "QUANTAXIS>> \n",
15 | " ```````````````````````````````````````````````````````````````````````````````````````````````````````````````````````` \n",
16 | " ``########`````##````````##``````````##`````````####````````##```##########````````#``````##``````###```##`````######`` \n",
17 | " `##``````## ```##````````##`````````####````````##`##```````##```````##```````````###``````##````##`````##```##`````##` \n",
18 | " ##````````##```##````````##````````##`##````````##``##``````##```````##``````````####```````#```##``````##```##``````## \n",
19 | " ##````````##```##````````##```````##```##```````##```##`````##```````##`````````##`##```````##`##```````##````##``````` \n",
20 | " ##````````##```##````````##``````##`````##``````##````##````##```````##````````##``###```````###````````##`````##`````` \n",
21 | " ##````````##```##````````##``````##``````##`````##`````##```##```````##```````##````##```````###````````##``````###```` \n",
22 | " ##````````##```##````````##`````##````````##````##``````##``##```````##``````##``````##`````##`##```````##````````##``` \n",
23 | " ##````````##```##````````##````#############````##```````##`##```````##`````###########`````##``##``````##`````````##`` \n",
24 | " ###```````##```##````````##```##```````````##```##```````##`##```````##````##`````````##```##```##``````##```##`````##` \n",
25 | " `##``````###````##``````###``##`````````````##``##````````####```````##```##``````````##``###````##`````##````##`````## \n",
26 | " ``#########``````########```##``````````````###`##``````````##```````##``##````````````##`##``````##````##`````###``### \n",
27 | " ````````#####`````````````````````````````````````````````````````````````````````````````````````````````````````##`` \n",
28 | " ``````````````````````````````````````````````````````````````````````````````````````````````````````````````````````` \n",
29 | " ``````````````````````````Copyright``yutiansut``2018``````QUANTITATIVE FINANCIAL FRAMEWORK````````````````````````````` \n",
30 | " ``````````````````````````````````````````````````````````````````````````````````````````````````````````````````````` \n",
31 | " ```````````````````````````````````````````````````````````````````````````````````````````````````````````````````````` \n",
32 | " ```````````````````````````````````````````````````````````````````````````````````````````````````````````````````````` \n",
33 | " \n"
34 | ]
35 | }
36 | ],
37 | "source": [
38 | "from QUANTAXIS.QAARP.QAStrategy import QA_Strategy\n",
39 | "from QUANTAXIS.QAARP.QAAccount import QA_Account\n",
40 | "from QUANTAXIS.QAUtil.QAParameter import (AMOUNT_MODEL, MARKET_TYPE,\n",
41 | " FREQUENCE, ORDER_DIRECTION,\n",
42 | " ORDER_MODEL,RUNNING_ENVIRONMENT)\n",
43 | "import QUANTAXIS as QA\n",
44 | "\n",
45 | "import random\n"
46 | ]
47 | },
48 | {
49 | "cell_type": "code",
50 | "execution_count": 2,
51 | "metadata": {},
52 | "outputs": [],
53 | "source": [
54 | "class MAMINT0Strategy(QA_Account):\n",
55 | " def __init__(self,init_hold={'000001':10000,'000002':20000,'000004':40000}):\n",
56 | " super().__init__(init_hold=init_hold)\n",
57 | " self.running_environment=RUNNING_ENVIRONMENT.TZERO\n",
58 | " self.frequence = FREQUENCE.FIFTEEN_MIN\n",
59 | " self.market_type = MARKET_TYPE.STOCK_CN\n",
60 | " self.account_cookie ='LCW_T0'\n",
61 | "\n",
62 | " def on_bar(self, event):\n",
63 | " try:\n",
64 | " for item in event.market_data.code:\n",
65 | "\n",
66 | " print(self.current_time)\n",
67 | " print(self.datetime)\n",
68 | " print('=====SELL_AVAILABLE======')\n",
69 | " print(self.sell_available)\n",
70 | " print('=====HOLD_AVAILABLE======')\n",
71 | " print(self.hold_available)\n",
72 | " print('=====BUY_AVAILABLE=======')\n",
73 | " print(self.buy_available)\n",
74 | " if self.sell_available.get(item, 0) > 0:\n",
75 | " event.send_order(account_cookie=self.account_cookie,\n",
76 | " amount=int(self.sell_available[item]*random.random()/100)*100, amount_model=AMOUNT_MODEL.BY_AMOUNT,\n",
77 | " time=self.current_time, code=item, price=0,\n",
78 | " order_model=ORDER_MODEL.MARKET, towards=ORDER_DIRECTION.SELL,\n",
79 | " market_type=self.market_type, frequence=self.frequence,\n",
80 | " broker_name=self.broker\n",
81 | " )\n",
82 | " if random.random()>0.5:\n",
83 | " event.send_order(account_cookie=self.account_cookie,\n",
84 | " amount=random.randint(1,50)*100, amount_model=AMOUNT_MODEL.BY_AMOUNT,\n",
85 | " time=self.current_time, code=item, price=0,\n",
86 | " order_model=ORDER_MODEL.MARKET, towards=ORDER_DIRECTION.BUY,\n",
87 | " market_type=self.market_type, frequence=self.frequence,\n",
88 | " broker_name=self.broker)\n",
89 | " except:\n",
90 | " pass"
91 | ]
92 | },
93 | {
94 | "cell_type": "code",
95 | "execution_count": 3,
96 | "metadata": {},
97 | "outputs": [],
98 | "source": [
99 | "class MAMINT0Strategy1(QA_Account):\n",
100 | " def __init__(self,init_hold={'000001':10000,'000004':20000,'000008':40000}):\n",
101 | " super().__init__(init_hold=init_hold)\n",
102 | " self.running_environment=RUNNING_ENVIRONMENT.TZERO\n",
103 | " self.frequence = FREQUENCE.FIFTEEN_MIN\n",
104 | " self.market_type = MARKET_TYPE.STOCK_CN\n",
105 | " self.account_cookie ='LCW_T01'\n",
106 | "\n",
107 | " def on_bar(self, event):\n",
108 | " try:\n",
109 | " for item in event.market_data.code:\n",
110 | "\n",
111 | " print(self.current_time)\n",
112 | " print(self.datetime)\n",
113 | " print('=====SELL_AVAILABLE======')\n",
114 | " print(self.sell_available)\n",
115 | " print('=====HOLD_AVAILABLE======')\n",
116 | " print(self.hold_available)\n",
117 | " print('=====BUY_AVAILABLE=======')\n",
118 | " print(self.buy_available)\n",
119 | " if self.sell_available.get(item, 0) > 0:\n",
120 | " event.send_order(account_cookie=self.account_cookie,\n",
121 | " amount=int(self.sell_available[item]*random.random()/100)*100, amount_model=AMOUNT_MODEL.BY_AMOUNT,\n",
122 | " time=self.current_time, code=item, price=0,\n",
123 | " order_model=ORDER_MODEL.MARKET, towards=ORDER_DIRECTION.SELL,\n",
124 | " market_type=self.market_type, frequence=self.frequence,\n",
125 | " broker_name=self.broker\n",
126 | " )\n",
127 | " if random.random()>0.5:\n",
128 | " event.send_order(account_cookie=self.account_cookie,\n",
129 | " amount=random.randint(1,50)*100, amount_model=AMOUNT_MODEL.BY_AMOUNT,\n",
130 | " time=self.current_time, code=item, price=0,\n",
131 | " order_model=ORDER_MODEL.MARKET, towards=ORDER_DIRECTION.BUY,\n",
132 | " market_type=self.market_type, frequence=self.frequence,\n",
133 | " broker_name=self.broker)\n",
134 | " except:\n",
135 | " pass"
136 | ]
137 | },
138 | {
139 | "cell_type": "code",
140 | "execution_count": 4,
141 | "metadata": {},
142 | "outputs": [],
143 | "source": [
144 | "account1=MAMINT0Strategy()"
145 | ]
146 | },
147 | {
148 | "cell_type": "code",
149 | "execution_count": 5,
150 | "metadata": {},
151 | "outputs": [],
152 | "source": [
153 | "account2=MAMINT0Strategy1()"
154 | ]
155 | },
156 | {
157 | "cell_type": "code",
158 | "execution_count": 6,
159 | "metadata": {},
160 | "outputs": [],
161 | "source": [
162 | "user=QA.QA_User(user_cookie='LCW')"
163 | ]
164 | },
165 | {
166 | "cell_type": "code",
167 | "execution_count": 7,
168 | "metadata": {},
169 | "outputs": [
170 | {
171 | "data": {
172 | "text/plain": [
173 | "< QA_Account LCW_T01>"
174 | ]
175 | },
176 | "execution_count": 7,
177 | "metadata": {},
178 | "output_type": "execute_result"
179 | }
180 | ],
181 | "source": [
182 | "account2"
183 | ]
184 | },
185 | {
186 | "cell_type": "code",
187 | "execution_count": null,
188 | "metadata": {},
189 | "outputs": [],
190 | "source": []
191 | },
192 | {
193 | "cell_type": "code",
194 | "execution_count": 8,
195 | "metadata": {},
196 | "outputs": [],
197 | "source": [
198 | "port=user.new_portfolio(portfolio_cookie='LCW_t0')"
199 | ]
200 | },
201 | {
202 | "cell_type": "code",
203 | "execution_count": 9,
204 | "metadata": {},
205 | "outputs": [],
206 | "source": [
207 | "port.add_account(account1)"
208 | ]
209 | },
210 | {
211 | "cell_type": "code",
212 | "execution_count": 10,
213 | "metadata": {},
214 | "outputs": [],
215 | "source": [
216 | "port.add_account(account2)"
217 | ]
218 | },
219 | {
220 | "cell_type": "code",
221 | "execution_count": 11,
222 | "metadata": {},
223 | "outputs": [],
224 | "source": [
225 | "import pandas as pd"
226 | ]
227 | },
228 | {
229 | "cell_type": "code",
230 | "execution_count": 12,
231 | "metadata": {},
232 | "outputs": [
233 | {
234 | "data": {
235 | "text/html": [
236 | "\n",
237 | "\n",
250 | "
\n",
251 | " \n",
252 | " \n",
253 | " | \n",
254 | " | \n",
255 | " amount | \n",
256 | "
\n",
257 | " \n",
258 | " code | \n",
259 | " account_cookie | \n",
260 | " | \n",
261 | "
\n",
262 | " \n",
263 | " \n",
264 | " \n",
265 | " 000001 | \n",
266 | " LCW_T0 | \n",
267 | " 10000 | \n",
268 | "
\n",
269 | " \n",
270 | " 000002 | \n",
271 | " LCW_T0 | \n",
272 | " 20000 | \n",
273 | "
\n",
274 | " \n",
275 | " 000004 | \n",
276 | " LCW_T0 | \n",
277 | " 40000 | \n",
278 | "
\n",
279 | " \n",
280 | " 000001 | \n",
281 | " LCW_T01 | \n",
282 | " 10000 | \n",
283 | "
\n",
284 | " \n",
285 | " 000004 | \n",
286 | " LCW_T01 | \n",
287 | " 20000 | \n",
288 | "
\n",
289 | " \n",
290 | " 000008 | \n",
291 | " LCW_T01 | \n",
292 | " 40000 | \n",
293 | "
\n",
294 | " \n",
295 | "
\n",
296 | "
"
297 | ],
298 | "text/plain": [
299 | " amount\n",
300 | "code account_cookie \n",
301 | "000001 LCW_T0 10000\n",
302 | "000002 LCW_T0 20000\n",
303 | "000004 LCW_T0 40000\n",
304 | "000001 LCW_T01 10000\n",
305 | "000004 LCW_T01 20000\n",
306 | "000008 LCW_T01 40000"
307 | ]
308 | },
309 | "execution_count": 12,
310 | "metadata": {},
311 | "output_type": "execute_result"
312 | }
313 | ],
314 | "source": [
315 | "port.init_hold_table"
316 | ]
317 | },
318 | {
319 | "cell_type": "code",
320 | "execution_count": 13,
321 | "metadata": {},
322 | "outputs": [],
323 | "source": [
324 | "#pd.concat([account.init_hold_with_account for account in list(port.accounts.values())]).groupby('code').sum()"
325 | ]
326 | },
327 | {
328 | "cell_type": "code",
329 | "execution_count": 14,
330 | "metadata": {},
331 | "outputs": [],
332 | "source": [
333 | "\n",
334 | "from QUANTAXIS.QAARP.QARisk import QA_Risk\n",
335 | "from QUANTAXIS.QAARP.QAUser import QA_User\n",
336 | "from QUANTAXIS.QAApplication.QABacktest import QA_Backtest\n",
337 | "from QUANTAXIS.QAUtil.QALogs import QA_util_log_info\n",
338 | "from QUANTAXIS.QAUtil.QAParameter import FREQUENCE, MARKET_TYPE\n",
339 | "\n",
340 | "\n",
341 | "class Backtest(QA_Backtest):\n",
342 | " '''\n",
343 | " 多线程模式回测示例\n",
344 | "\n",
345 | " '''\n",
346 | "\n",
347 | " def __init__(self, market_type, frequence, start, end, code_list, commission_fee):\n",
348 | " super().__init__(market_type, frequence, start, end, code_list, commission_fee)\n",
349 | " self.user = QA_User()\n",
350 | " t0strategy=MAMINT0Strategy()\n",
351 | " # maminstrategy.reset_assets(1000)\n",
352 | " # self.portfolio, self.account = self.user.register_account(mastrategy)\n",
353 | " self.user = QA_User(user_cookie='user_admin')\n",
354 | " self.portfolio = self.user.new_portfolio('folio_admin')\n",
355 | " self.portfolio, self.account = self.user.register_account(t0strategy)\n",
356 | "\n",
357 | " def after_success(self):\n",
358 | " QA_util_log_info(self.account.history_table)\n",
359 | " risk = QA_Risk(self.account, benchmark_code='000300',\n",
360 | " benchmark_type=MARKET_TYPE.INDEX_CN)\n",
361 | "\n",
362 | " print(risk().T)\n",
363 | "\n",
364 | " self.account.save()\n",
365 | " risk.save()"
366 | ]
367 | },
368 | {
369 | "cell_type": "code",
370 | "execution_count": null,
371 | "metadata": {},
372 | "outputs": [],
373 | "source": []
374 | },
375 | {
376 | "cell_type": "code",
377 | "execution_count": null,
378 | "metadata": {},
379 | "outputs": [],
380 | "source": [
381 | "\n",
382 | "backtest = Backtest(market_type=MARKET_TYPE.STOCK_CN,\n",
383 | " frequence=FREQUENCE.FIFTEEN_MIN,\n",
384 | " start='2018-08-01',\n",
385 | " end='2018-08-05',\n",
386 | " code_list=['000001','000002','000004'],\n",
387 | " commission_fee=0.00015)\n",
388 | "backtest.start_market()\n",
389 | "\n",
390 | "backtest.run()\n",
391 | "backtest.stop()\n"
392 | ]
393 | },
394 | {
395 | "cell_type": "code",
396 | "execution_count": null,
397 | "metadata": {},
398 | "outputs": [],
399 | "source": [
400 | "backtest.account.hold_available"
401 | ]
402 | },
403 | {
404 | "cell_type": "code",
405 | "execution_count": null,
406 | "metadata": {},
407 | "outputs": [],
408 | "source": [
409 | "backtest.account.orders.queue_df"
410 | ]
411 | },
412 | {
413 | "cell_type": "code",
414 | "execution_count": null,
415 | "metadata": {},
416 | "outputs": [],
417 | "source": [
418 | "risk=QA.QA_Risk(backtest.account)"
419 | ]
420 | },
421 | {
422 | "cell_type": "code",
423 | "execution_count": null,
424 | "metadata": {},
425 | "outputs": [],
426 | "source": [
427 | "risk.profit_construct"
428 | ]
429 | },
430 | {
431 | "cell_type": "code",
432 | "execution_count": null,
433 | "metadata": {},
434 | "outputs": [],
435 | "source": [
436 | "backtest.account.init_assets"
437 | ]
438 | },
439 | {
440 | "cell_type": "code",
441 | "execution_count": null,
442 | "metadata": {},
443 | "outputs": [],
444 | "source": [
445 | "backtest.account.daily_hold"
446 | ]
447 | },
448 | {
449 | "cell_type": "code",
450 | "execution_count": null,
451 | "metadata": {},
452 | "outputs": [],
453 | "source": []
454 | },
455 | {
456 | "cell_type": "code",
457 | "execution_count": null,
458 | "metadata": {},
459 | "outputs": [],
460 | "source": [
461 | "risk.plot_assets_curve()"
462 | ]
463 | }
464 | ],
465 | "metadata": {
466 | "kernelspec": {
467 | "display_name": "Python 3",
468 | "language": "python",
469 | "name": "python3"
470 | },
471 | "language_info": {
472 | "codemirror_mode": {
473 | "name": "ipython",
474 | "version": 3
475 | },
476 | "file_extension": ".py",
477 | "mimetype": "text/x-python",
478 | "name": "python",
479 | "nbconvert_exporter": "python",
480 | "pygments_lexer": "ipython3",
481 | "version": "3.6.6"
482 | }
483 | },
484 | "nbformat": 4,
485 | "nbformat_minor": 2
486 | }
487 |
--------------------------------------------------------------------------------
/test_backtest/T0backtest.py:
--------------------------------------------------------------------------------
1 |
2 | # coding: utf-8
3 |
4 | # In[1]:
5 |
6 |
7 | from QUANTAXIS.QAARP.QAStrategy import QA_Strategy
8 | from QUANTAXIS.QAARP.QAAccount import QA_Account
9 | from QUANTAXIS.QAUtil.QAParameter import (AMOUNT_MODEL, MARKET_TYPE,
10 | FREQUENCE, ORDER_DIRECTION,
11 | ORDER_MODEL, RUNNING_ENVIRONMENT)
12 |
13 |
14 | import random
15 |
16 |
17 | # In[2]:
18 |
19 |
20 | class MAMINT0Strategy(QA_Account):
21 | def __init__(self, user_cookie='default', portfolio_cookie='default', init_hold={'000001': 10000}):
22 | super().__init__(user_cookie, portfolio_cookie, init_hold=init_hold)
23 | self.account_cookie = 'T0BACKTEST'
24 | self.running_environment = RUNNING_ENVIRONMENT.TZERO
25 | self.frequence = FREQUENCE.ONE_MIN
26 | self.market_type = MARKET_TYPE.STOCK_CN
27 |
28 | self.result = {}
29 |
30 | def on_bar(self, event):
31 |
32 | # min5= self.market_data.min5
33 | # min15= self.market_data.min15
34 |
35 | # min5macd=QA.QA_indicator_MACD(min5)
36 | # min15macd=QA.QA_indicator_MACD(min15)
37 | # self.result['min5macd']=min5macd
38 |
39 | # self.cash_available # 当前剩余现金
40 | # self.sell_available # 当前可卖股票
41 | # self.history_table # 当前的历史交易
42 | # self.hold_time # 当前的持仓时间
43 | # self.hold_price # 当前持仓的成本价格
44 | # self.get_orders # 获取历史订单
45 | # self.allow_sellopen # 账户是否允许卖空
46 | # self.allow_t0 # 账户是否允许t0
47 | # self.commission_coeff # 账户的手续费(可自行调整)
48 |
49 | try:
50 | for item in event.market_data.code:
51 |
52 | print('================')
53 | print(self.sell_available)
54 | print('================')
55 | print(self.hold_available)
56 | if self.sell_available.get(item, 0) > 0:
57 | event.send_order(account_cookie=self.account_cookie,
58 | amount=self.sell_available[item], amount_model=AMOUNT_MODEL.BY_AMOUNT,
59 | time=self.current_time, code=item, price=0,
60 | order_model=ORDER_MODEL.MARKET, towards=ORDER_DIRECTION.SELL,
61 | market_type=self.market_type, frequence=self.frequence,
62 | broker_name=self.broker
63 | )
64 | else:
65 | event.send_order(account_cookie=self.account_cookie,
66 | amount=100, amount_model=AMOUNT_MODEL.BY_AMOUNT,
67 | time=self.current_time, code=item, price=0,
68 | order_model=ORDER_MODEL.MARKET, towards=ORDER_DIRECTION.BUY,
69 | market_type=self.market_type, frequence=self.frequence,
70 | broker_name=self.broker)
71 | except:
72 | pass
73 |
74 |
75 | # In[3]:
76 |
77 |
78 | from QUANTAXIS.QAARP.QARisk import QA_Risk
79 | from QUANTAXIS.QAARP.QAUser import QA_User
80 | from QUANTAXIS.QAApplication.QABacktest import QA_Backtest
81 | from QUANTAXIS.QAUtil.QALogs import QA_util_log_info
82 | from QUANTAXIS.QAUtil.QAParameter import FREQUENCE, MARKET_TYPE
83 |
84 |
85 | class Backtest(QA_Backtest):
86 | '''
87 | 多线程模式回测示例
88 |
89 | '''
90 |
91 | def __init__(self, market_type, frequence, start, end, code_list, commission_fee):
92 | super().__init__(market_type, frequence, start, end, code_list, commission_fee)
93 | self.account = self.portfolio.add_account( MAMINT0Strategy(user_cookie=self.user.user_cookie, portfolio_cookie= self.portfolio.portfolio_cookie))
94 |
95 | def after_success(self):
96 | QA_util_log_info(self.account.history_table)
97 | risk = QA_Risk(self.account, benchmark_code='000300',
98 | benchmark_type=MARKET_TYPE.INDEX_CN)
99 |
100 | print(risk().T)
101 | self.account.save()
102 | risk.save()
103 | risk.plot_assets_curve()
104 | print(risk.profit_construct)
105 |
106 |
107 | # In[4]:
108 |
109 |
110 | import QUANTAXIS as QA
111 | backtest = Backtest(market_type=MARKET_TYPE.STOCK_CN,
112 | frequence=FREQUENCE.FIFTEEN_MIN,
113 | start='2018-11-01',
114 | end='2018-12-10',
115 | code_list=['000001'],
116 | commission_fee=0.00015)
117 | backtest.start_market()
118 |
119 | backtest.run()
120 | backtest.stop()
121 |
122 |
123 | # In[5]:
124 |
125 |
126 | print(backtest.account.history_table)
127 |
--------------------------------------------------------------------------------
/test_backtest/TEST_MARKET_SETTLE.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 1,
6 | "metadata": {},
7 | "outputs": [
8 | {
9 | "name": "stderr",
10 | "output_type": "stream",
11 | "text": [
12 | "QUANTAXIS>> start QUANTAXIS\n",
13 | "QUANTAXIS>> Welcome to QUANTAXIS, the Version is 1.1.0\n",
14 | "QUANTAXIS>> \n",
15 | " ```````````````````````````````````````````````````````````````````````````````````````````````````````````````````````` \n",
16 | " ``########`````##````````##``````````##`````````####````````##```##########````````#``````##``````###```##`````######`` \n",
17 | " `##``````## ```##````````##`````````####````````##`##```````##```````##```````````###``````##````##`````##```##`````##` \n",
18 | " ##````````##```##````````##````````##`##````````##``##``````##```````##``````````####```````#```##``````##```##``````## \n",
19 | " ##````````##```##````````##```````##```##```````##```##`````##```````##`````````##`##```````##`##```````##````##``````` \n",
20 | " ##````````##```##````````##``````##`````##``````##````##````##```````##````````##``###```````###````````##`````##`````` \n",
21 | " ##````````##```##````````##``````##``````##`````##`````##```##```````##```````##````##```````###````````##``````###```` \n",
22 | " ##````````##```##````````##`````##````````##````##``````##``##```````##``````##``````##`````##`##```````##````````##``` \n",
23 | " ##````````##```##````````##````#############````##```````##`##```````##`````###########`````##``##``````##`````````##`` \n",
24 | " ###```````##```##````````##```##```````````##```##```````##`##```````##````##`````````##```##```##``````##```##`````##` \n",
25 | " `##``````###````##``````###``##`````````````##``##````````####```````##```##``````````##``###````##`````##````##`````## \n",
26 | " ``#########``````########```##``````````````###`##``````````##```````##``##````````````##`##``````##````##`````###``### \n",
27 | " ````````#####`````````````````````````````````````````````````````````````````````````````````````````````````````##`` \n",
28 | " ``````````````````````````````````````````````````````````````````````````````````````````````````````````````````````` \n",
29 | " ``````````````````````````Copyright``yutiansut``2018``````QUANTITATIVE FINANCIAL FRAMEWORK````````````````````````````` \n",
30 | " ``````````````````````````````````````````````````````````````````````````````````````````````````````````````````````` \n",
31 | " ```````````````````````````````````````````````````````````````````````````````````````````````````````````````````````` \n",
32 | " ```````````````````````````````````````````````````````````````````````````````````````````````````````````````````````` \n",
33 | " \n"
34 | ]
35 | }
36 | ],
37 | "source": [
38 | "import QUANTAXIS as QA\n",
39 | "\n",
40 | "import threading\n",
41 | "import pandas as pd\n",
42 | "\n",
43 | "import time"
44 | ]
45 | },
46 | {
47 | "cell_type": "code",
48 | "execution_count": 2,
49 | "metadata": {},
50 | "outputs": [
51 | {
52 | "name": "stdout",
53 | "output_type": "stream",
54 | "text": [
55 | "sub\n",
56 | "subscribe\n",
57 | "[<_MainThread(MainThread, started 21604)>, , , , , , , , , , ]\n"
58 | ]
59 | }
60 | ],
61 | "source": [
62 | "# utf-8\n",
63 | "import QUANTAXIS as QA\n",
64 | "\n",
65 | "market = QA.QA_Market(if_start_orderthreading=True)\n",
66 | "portfolio= QA.QA_Portfolio()\n",
67 | "# 创建两个account\n",
68 | "# 这里是创建一个资产组合,然后在组合里面创建两个account 你可以想象成股票里面的两个策略账户\n",
69 | "# 然后返回的是这个账户的id\n",
70 | "a_1 = portfolio.new_account()\n",
71 | "a_1.reset_assets(100000000)\n",
72 | "a_1.frequence = QA.FREQUENCE.ONE_MIN\n",
73 | "market.start()\n",
74 | "market._sync_orders()\n",
75 | "market.connect(QA.BROKER_TYPE.BACKETEST)\n",
76 | "market.login(QA.BROKER_TYPE.BACKETEST, a_1.account_cookie, a_1)\n",
77 | "\n",
78 | "market.order_handler.monitor\n",
79 | "print(threading.enumerate())"
80 | ]
81 | },
82 | {
83 | "cell_type": "code",
84 | "execution_count": 3,
85 | "metadata": {},
86 | "outputs": [
87 | {
88 | "name": "stderr",
89 | "output_type": "stream",
90 | "text": [
91 | "QUANTAXIS>> MARKET WARING: SOMEING WRONG WITH ORDER \n",
92 | " \n",
93 | "QUANTAXIS>> code 000001 date 2018-08-14 14:58:00 price 0 order_model MARKET amount_model by_amount\n",
94 | "QUANTAXIS>> MARKET WARING: SOMEING WRONG WITH ORDER \n",
95 | " \n",
96 | "QUANTAXIS>> code 000004 date 2018-08-14 14:58:00 price 0 order_model MARKET amount_model by_amount\n"
97 | ]
98 | }
99 | ],
100 | "source": [
101 | "for code in ['000001', '000002', '000004', '600010', '000007','600000']:\n",
102 | " market.insert_order(a_1.account_cookie,code=code,\n",
103 | " price=0,\n",
104 | " amount=1000,\n",
105 | " time='2018-08-14 14:58:00',\n",
106 | " towards=QA.ORDER_DIRECTION.BUY,\n",
107 | " order_model=QA.ORDER_MODEL.MARKET,\n",
108 | " amount_model=QA.AMOUNT_MODEL.BY_AMOUNT,\n",
109 | " market_type=QA.MARKET_TYPE.STOCK_CN,\n",
110 | " frequence=QA.FREQUENCE.ONE_MIN,\n",
111 | " broker_name=QA.BROKER_TYPE.BACKETEST,\n",
112 | " )\n",
113 | "while True:\n",
114 | " if len(market.order_handler.order_queue.untrade)==0:\n",
115 | " break\n"
116 | ]
117 | },
118 | {
119 | "cell_type": "code",
120 | "execution_count": 4,
121 | "metadata": {},
122 | "outputs": [],
123 | "source": [
124 | "market.settle_order()"
125 | ]
126 | },
127 | {
128 | "cell_type": "code",
129 | "execution_count": 5,
130 | "metadata": {},
131 | "outputs": [
132 | {
133 | "name": "stdout",
134 | "output_type": "stream",
135 | "text": [
136 | "['Acc_HgDIe1qk', '2018-08-14 14:58:00', '2018-08-14 14:58:00', '000002', None, 1, 22.33, 22.33, 'trade_success', 1000, 1000, 22335.5825, 0, 'Order_LYjbzuBt', 'Trade_92iCzWUE']\n",
137 | "on_insert_order\n",
138 | "< QA_Order realorder_id Order_LYjbzuBt datetime:2018-08-14 14:58:00 code:000002 amount:1000 price:22.33 towards:1 btype:stock_cn order_id:Order_LYjbzuBt account:Acc_HgDIe1qk status:queued >\n",
139 | "queued\n",
140 | "['Acc_HgDIe1qk', '2018-08-14 14:58:00', '2018-08-14 14:58:00', '600010', None, 1, 1.63, 1.63, 'trade_success', 1000, 1000, 1635.0, 0, 'Order_FLyq7JBN', 'Trade_USTZ08F1']\n",
141 | "on_insert_order\n",
142 | "< QA_Order realorder_id Order_FLyq7JBN datetime:2018-08-14 14:58:00 code:600010 amount:1000 price:1.63 towards:1 btype:stock_cn order_id:Order_FLyq7JBN account:Acc_HgDIe1qk status:queued >\n",
143 | "queued\n",
144 | "['Acc_HgDIe1qk', '2018-08-14 14:58:00', '2018-08-14 14:58:00', '000007', None, 1, 0.0, 13.23, 'trade_price_limit', 1000, 0, 5, 0, 'Order_OIuxT70K', 'Trade_jn5GlHwK']\n",
145 | "on_insert_order\n",
146 | "< QA_Order realorder_id Order_OIuxT70K datetime:2018-08-14 14:58:00 code:000007 amount:1000 price:13.23 towards:1 btype:stock_cn order_id:Order_OIuxT70K account:Acc_HgDIe1qk status:queued >\n",
147 | "queued\n",
148 | "['Acc_HgDIe1qk', '2018-08-14 14:58:00', '2018-08-14 14:58:00', '600000', None, 1, 10.07, 10.065000000000001, 'trade_success', 1000, 1000, 10070.000000000002, 0, 'Order_JkyYMKu3', 'Trade_JNOqDLPG']\n",
149 | "on_insert_order\n",
150 | "< QA_Order realorder_id Order_JkyYMKu3 datetime:2018-08-14 14:58:00 code:600000 amount:1000 price:10.065000000000001 towards:1 btype:stock_cn order_id:Order_JkyYMKu3 account:Acc_HgDIe1qk status:queued >\n",
151 | "queued\n",
152 | "SETTLE ORDERHANDLER\n",
153 | "11468\n",
154 | "receive deal\n",
155 | "11468\n",
156 | "receive deal\n",
157 | "11468\n",
158 | "11468\n",
159 | "receive deal\n",
160 | "True\n",
161 | "[]\n",
162 | "settled\n"
163 | ]
164 | }
165 | ],
166 | "source": [
167 | "market.trade_engine.join()"
168 | ]
169 | },
170 | {
171 | "cell_type": "code",
172 | "execution_count": 7,
173 | "metadata": {},
174 | "outputs": [
175 | {
176 | "data": {
177 | "text/html": [
178 | "\n",
179 | "\n",
192 | "
\n",
193 | " \n",
194 | " \n",
195 | " | \n",
196 | " datetime | \n",
197 | " code | \n",
198 | " price | \n",
199 | " amount | \n",
200 | " cash | \n",
201 | " order_id | \n",
202 | " realorder_id | \n",
203 | " trade_id | \n",
204 | " account_cookie | \n",
205 | " commission | \n",
206 | " tax | \n",
207 | "
\n",
208 | " \n",
209 | " \n",
210 | " \n",
211 | " 0 | \n",
212 | " 2018-08-14 14:58:00 | \n",
213 | " 000002 | \n",
214 | " 22.33 | \n",
215 | " 1000 | \n",
216 | " 9.997763e+07 | \n",
217 | " Order_LYjbzuBt | \n",
218 | " Order_LYjbzuBt | \n",
219 | " Trade_lQ7NMwHu | \n",
220 | " Acc_HgDIe1qk | \n",
221 | " 5.5825 | \n",
222 | " 33.495 | \n",
223 | "
\n",
224 | " \n",
225 | " 1 | \n",
226 | " 2018-08-14 14:58:00 | \n",
227 | " 600010 | \n",
228 | " 1.63 | \n",
229 | " 1000 | \n",
230 | " 9.997600e+07 | \n",
231 | " Order_FLyq7JBN | \n",
232 | " Order_FLyq7JBN | \n",
233 | " Trade_7MW4lamQ | \n",
234 | " Acc_HgDIe1qk | \n",
235 | " 0.4075 | \n",
236 | " 2.445 | \n",
237 | "
\n",
238 | " \n",
239 | " 2 | \n",
240 | " 2018-08-14 14:58:00 | \n",
241 | " 600000 | \n",
242 | " 10.07 | \n",
243 | " 1000 | \n",
244 | " 9.996591e+07 | \n",
245 | " Order_JkyYMKu3 | \n",
246 | " Order_JkyYMKu3 | \n",
247 | " Trade_ZzMWFyil | \n",
248 | " Acc_HgDIe1qk | \n",
249 | " 2.5175 | \n",
250 | " 15.105 | \n",
251 | "
\n",
252 | " \n",
253 | "
\n",
254 | "
"
255 | ],
256 | "text/plain": [
257 | " datetime code price amount cash order_id \\\n",
258 | "0 2018-08-14 14:58:00 000002 22.33 1000 9.997763e+07 Order_LYjbzuBt \n",
259 | "1 2018-08-14 14:58:00 600010 1.63 1000 9.997600e+07 Order_FLyq7JBN \n",
260 | "2 2018-08-14 14:58:00 600000 10.07 1000 9.996591e+07 Order_JkyYMKu3 \n",
261 | "\n",
262 | " realorder_id trade_id account_cookie commission tax \n",
263 | "0 Order_LYjbzuBt Trade_lQ7NMwHu Acc_HgDIe1qk 5.5825 33.495 \n",
264 | "1 Order_FLyq7JBN Trade_7MW4lamQ Acc_HgDIe1qk 0.4075 2.445 \n",
265 | "2 Order_JkyYMKu3 Trade_ZzMWFyil Acc_HgDIe1qk 2.5175 15.105 "
266 | ]
267 | },
268 | "execution_count": 7,
269 | "metadata": {},
270 | "output_type": "execute_result"
271 | }
272 | ],
273 | "source": [
274 | "a_1.history_table"
275 | ]
276 | },
277 | {
278 | "cell_type": "code",
279 | "execution_count": 8,
280 | "metadata": {},
281 | "outputs": [
282 | {
283 | "data": {
284 | "text/plain": [
285 | "True"
286 | ]
287 | },
288 | "execution_count": 8,
289 | "metadata": {},
290 | "output_type": "execute_result"
291 | }
292 | ],
293 | "source": [
294 | "market.order_handler.if_start_orderquery"
295 | ]
296 | },
297 | {
298 | "cell_type": "code",
299 | "execution_count": null,
300 | "metadata": {},
301 | "outputs": [],
302 | "source": []
303 | },
304 | {
305 | "cell_type": "code",
306 | "execution_count": null,
307 | "metadata": {},
308 | "outputs": [],
309 | "source": []
310 | },
311 | {
312 | "cell_type": "code",
313 | "execution_count": null,
314 | "metadata": {},
315 | "outputs": [],
316 | "source": []
317 | },
318 | {
319 | "cell_type": "code",
320 | "execution_count": null,
321 | "metadata": {},
322 | "outputs": [],
323 | "source": []
324 | },
325 | {
326 | "cell_type": "code",
327 | "execution_count": null,
328 | "metadata": {},
329 | "outputs": [],
330 | "source": []
331 | },
332 | {
333 | "cell_type": "code",
334 | "execution_count": null,
335 | "metadata": {},
336 | "outputs": [],
337 | "source": []
338 | },
339 | {
340 | "cell_type": "code",
341 | "execution_count": null,
342 | "metadata": {},
343 | "outputs": [],
344 | "source": []
345 | },
346 | {
347 | "cell_type": "code",
348 | "execution_count": null,
349 | "metadata": {},
350 | "outputs": [],
351 | "source": []
352 | },
353 | {
354 | "cell_type": "code",
355 | "execution_count": null,
356 | "metadata": {},
357 | "outputs": [],
358 | "source": []
359 | },
360 | {
361 | "cell_type": "code",
362 | "execution_count": null,
363 | "metadata": {},
364 | "outputs": [],
365 | "source": []
366 | }
367 | ],
368 | "metadata": {
369 | "kernelspec": {
370 | "display_name": "Python 3",
371 | "language": "python",
372 | "name": "python3"
373 | },
374 | "language_info": {
375 | "codemirror_mode": {
376 | "name": "ipython",
377 | "version": 3
378 | },
379 | "file_extension": ".py",
380 | "mimetype": "text/x-python",
381 | "name": "python",
382 | "nbconvert_exporter": "python",
383 | "pygments_lexer": "ipython3",
384 | "version": "3.6.6"
385 | }
386 | },
387 | "nbformat": 4,
388 | "nbformat_minor": 2
389 | }
390 |
--------------------------------------------------------------------------------
/test_backtest/TEST_MARKET_SETTLE.py:
--------------------------------------------------------------------------------
1 |
2 | # coding: utf-8
3 |
4 | # In[1]:
5 |
6 |
7 | import QUANTAXIS as QA
8 |
9 | import threading
10 | import pandas as pd
11 |
12 | import time
13 |
14 |
15 | # In[2]:
16 |
17 |
18 | # utf-8
19 | import QUANTAXIS as QA
20 |
21 | market = QA.QA_Market(if_start_orderthreading=True)
22 | portfolio = QA.QA_Portfolio()
23 | # 创建两个account
24 | # 这里是创建一个资产组合,然后在组合里面创建两个account 你可以想象成股票里面的两个策略账户
25 | # 然后返回的是这个账户的id
26 | a_1 = portfolio.new_account()
27 | a_1.reset_assets(100000000)
28 | a_1.frequence = QA.FREQUENCE.ONE_MIN
29 | market.start()
30 | market._sync_orders()
31 | market.connect(QA.BROKER_TYPE.BACKETEST)
32 | market.login(QA.BROKER_TYPE.BACKETEST, a_1.account_cookie, a_1)
33 |
34 | market.order_handler.monitor
35 |
36 |
37 | # In[3]:
38 |
39 |
40 | for code in ['000001', '000002', '000004', '600010', '000007', '600000']:
41 | market.insert_order(a_1.account_cookie, code=code,
42 | price=0,
43 | amount=1000,
44 | time='2018-08-14 14:58:00',
45 | towards=QA.ORDER_DIRECTION.BUY,
46 | order_model=QA.ORDER_MODEL.MARKET,
47 | amount_model=QA.AMOUNT_MODEL.BY_AMOUNT,
48 | market_type=QA.MARKET_TYPE.STOCK_CN,
49 | frequence=QA.FREQUENCE.ONE_MIN,
50 | broker_name=QA.BROKER_TYPE.BACKETEST,
51 | )
52 |
53 |
54 | # In[4]:
55 |
56 |
57 | print(market.trade_engine.queue.qsize())
58 |
59 |
60 | # In[5]:
61 |
62 |
63 | print(market.trade_engine.kernels_dict['ORDER'].queue.qsize())
64 |
65 |
66 | # In[6]:
67 |
68 |
69 | print(market.trade_engine.kernels_dict[QA.BROKER_TYPE.BACKETEST].queue.qsize())
70 |
71 |
72 | # In[7]:
73 |
74 |
75 | # ma
76 |
77 |
78 | # In[8]:
79 |
80 |
81 | # In[ ]:
82 |
83 |
84 | # market.trade_engine.kernels_dict['ORDER'].queue.task_done()
85 |
86 | market.settle_order()
87 |
88 |
89 | # In[ ]:
90 |
91 | market.trade_engine.join()
92 | # market.trade_engine.kernels_dict['ORDER'].queue.join()
93 |
94 | print(a_1.history_table)
95 | # In[ ]:
96 |
97 |
98 | # market.trade_engine.join()
99 |
100 |
101 | # In[ ]:
102 |
--------------------------------------------------------------------------------
/test_backtest/backtest_debug.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8
2 | #
3 | # The MIT License (MIT)
4 | #
5 | # Copyright (c) 2016-2018 yutiansut/QUANTAXIS
6 | #
7 | # Permission is hereby granted, free of charge, to any person obtaining a copy
8 | # of this software and associated documentation files (the "Software"), to deal
9 | # in the Software without restriction, including without limitation the rights
10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | # copies of the Software, and to permit persons to whom the Software is
12 | # furnished to do so, subject to the following conditions:
13 | #
14 | # The above copyright notice and this permission notice shall be included in all
15 | # copies or substantial portions of the Software.
16 | #
17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | # SOFTWARE.
24 |
25 |
26 | from QUANTAXIS.QAARP.QARisk import QA_Risk
27 | from QUANTAXIS.QAARP.QAUser import QA_User
28 | from QUANTAXIS.QAApplication.QABacktest import QA_Backtest
29 | from QUANTAXIS.QAUtil.QALogs import QA_util_log_info
30 | from QUANTAXIS.QAUtil.QAParameter import FREQUENCE, MARKET_TYPE
31 | from test_backtest.minstrategy import MAMINStrategy
32 | from test_backtest.strategy import MAStrategy
33 |
34 |
35 | class Backtest(QA_Backtest):
36 | '''
37 | 多线程模式回测示例
38 |
39 | '''
40 |
41 | def __init__(self, market_type, frequence, start, end, code_list, commission_fee):
42 | super().__init__(market_type, frequence, start, end, code_list, commission_fee)
43 | self.user = QA_User()
44 | mastrategy = MAStrategy()
45 | maminstrategy = MAMINStrategy()
46 | # maminstrategy.reset_assets(1000)
47 | # self.portfolio, self.account = self.user.register_account(mastrategy)
48 | self.user = QA_User(user_cookie='user_admin')
49 | self.portfolio = self.user.new_portfolio('folio_admin')
50 | self.portfolio, self.account = self.user.register_account(mastrategy)
51 |
52 | print(self.user)
53 | print(self.portfolio)
54 | print(self.account)
55 | print(self.account.message)
56 |
57 | def after_success(self):
58 | QA_util_log_info(self.account.history_table)
59 | risk = QA_Risk(self.account, benchmark_code='000300',
60 | benchmark_type=MARKET_TYPE.INDEX_CN)
61 |
62 | print(risk().T)
63 | fig=risk.plot_assets_curve()
64 | fig.show()
65 | fig=risk.plot_dailyhold()
66 | fig.show()
67 | fig=risk.plot_signal()
68 | fig.show()
69 | self.account.save()
70 | risk.save()
71 |
72 |
73 | def run_daybacktest():
74 | import QUANTAXIS as QA
75 | backtest = Backtest(market_type=MARKET_TYPE.STOCK_CN,
76 | frequence=FREQUENCE.DAY,
77 | start='2017-01-01',
78 | end='2017-02-10',
79 | code_list=QA.QA_fetch_stock_block_adv().code[0:5],
80 | commission_fee=0.00015)
81 | backtest.start_market()
82 |
83 | backtest.run()
84 | backtest.stop()
85 |
86 |
87 | def run_minbacktest():
88 | import QUANTAXIS as QA
89 | backtest = Backtest(market_type=MARKET_TYPE.STOCK_CN,
90 | frequence=FREQUENCE.FIFTEEN_MIN,
91 | start='2017-11-01',
92 | end='2017-11-10',
93 | code_list=QA.QA_fetch_stock_block_adv().code[0:5],
94 | commission_fee=0.00015)
95 | backtest.start_market()
96 |
97 | backtest.run()
98 | backtest.stop()
99 |
100 |
101 | if __name__ == '__main__':
102 | run_daybacktest()
103 | #run_minbacktest()
104 |
105 |
--------------------------------------------------------------------------------
/test_backtest/example/indicator/macd.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | import QUANTAXIS as QA
3 | import pandas as pd
4 |
5 | def MACD_JCSC(dataframe, SHORT=12, LONG=26, M=9):
6 | """
7 | 1.DIF向上突破DEA,买入信号参考。
8 | 2.DIF向下跌破DEA,卖出信号参考。
9 | """
10 | CLOSE = dataframe.close
11 | DIFF = QA.EMA(CLOSE, SHORT) - QA.EMA(CLOSE, LONG)
12 | DEA = QA.EMA(DIFF, M)
13 | MACD = 2*(DIFF-DEA)
14 |
15 | CROSS_JC = QA.CROSS(DIFF, DEA)
16 | CROSS_SC = QA.CROSS(DEA, DIFF)
17 | ZERO = 0
18 | return pd.DataFrame({'DIFF': DIFF, 'DEA': DEA, 'MACD': MACD, 'CROSS_JC': CROSS_JC, 'CROSS_SC': CROSS_SC, 'ZERO': ZERO})
19 |
--------------------------------------------------------------------------------
/test_backtest/example/simple_backtest_day.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # @Author: zhongjy
3 | # @Date: 2018-08-27 00:21:02
4 | # @Last Modified by: Jingyao.Zhong
5 | # @Last Modified time: 2018-08-27 10:19:26
6 | import math
7 | import QUANTAXIS as QA
8 |
9 | from indicator.macd import MACD_JCSC
10 |
11 | try:
12 | if QA.__version__>'1.1.0':
13 | pass
14 | else:
15 | print('quantaxis version < 1.1.0; please upgrade quantaxis.\npip install quantaxis==1.1.0')
16 | exit()
17 | except Exception as e:
18 | print('quantaxis version < 1.1.0; please upgrade quantaxis.\npip install quantaxis==1.1.0')
19 | exit()
20 |
21 | def simple_backtest(AC:QA.QA_Account, code, start:str, end:str):
22 | '''
23 |
24 | :param AC: QA_Account
25 | :param code: 股票代码
26 | :type list or str
27 | :param start: 回测开始时间
28 | :param end: 回测结束时间
29 | :return:
30 | '''
31 | # 取数并前复权
32 | DATA = QA.QA_fetch_stock_day_adv(code, start, end).to_qfq()
33 | # todo 计算信号
34 | stock_signal = DATA.add_func(MACD_JCSC, 12, 26, 9)
35 |
36 |
37 | for peroid_item in DATA.panel_gen:
38 | # 一天过去了
39 |
40 | for stock_item in peroid_item.security_gen:
41 | # 当天的某个股票
42 |
43 | cur_stock_code = stock_item.code[0]
44 | cur_stock_date = stock_item.date[0]
45 | # 可卖数量
46 | cur_account_sotck_code_sell_available_amount = AC.sell_available.get(cur_stock_code, 0)
47 |
48 | cur_sotck_operation_towards = None
49 | # todo 提取对应的信号
50 | cur_stock_signal = stock_signal.loc[cur_stock_date, cur_stock_code]['DIFF']
51 | # 剔除无效信号
52 | if cur_stock_signal is None or math.isnan(cur_stock_signal):
53 | continue
54 |
55 | if cur_stock_signal > 0 and cur_account_sotck_code_sell_available_amount == 0:
56 | # 买入信号, 持仓为0, 方向: 买入
57 | # 买入方式, QA.ORDER_DIRECTION.BUY, QA.ORDER_DIRECTION.BUY_CLOSE, QA.ORDER_DIRECTION.BUY_OPEN
58 | cur_sotck_operation_towards = QA.ORDER_DIRECTION.BUY
59 |
60 | elif cur_stock_signal > 0 and cur_account_sotck_code_sell_available_amount > 0:
61 | # 买入信号, 持仓不为0, 方向: 持有
62 | cur_sotck_operation_towards = None
63 | pass
64 | elif cur_stock_signal < 0 and cur_account_sotck_code_sell_available_amount == 0:
65 | # 卖出信号, 持仓为0, 忽略
66 | cur_sotck_operation_towards =None
67 | pass
68 | elif cur_stock_signal < 0 and cur_account_sotck_code_sell_available_amount > 0:
69 | # 买入信号, 持仓不为0, 方向: 卖出
70 | cur_sotck_operation_towards = QA.ORDER_DIRECTION.SELL
71 |
72 | if cur_sotck_operation_towards is None:
73 | continue
74 |
75 | order = None
76 | if cur_sotck_operation_towards == QA.ORDER_DIRECTION.BUY:
77 | # 97 % 仓 买入
78 | maxMoney = 0.97 * AC.cash_available
79 | # closePrice = stock_item.close[0]
80 | highPrice = stock_item.high[0]
81 | lowPrice = stock_item.low[0]
82 | avgPrice = (highPrice + lowPrice) / 2
83 |
84 | if round(avgPrice, 2) < avgPrice:
85 | avgPrice = round(avgPrice, 2) + 0.01
86 |
87 | maxBuyAmount = int(maxMoney / (avgPrice * (1 + commission_coeff) * 100)) * 100
88 |
89 | print('cash_available {}'.format(AC.cash_available))
90 | print("可用资金: %s, 预计买入 %s , %s, %s, %s,股" % (maxMoney, cur_stock_code, cur_stock_date, avgPrice, maxBuyAmount))
91 | order = AC.send_order(
92 | code=cur_stock_code, time=cur_stock_date, towards=cur_sotck_operation_towards,
93 | order_model=QA.ORDER_MODEL.MARKET,
94 | amount_model=QA.AMOUNT_MODEL.BY_MONEY,
95 | money=maxMoney,
96 | price=avgPrice,
97 | )
98 | elif cur_sotck_operation_towards == QA.ORDER_DIRECTION.SELL:
99 | # 市价 全仓卖出
100 | order = AC.send_order(
101 | code=cur_stock_code, time=cur_stock_date, towards=cur_sotck_operation_towards,
102 | order_model=QA.ORDER_MODEL.MARKET, amount_model=QA.AMOUNT_MODEL.BY_AMOUNT,
103 | amount=cur_account_sotck_code_sell_available_amount, price=0,
104 |
105 | )
106 |
107 | if order is not None and order:
108 | Broker.receive_order(QA.QA_Event(order=order, market_data=stock_item))
109 | trade_mes = Broker.query_orders(AC.account_cookie, 'filled')
110 | res = trade_mes.loc[order.account_cookie, order.realorder_id]
111 | order.trade(res.trade_id, res.trade_price,
112 | res.trade_amount, res.trade_time)
113 | # 当天结算
114 | AC.settle()
115 |
116 |
117 | if __name__ == '__main__':
118 | # 策略名称
119 | strategy_name = 'MACD_JCSC'
120 | # 用户cookie
121 | user_cookie = 'user1'
122 | # 组合cookie
123 | portfolio_cookie = 'win300'
124 | # 账户cookie
125 | account_cookie = 'bba'
126 | benchmark_code = '000300'
127 | initial_cash = 200000
128 | initial_hold = {}
129 | # 交易佣金
130 | commission_coeff = 0.00025
131 | # 印花税
132 | tax_coeff = 0.0015
133 |
134 | # backtest_code_list = QA.QA_fetch_stock_block_adv().code[0:10]
135 | backtest_code_list = '000001'
136 | backtest_start_date = '2018-01-01'
137 | backtest_end_date = '2018-08-25'
138 |
139 | Broker = QA.QA_BacktestBroker()
140 | AC = QA.QA_Account(
141 | strategy_name=strategy_name,
142 | user_cookie=user_cookie,
143 | portfolio_cookie=portfolio_cookie,
144 | account_cookie=account_cookie,
145 | init_hold=initial_hold,
146 | init_cash=initial_cash,
147 | commission_coeff=commission_coeff,
148 | tax_coeff=tax_coeff,
149 | market_type=QA.MARKET_TYPE.STOCK_CN,
150 | frequence=QA.FREQUENCE.DAY
151 | )
152 | # 设置初始资金
153 | # AC.reset_assets(20000000)
154 |
155 | # 回测
156 | simple_backtest(AC, backtest_code_list, backtest_start_date, backtest_end_date)
157 |
158 | AC.save()
159 |
160 | # 结果
161 | print(AC.message)
162 | print(AC.history_table)
163 |
164 |
165 |
166 | # 分析
167 | risk = QA.QA_Risk(account=AC, benchmark_code=benchmark_code, benchmark_type=QA.MARKET_TYPE.INDEX_CN, if_fq=False)
168 | risk.save()
169 |
170 | print(risk.message)
171 | fig=risk.plot_assets_curve()
172 |
173 | fig.plot()
--------------------------------------------------------------------------------
/test_backtest/make_order.md:
--------------------------------------------------------------------------------
1 | # 下单说明:
2 |
3 | ## 全仓买入测试
4 |
5 | ```python
6 | # 初始化一个account
7 | Account=QA.QA_Account()
8 |
9 | # 全仓买入'000001'
10 |
11 | Order=Account.send_order(code='000001',
12 | price=11,
13 | money=Account.cash_available,
14 | time='2018-05-09',
15 | towards=QA.ORDER_DIRECTION.BUY,
16 | order_model=QA.ORDER_MODEL.MARKET,
17 | amount_model=QA.AMOUNT_MODEL.BY_MONEY
18 | )
19 |
20 |
21 | # 打印剩余资金
22 | Account.cash_available
23 | Out[5]: 950.2999999999302
24 |
25 | ## 打印order的占用资金
26 | (Order.amount*Order.price)*(1+Account.commission_coeff)
27 | Out[6]: 999049.7000000001
28 |
29 | ## order占用的资金和account的资金相加等于总和
30 | 999049.7000000001+950.2999999999302
31 | Out[7]: 1000000.0
32 | ```
--------------------------------------------------------------------------------
/test_backtest/strategy_qsdd.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Name: QSDD strategy
3 |
4 | import QUANTAXIS as QA
5 | import numpy as np
6 | import pandas as pd
7 | import talib
8 | import matplotlib as mpl
9 | import matplotlib.pyplot as plt
10 | import seaborn as sns
11 |
12 | # code_list = ['000001', '000002', '000004', '600000',
13 | # '600536', '000936', '002023', '600332',
14 | # '600398', '300498', '603609', '300673']
15 | code_list = QA.QA_fetch_stock_block_adv().code[0:50]
16 | start_date = '2017-01-01'
17 | end_date = '2018-05-23'
18 |
19 | '''
20 | QSDD
21 | 趋势顶底(QSDD)指标介绍
22 |
23 | '''
24 |
25 | # define the QSDD strategy
26 |
27 |
28 | def QSDD(dataframe, SHORT=12, LONG=26, M=9):
29 | """
30 | 1.line_mid向上突破line_long,买入信号参考。
31 | 2.line_mid向下跌破line_long,卖出信号参考。
32 | """
33 | OPEN = dataframe.open
34 | HIGH = dataframe.high
35 | LOW = dataframe.low
36 | CLOSE = dataframe.close
37 |
38 | # QSDD策略
39 | # A = talib.MA(-100 * (talib.MAX(HIGH, 34) - CLOSE) / (talib.MAX(HIGH, 34) - talib.MIN(LOW, 34)), 19)
40 | # B = -100 * (talib.MAX(HIGH, 14) - CLOSE) / (talib.MAX(HIGH, 14) - talib.MIN(LOW, 14))
41 | # D = talib.EMA(-100 * (talib.MAX(HIGH, 34) - CLOSE) / (talib.MAX(HIGH, 34) - talib.MIN(LOW, 34)), 4)
42 | A = QA.MA(-100 * (QA.HHV(HIGH, 34) - CLOSE) /
43 | (QA.HHV(HIGH, 34) - QA.LLV(LOW, 34)), 19)
44 | B = -100 * (QA.HHV(HIGH, 14) - CLOSE) / \
45 | (QA.HHV(HIGH, 14) - QA.LLV(LOW, 14))
46 | D = QA.EMA(-100 * (QA.HHV(HIGH, 34) - CLOSE) /
47 | (QA.HHV(HIGH, 34) - QA.LLV(LOW, 34)), 4)
48 |
49 | line_long = A + 100
50 | line_short = B + 100
51 | line_mid = D + 100 # 信号线
52 |
53 | CROSS_JC = QA.CROSS(line_mid, line_long)
54 | CROSS_SC = QA.CROSS(line_long, line_mid)
55 | return pd.DataFrame({'line_mid': line_mid, 'line_long': line_long, 'CROSS_JC': CROSS_JC, 'CROSS_SC': CROSS_SC})
56 |
57 |
58 | # create account
59 | Account = QA.QA_Account()
60 | Broker = QA.QA_BacktestBroker()
61 |
62 | Account.reset_assets(1000000)
63 | Account.account_cookie = 'user_admin_qsdd'
64 |
65 | # get data from mongodb
66 | data = QA.QA_fetch_stock_day_adv(code_list, start_date, end_date)
67 | data = data.to_qfq()
68 |
69 | # add indicator
70 | ind = data.add_func(QSDD)
71 | # ind.xs('000001',level=1)['2018-01'].plot()
72 |
73 | # data_forbacktest=data.select_time('2018-01-01','2018-05-20')
74 | data_forbacktest = data
75 |
76 | for items in data_forbacktest.panel_gen:
77 | for item in items.security_gen:
78 | daily_ind = ind.loc[item.index]
79 | if daily_ind.CROSS_JC.iloc[0] > 0:
80 | order = Account.send_order(
81 | code=item.code[0],
82 | time=item.date[0],
83 | amount=1000,
84 | towards=QA.ORDER_DIRECTION.BUY,
85 | price=0,
86 | order_model=QA.ORDER_MODEL.CLOSE,
87 | amount_model=QA.AMOUNT_MODEL.BY_AMOUNT
88 | )
89 | Broker.receive_order(QA.QA_Event(order=order, market_data=item))
90 | trade_mes = Broker.query_orders(Account.account_cookie, 'filled')
91 | res = trade_mes.loc[order.account_cookie, order.realorder_id]
92 | order.trade(res.trade_id, res.trade_price,
93 | res.trade_amount, res.trade_time)
94 | elif daily_ind.CROSS_SC.iloc[0] > 0:
95 | if Account.sell_available.get(item.code[0], 0) > 0:
96 | order = Account.send_order(
97 | code=item.code[0],
98 | time=item.date[0],
99 | amount=Account.sell_available.get(item.code[0], 0),
100 | towards=QA.ORDER_DIRECTION.SELL,
101 | price=0,
102 | order_model=QA.ORDER_MODEL.MARKET,
103 | amount_model=QA.AMOUNT_MODEL.BY_AMOUNT
104 | )
105 | Broker.receive_order(QA.QA_Event(
106 | order=order, market_data=item))
107 | trade_mes = Broker.query_orders(
108 | Account.account_cookie, 'filled')
109 | res = trade_mes.loc[order.account_cookie, order.realorder_id]
110 | order.trade(res.trade_id, res.trade_price,
111 | res.trade_amount, res.trade_time)
112 | Account.settle()
113 |
114 | print(Account.history)
115 | print(Account.history_table)
116 | print(Account.daily_hold)
117 |
118 | # create Risk analysis
119 | Risk = QA.QA_Risk(Account)
120 | print(Risk.message)
121 | print(Risk.assets)
122 |
123 | # Risk.assets.plot()
124 | # Risk.benchmark_assets.plot()
125 | fig = Risk.plot_assets_curve()
126 | fig.plot()
127 | fig = Risk.plot_dailyhold()
128 | fig.plot()
129 | fig = Risk.plot_signal()
130 | fig.plot()
131 |
132 | # plt.style.use('ggplot')
133 | # f, ax = plt.subplots(figsize=(20, 8))
134 | # ax.set_title('SIGNAL TABLE --ACCOUNT: {}'.format(Account.account_cookie))
135 | # ax.set_xlabel('Code')
136 | # ax.set_ylabel('DATETIME', rotation=90)
137 | # import matplotlib.patches as mpatches
138 | # # x2 = Risk.benchmark_assets.x
139 | #
140 | # patch_assert = mpatches.Patch(color='red', label='assert')
141 | # patch_benchmark = mpatches.Patch(label='benchmark')
142 | # plt.legend(handles=[patch_assert, patch_benchmark], loc=0)
143 | # plt.title('Assert and Benchmark')
144 | #
145 | #
146 | # cmap = sns.cubehelix_palette(start=1, rot=3, gamma=0.8, as_cmap=True)
147 | # ht = sns.heatmap(Account.trade.head(55), cmap=cmap, linewidths=0.05, ax=ax)
148 | # # sns.heatmap(Account.trade.head(55), cmap="YlGnBu",linewidths = 0.05, ax = ax)
149 | # # ht.set_xticklabels(rotation=90)
150 | # # ht.set_yticklabels(rotation=90)
151 | # plt.show()
152 |
153 | # # save result
154 | # Account.save()
155 | # Risk.save()
156 | #
157 | # account_info=QA.QA_fetch_account({'account_cookie':'user_admin_macd'})
158 | # account=QA.QA_Account().from_message(account_info[0])
159 | # print(account)
160 |
--------------------------------------------------------------------------------
/test_backtest/test_insert_orderspeed.py:
--------------------------------------------------------------------------------
1 | # utf-8
2 | import QUANTAXIS as QA
3 | import time
4 | market = QA.QA_Market(if_start_orderthreading=True)
5 | user = QA.QA_Portfolio()
6 | # 创建两个account
7 | # 这里是创建一个资产组合,然后在组合里面创建两个account 你可以想象成股票里面的两个策略账户
8 | # 然后返回的是这个账户的id
9 | a_1 = user.new_account()
10 | a_1.reset_assets(100000000)
11 | a_1.frequence = QA.FREQUENCE.ONE_MIN
12 | market.start()
13 |
14 | market.connect(QA.BROKER_TYPE.BACKETEST)
15 |
16 | # 打印market
17 | print(market)
18 |
19 | """
20 | 登陆到这个交易前置上 把你刚才的两个账户
21 | """
22 | # 登陆交易
23 |
24 | market.login(QA.BROKER_TYPE.BACKETEST, a_1.account_cookie, a_1)
25 | market._sync_orders()
26 | for code in ['000001', '000002', '000004', '600010', '000007', '600000']:
27 | market.insert_order(a_1.account_cookie, code=code,
28 | price=0,
29 | amount=1000,
30 | time='2018-08-14 14:58:00',
31 | towards=QA.ORDER_DIRECTION.BUY,
32 | order_model=QA.ORDER_MODEL.MARKET,
33 | amount_model=QA.AMOUNT_MODEL.BY_AMOUNT,
34 | market_type=QA.MARKET_TYPE.STOCK_CN,
35 | frequence=QA.FREQUENCE.ONE_MIN,
36 | broker_name=QA.BROKER_TYPE.BACKETEST,
37 | )
38 | # market.trade_engine.join()
39 | # market._settle(QA.BROKER_TYPE.BACKETEST)
40 | time.sleep(10)
41 | print(a_1.history)
42 | print(a_1.cash)
43 | print(a_1.cash_available)
44 | print(a_1.history_table)
45 | print(a_1.hold)
46 |
47 | # market.trade_engine.stop_all()
48 | # market.trade_engine.stop()
49 |
--------------------------------------------------------------------------------
/test_backtest/关于1.1.0的quantaxis的账户,市场,实盘模拟盘回测.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# 前言 : \n",
8 | "\n",
9 | "1.1.0 是对于QA_Market的一个小规模重构,区别以往的订单,成交模式, 故更新一个小版本\n",
10 | "\n",
11 | "本次的更新主要有:\n",
12 | "\n",
13 | "\n",
14 | "[QAData]\n",
15 | "\n",
16 | "1. 修改了采样函数的写法\n",
17 | "2. 修复了tick采样成60min的bug\n",
18 | "3. 修复了因为multiindex导致的QA_DataStruct.to_json方法缺失 datetime/code 字段的问题\n",
19 | "\n",
20 | "[QAMARKET]\n",
21 | "\n",
22 | "\n",
23 | "1. 增加对于实盘易的支持\n",
24 | "2. 将一些基础解析字段挪至基类QABroker中\n",
25 | "3. 基于QAMarket创建的broker/order线程全部变成后台线程\n",
26 | "4. QA_OrderHandler 增加持久化 订单/成交单部分\n",
27 | "5. 修改QAOrder 变成有限状态机, 通过状态机的动作自动改变Order的状态\n",
28 | "6. 修改QABacktest_Broker 适配新的order类\n",
29 | "7. 优化QABroker的状态显示\n",
30 | "8. 将撮合缓存字典重构进QADealer, dealer加入 deal_message(dict) 和deal_df(dataframe),并增加dealer的settle函数\n",
31 | "9. 大量更新QABacktest_Broker方法,使之适配新版本回测\n",
32 | "10. 适配实盘,增加字段解析 trade_towards_cn_en, order_status_cn_en\n",
33 | "11. 修改order的撮合机制, 使用创建order时的callback回调来更新账户\n",
34 | "\n",
35 | "\n",
36 | "[QAEngine]\n",
37 | "\n",
38 | "1. QAThread 初始化增加 daemon选项, 用于创建守护线程\n",
39 | "\n",
40 | "[QAARP]\n",
41 | "\n",
42 | "1. QA_Account 增加 cancel_order方法 撤单操作\n",
43 | "2. 重写QA_Account的receive_deal方法, 适配新版本更新账户\n",
44 | "3. 优化和修改QA_Portfolio 增加对于history/history_table的支持\n",
45 | "\n",
46 | "\n",
47 | "[QASU]\n",
48 | "\n",
49 | "1. save_orderhandler.py 增加 QA_SU_save_order/ QA_SU_save_deal 方法\n",
50 | "2. 增加对于运行时出错的容错处理\n",
51 | "\n",
52 | "[QAUtil]\n",
53 | "\n",
54 | "1. QADate_Trade 增加QA_util_get_order_datetime() 用于获取委托的真实日期 QA_util_get_trade_datetime() 用于获取成交的真实日期\n",
55 | "2. QA_Parameter 修改订单状态\n",
56 | "\n",
57 | "[QAWEB]\n",
58 | "\n",
59 | "1. QAWEB 增加查询股票名称的接口 http://ip:port/marketdata/stock/code?code=xxxxx"
60 | ]
61 | },
62 | {
63 | "cell_type": "code",
64 | "execution_count": 1,
65 | "metadata": {},
66 | "outputs": [
67 | {
68 | "name": "stderr",
69 | "output_type": "stream",
70 | "text": [
71 | "QUANTAXIS>> start QUANTAXIS\n",
72 | "QUANTAXIS>> Welcome to QUANTAXIS, the Version is 1.1.0\n",
73 | "QUANTAXIS>> \n",
74 | " ```````````````````````````````````````````````````````````````````````````````````````````````````````````````````````` \n",
75 | " ``########`````##````````##``````````##`````````####````````##```##########````````#``````##``````###```##`````######`` \n",
76 | " `##``````## ```##````````##`````````####````````##`##```````##```````##```````````###``````##````##`````##```##`````##` \n",
77 | " ##````````##```##````````##````````##`##````````##``##``````##```````##``````````####```````#```##``````##```##``````## \n",
78 | " ##````````##```##````````##```````##```##```````##```##`````##```````##`````````##`##```````##`##```````##````##``````` \n",
79 | " ##````````##```##````````##``````##`````##``````##````##````##```````##````````##``###```````###````````##`````##`````` \n",
80 | " ##````````##```##````````##``````##``````##`````##`````##```##```````##```````##````##```````###````````##``````###```` \n",
81 | " ##````````##```##````````##`````##````````##````##``````##``##```````##``````##``````##`````##`##```````##````````##``` \n",
82 | " ##````````##```##````````##````#############````##```````##`##```````##`````###########`````##``##``````##`````````##`` \n",
83 | " ###```````##```##````````##```##```````````##```##```````##`##```````##````##`````````##```##```##``````##```##`````##` \n",
84 | " `##``````###````##``````###``##`````````````##``##````````####```````##```##``````````##``###````##`````##````##`````## \n",
85 | " ``#########``````########```##``````````````###`##``````````##```````##``##````````````##`##``````##````##`````###``### \n",
86 | " ````````#####`````````````````````````````````````````````````````````````````````````````````````````````````````##`` \n",
87 | " ``````````````````````````````````````````````````````````````````````````````````````````````````````````````````````` \n",
88 | " ``````````````````````````Copyright``yutiansut``2018``````QUANTITATIVE FINANCIAL FRAMEWORK````````````````````````````` \n",
89 | " ``````````````````````````````````````````````````````````````````````````````````````````````````````````````````````` \n",
90 | " ```````````````````````````````````````````````````````````````````````````````````````````````````````````````````````` \n",
91 | " ```````````````````````````````````````````````````````````````````````````````````````````````````````````````````````` \n",
92 | " \n"
93 | ]
94 | }
95 | ],
96 | "source": [
97 | "import QUANTAXIS as QA\n",
98 | "import pandas as pd\n",
99 | "import threading\n",
100 | "import time\n",
101 | "import datetime\n",
102 | "import numpy as np"
103 | ]
104 | },
105 | {
106 | "cell_type": "code",
107 | "execution_count": 2,
108 | "metadata": {},
109 | "outputs": [],
110 | "source": [
111 | "if QA.__version__<'1.1.0':\n",
112 | " print('请升级quantaxis后再运行此教程')"
113 | ]
114 | },
115 | {
116 | "cell_type": "markdown",
117 | "metadata": {},
118 | "source": [
119 | "# 首先我们介绍QA_MARKET:\n",
120 | "\n",
121 | "1. 如何理解QA_MARKET:\n",
122 | " QA_MARKET 是一个交易前置, 从使用的角度看,你可以把他理解成一个交易终端(比如同花顺/通达信)\n",
123 | " \n",
124 | " 在去年准备对于MARKET类重构的时候,QA_MARKET的作用图如下:\n",
125 | " \n",
126 | " \n",
127 | " \n",
128 | " \n",
129 | " 交易前置主要起的作用是:\n",
130 | " \n",
131 | " 1. 向上接入不同的Broker\n",
132 | " 2. 向下接入不同的账户\n",
133 | " \n",
134 | " broker可以利用不同的接口, 接入不同的市场(股票/期货/港股/美股/模拟盘/回测)\n",
135 | "\n",
136 | "2. QA_MARKET的类构成:\n",
137 | "\n",
138 | " QA_Market继承于 QA_Trade, QA_Trade 是一个交易前置基类, 其中包含了 QA_Engine(用于开启多线程的管理引擎), 以及各种基类方法\n",
139 | "\n",
140 | "3. QA_Market的主要方法:\n",
141 | "\n",
142 | " - start() 启动交易前置\n",
143 | " \n",
144 | " - connect(broker) 连接broker (等同于在同花顺里面选择不同的券商)\n",
145 | " \n",
146 | " - register(broker_name,broker) 注册一个broker(如果不是官方支持的broker)\n",
147 | " \n",
148 | " - login(account_cookie,account) 登陆账户\n",
149 | " \n",
150 | " - login_out(account_cookie,account) 登出\n",
151 | " \n",
152 | " - get_account(account_cookie) 获得账户句柄\n",
153 | " \n",
154 | " - insert_order(account_cookie, amount, amount_model, time, code, price, order_model, towards, market_type, frequence, broker_name, money=None) 插入订单\n",
155 | " \n",
156 | " - cancel_order(broker_name,account_cookie,order_id) 撤单\n",
157 | " \n",
158 | " - cancel_all(broker_name,account_cookie) 某一个账户订单全撤\n",
159 | " \n",
160 | " - query_assets(account_cookie) 查询某个账户的资产\n",
161 | " \n",
162 | " - query_position(account_cookie) 查询某个账户的持仓\n",
163 | " \n",
164 | " - query_cash(account_cookie) 查询某个账户的现金\n",
165 | " \n",
166 | " - query_data(broker_name, frequence, market_type, code, start, end=None) 查询历史行情数据\n",
167 | " \n",
168 | " - query_currentbar(broker_name, market_type, code) 查询当前行情\n",
169 | " \n",
170 | " - get_trading_day() 查询当前交易日期\n",
171 | " \n",
172 | " \n",
173 | "4. QA_Market的非阻塞事件\n",
174 | "\n",
175 | " QA_Market的非阻塞事件由 QA_Engine, Engine 中管理着各个QA_Thread, 通过submit(QA_Task) 和submit_nowait(QA_Task)的方法将事件推送到处理队列中\n",
176 | " \n",
177 | " - upcoming_data(broker, data) 行情推送进交易前置, 分发至market下的所有账户中\n",
178 | " \n",
179 | " - settle(broker) 每日交易结算\n",
180 | " \n",
181 | " - insert_order 插入订单 可以在on_insert_order中写异步处理(需要继承)\n",
182 | " \n",
183 | " 关于submit函数和QA_Task\n",
184 | " \n",
185 | " \n",
186 | " \n",
187 | " 你可以在QA_Task的QA_Event中自行写入回调来异步调用你的函数\n",
188 | " \n",
189 | " \n",
190 | " \n",
191 | " \n",
192 | "\n",
193 | " \n",
194 | " \n",
195 | " \n",
196 | " \n",
197 | " "
198 | ]
199 | }
200 | ],
201 | "metadata": {
202 | "kernelspec": {
203 | "display_name": "Python 3",
204 | "language": "python",
205 | "name": "python3"
206 | },
207 | "language_info": {
208 | "codemirror_mode": {
209 | "name": "ipython",
210 | "version": 3
211 | },
212 | "file_extension": ".py",
213 | "mimetype": "text/x-python",
214 | "name": "python",
215 | "nbconvert_exporter": "python",
216 | "pygments_lexer": "ipython3",
217 | "version": "3.6.6"
218 | }
219 | },
220 | "nbformat": 4,
221 | "nbformat_minor": 2
222 | }
223 |
--------------------------------------------------------------------------------