代码拉取完成,页面将自动刷新
<html lang="zh-cn">
<head>
<meta content="text/html; charset=utf-8" http-equiv="content-type" />
<link href="default.css" rel="stylesheet">
<link href="github.css" rel="stylesheet">
</head>
<body>
<title> "收盘线+ATR"达标线策略研究(以深证100指数的周线数据为例) </title>
<h3>"收盘线+ATR"达标线策略研究(以深证100指数的周线数据为例)</h3>
<h1>处理流程</h1>
<ol>
<li>加载数据</li>
<li>历史数据回放</li>
<li>计算技术指标</li>
<li>计算交易信号</li>
<li>模拟交易</li>
</ol>
<h1>质检图和成果图</h1>
<ol>
<li>检查复权价: 原始价 vs 前复权价</li>
<li>K线和SMA均线</li>
<li>收盘价和BH收益率线条图</li>
<li>蜡烛图DMA均线ATR通道</li>
<li>蜡烛图和交易信号</li>
</ol>
<h2>配图</h2>
<p>全景的历史数据较长, 为了便于显示, 我们从后往前每隔200个K线提取一个<br>
切片, 单独成图. 最后也会制作一个全景图.</p>
<ol>
<li>深证100<em>100dpi</em>-200~None_2458994153_k线和交易信号.png</li>
<li>深证100<em>100dpi</em>-400~-200_2458994154_k线和交易信号.png</li>
<li>深证100<em>100dpi</em>-600~-400_2458994154_k线和交易信号.png</li>
<li>深证100<em>100dpi</em>-800~-600_2458994154_k线和交易信号.png</li>
<li>深证100_100dpi_None~None_2458994154_k线和交易信号.png</li>
</ol>
<p><img alt="" src="./深证100_100dpi_-200~None_2458994153_k线和交易信号.png" height="500" width="4000"/></p>
<p><img alt="" src="./深证100_100dpi_-400~-200_2458994154_k线和交易信号.png" height="500" width="4000"/></p>
<p><img alt="" src="./深证100_100dpi_-600~-400_2458994154_k线和交易信号.png" height="500" width="4000"/></p>
<p><img alt="" src="./深证100_100dpi_-800~-600_2458994154_k线和交易信号.png" height="500" width="4000"/></p>
<p><img alt="" src="./深证100_100dpi_None~None_2458994154_k线和交易信号.png" height="500" width="4000"/></p>
<h1>参数优化结果汇总一览表</h1>
<table>
<thead><tr>
<th style="text-align:right">序号</th>
<th style="text-align:right">atr_n</th>
<th style="text-align:right">maxloss_pct</th>
<th style="text-align:right">stoploss_mode</th>
<th style="text-align:right">trx_timing</th>
<th style="text-align:right">cagr</th>
<th style="text-align:right">mdd</th>
<th style="text-align:right">sharpe</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:right">0</td>
<td style="text-align:right">13</td>
<td style="text-align:right">0.05</td>
<td style="text-align:right">1</td>
<td style="text-align:right">closing</td>
<td style="text-align:right">0.173</td>
<td style="text-align:right">0.359</td>
<td style="text-align:right">1.107</td>
</tr>
<tr>
<td style="text-align:right">1</td>
<td style="text-align:right">13</td>
<td style="text-align:right">0.06</td>
<td style="text-align:right">1</td>
<td style="text-align:right">closing</td>
<td style="text-align:right">0.184</td>
<td style="text-align:right">0.395</td>
<td style="text-align:right">1.144</td>
</tr>
<tr>
<td style="text-align:right">2</td>
<td style="text-align:right">13</td>
<td style="text-align:right">0.07</td>
<td style="text-align:right">1</td>
<td style="text-align:right">closing</td>
<td style="text-align:right">0.172</td>
<td style="text-align:right">0.395</td>
<td style="text-align:right">1.053</td>
</tr>
<tr>
<td style="text-align:right">3</td>
<td style="text-align:right">13</td>
<td style="text-align:right">0.08</td>
<td style="text-align:right">1</td>
<td style="text-align:right">closing</td>
<td style="text-align:right">0.171</td>
<td style="text-align:right">0.395</td>
<td style="text-align:right">1.043</td>
</tr>
<tr>
<td style="text-align:right">4</td>
<td style="text-align:right">13</td>
<td style="text-align:right">0.09</td>
<td style="text-align:right">1</td>
<td style="text-align:right">closing</td>
<td style="text-align:right">0.175</td>
<td style="text-align:right">0.395</td>
<td style="text-align:right">1.065</td>
</tr>
<tr>
<td style="text-align:right">5</td>
<td style="text-align:right">13</td>
<td style="text-align:right">0.1</td>
<td style="text-align:right">1</td>
<td style="text-align:right">closing</td>
<td style="text-align:right">0.177</td>
<td style="text-align:right">0.395</td>
<td style="text-align:right">1.073</td>
</tr>
<tr>
<td style="text-align:right">6</td>
<td style="text-align:right">13</td>
<td style="text-align:right">0.11</td>
<td style="text-align:right">1</td>
<td style="text-align:right">closing</td>
<td style="text-align:right">0.181</td>
<td style="text-align:right">0.395</td>
<td style="text-align:right">1.098</td>
</tr>
<tr>
<td style="text-align:right">7</td>
<td style="text-align:right">13</td>
<td style="text-align:right">0.12</td>
<td style="text-align:right">1</td>
<td style="text-align:right">closing</td>
<td style="text-align:right">0.181</td>
<td style="text-align:right">0.395</td>
<td style="text-align:right">1.098</td>
</tr>
<tr>
<td style="text-align:right">8</td>
<td style="text-align:right">13</td>
<td style="text-align:right">0.13</td>
<td style="text-align:right">1</td>
<td style="text-align:right">closing</td>
<td style="text-align:right">0.192</td>
<td style="text-align:right">0.395</td>
<td style="text-align:right">1.136</td>
</tr>
<tr>
<td style="text-align:right">9</td>
<td style="text-align:right">13</td>
<td style="text-align:right">0.14</td>
<td style="text-align:right">1</td>
<td style="text-align:right">closing</td>
<td style="text-align:right">0.187</td>
<td style="text-align:right">0.395</td>
<td style="text-align:right">1.093</td>
</tr>
<tr>
<td style="text-align:right">10</td>
<td style="text-align:right">13</td>
<td style="text-align:right">0.15</td>
<td style="text-align:right">1</td>
<td style="text-align:right">closing</td>
<td style="text-align:right">0.182</td>
<td style="text-align:right">0.41</td>
<td style="text-align:right">1.05</td>
</tr>
<tr>
<td style="text-align:right">11</td>
<td style="text-align:right">13</td>
<td style="text-align:right">0.16</td>
<td style="text-align:right">1</td>
<td style="text-align:right">closing</td>
<td style="text-align:right">0.181</td>
<td style="text-align:right">0.417</td>
<td style="text-align:right">1.044</td>
</tr>
<tr>
<td style="text-align:right">12</td>
<td style="text-align:right">14</td>
<td style="text-align:right">0.05</td>
<td style="text-align:right">1</td>
<td style="text-align:right">closing</td>
<td style="text-align:right">0.16</td>
<td style="text-align:right">0.248</td>
<td style="text-align:right">1.058</td>
</tr>
<tr>
<td style="text-align:right">13</td>
<td style="text-align:right">14</td>
<td style="text-align:right">0.06</td>
<td style="text-align:right">1</td>
<td style="text-align:right">closing</td>
<td style="text-align:right">0.174</td>
<td style="text-align:right">0.248</td>
<td style="text-align:right">1.12</td>
</tr>
<tr>
<td style="text-align:right">14</td>
<td style="text-align:right">14</td>
<td style="text-align:right">0.07</td>
<td style="text-align:right">1</td>
<td style="text-align:right">closing</td>
<td style="text-align:right">0.166</td>
<td style="text-align:right">0.311</td>
<td style="text-align:right">1.047</td>
</tr>
<tr>
<td style="text-align:right">15</td>
<td style="text-align:right">14</td>
<td style="text-align:right">0.08</td>
<td style="text-align:right">1</td>
<td style="text-align:right">closing</td>
<td style="text-align:right">0.167</td>
<td style="text-align:right">0.318</td>
<td style="text-align:right">1.047</td>
</tr>
<tr>
<td style="text-align:right">16</td>
<td style="text-align:right">14</td>
<td style="text-align:right">0.09</td>
<td style="text-align:right">1</td>
<td style="text-align:right">closing</td>
<td style="text-align:right">0.177</td>
<td style="text-align:right">0.261</td>
<td style="text-align:right">1.108</td>
</tr>
<tr>
<td style="text-align:right">17</td>
<td style="text-align:right">14</td>
<td style="text-align:right">0.1</td>
<td style="text-align:right">1</td>
<td style="text-align:right">closing</td>
<td style="text-align:right">0.179</td>
<td style="text-align:right">0.248</td>
<td style="text-align:right">1.117</td>
</tr>
<tr>
<td style="text-align:right">18</td>
<td style="text-align:right">14</td>
<td style="text-align:right">0.11</td>
<td style="text-align:right">1</td>
<td style="text-align:right">closing</td>
<td style="text-align:right">0.184</td>
<td style="text-align:right">0.235</td>
<td style="text-align:right">1.142</td>
</tr>
<tr>
<td style="text-align:right">19</td>
<td style="text-align:right">14</td>
<td style="text-align:right">0.12</td>
<td style="text-align:right">1</td>
<td style="text-align:right">closing</td>
<td style="text-align:right">0.184</td>
<td style="text-align:right">0.235</td>
<td style="text-align:right">1.142</td>
</tr>
<tr>
<td style="text-align:right">20</td>
<td style="text-align:right">14</td>
<td style="text-align:right">0.13</td>
<td style="text-align:right">1</td>
<td style="text-align:right">closing</td>
<td style="text-align:right">0.195</td>
<td style="text-align:right">0.235</td>
<td style="text-align:right">1.18</td>
</tr>
<tr>
<td style="text-align:right">21</td>
<td style="text-align:right">14</td>
<td style="text-align:right">0.14</td>
<td style="text-align:right">1</td>
<td style="text-align:right">closing</td>
<td style="text-align:right">0.189</td>
<td style="text-align:right">0.235</td>
<td style="text-align:right">1.135</td>
</tr>
<tr>
<td style="text-align:right">22</td>
<td style="text-align:right">14</td>
<td style="text-align:right">0.15</td>
<td style="text-align:right">1</td>
<td style="text-align:right">closing</td>
<td style="text-align:right">0.186</td>
<td style="text-align:right">0.235</td>
<td style="text-align:right">1.103</td>
</tr>
<tr>
<td style="text-align:right">23</td>
<td style="text-align:right">14</td>
<td style="text-align:right">0.16</td>
<td style="text-align:right">1</td>
<td style="text-align:right">closing</td>
<td style="text-align:right">0.185</td>
<td style="text-align:right">0.245</td>
<td style="text-align:right">1.096</td>
</tr>
<tr>
<td style="text-align:right">24</td>
<td style="text-align:right">15</td>
<td style="text-align:right">0.05</td>
<td style="text-align:right">1</td>
<td style="text-align:right">closing</td>
<td style="text-align:right">0.152</td>
<td style="text-align:right">0.391</td>
<td style="text-align:right">0.987</td>
</tr>
<tr>
<td style="text-align:right">25</td>
<td style="text-align:right">15</td>
<td style="text-align:right">0.06</td>
<td style="text-align:right">1</td>
<td style="text-align:right">closing</td>
<td style="text-align:right">0.155</td>
<td style="text-align:right">0.426</td>
<td style="text-align:right">0.984</td>
</tr>
<tr>
<td style="text-align:right">26</td>
<td style="text-align:right">15</td>
<td style="text-align:right">0.07</td>
<td style="text-align:right">1</td>
<td style="text-align:right">closing</td>
<td style="text-align:right">0.143</td>
<td style="text-align:right">0.426</td>
<td style="text-align:right">0.895</td>
</tr>
<tr>
<td style="text-align:right">27</td>
<td style="text-align:right">15</td>
<td style="text-align:right">0.08</td>
<td style="text-align:right">1</td>
<td style="text-align:right">closing</td>
<td style="text-align:right">0.142</td>
<td style="text-align:right">0.426</td>
<td style="text-align:right">0.886</td>
</tr>
<tr>
<td style="text-align:right">28</td>
<td style="text-align:right">15</td>
<td style="text-align:right">0.09</td>
<td style="text-align:right">1</td>
<td style="text-align:right">closing</td>
<td style="text-align:right">0.144</td>
<td style="text-align:right">0.445</td>
<td style="text-align:right">0.89</td>
</tr>
<tr>
<td style="text-align:right">29</td>
<td style="text-align:right">15</td>
<td style="text-align:right">0.1</td>
<td style="text-align:right">1</td>
<td style="text-align:right">closing</td>
<td style="text-align:right">0.145</td>
<td style="text-align:right">0.445</td>
<td style="text-align:right">0.899</td>
</tr>
<tr>
<td style="text-align:right">30</td>
<td style="text-align:right">15</td>
<td style="text-align:right">0.11</td>
<td style="text-align:right">1</td>
<td style="text-align:right">closing</td>
<td style="text-align:right">0.15</td>
<td style="text-align:right">0.445</td>
<td style="text-align:right">0.923</td>
</tr>
<tr>
<td style="text-align:right">31</td>
<td style="text-align:right">15</td>
<td style="text-align:right">0.12</td>
<td style="text-align:right">1</td>
<td style="text-align:right">closing</td>
<td style="text-align:right">0.155</td>
<td style="text-align:right">0.407</td>
<td style="text-align:right">0.951</td>
</tr>
<tr>
<td style="text-align:right">32</td>
<td style="text-align:right">15</td>
<td style="text-align:right">0.13</td>
<td style="text-align:right">1</td>
<td style="text-align:right">closing</td>
<td style="text-align:right">0.166</td>
<td style="text-align:right">0.407</td>
<td style="text-align:right">0.991</td>
</tr>
<tr>
<td style="text-align:right">33</td>
<td style="text-align:right">15</td>
<td style="text-align:right">0.14</td>
<td style="text-align:right">1</td>
<td style="text-align:right">closing</td>
<td style="text-align:right">0.161</td>
<td style="text-align:right">0.407</td>
<td style="text-align:right">0.95</td>
</tr>
<tr>
<td style="text-align:right">34</td>
<td style="text-align:right">15</td>
<td style="text-align:right">0.15</td>
<td style="text-align:right">1</td>
<td style="text-align:right">closing</td>
<td style="text-align:right">0.161</td>
<td style="text-align:right">0.401</td>
<td style="text-align:right">0.929</td>
</tr>
<tr>
<td style="text-align:right">35</td>
<td style="text-align:right">15</td>
<td style="text-align:right">0.16</td>
<td style="text-align:right">1</td>
<td style="text-align:right">closing</td>
<td style="text-align:right">0.16</td>
<td style="text-align:right">0.408</td>
<td style="text-align:right">0.923</td>
</tr>
</tbody>
</table>
<h1>备注</h1>
<ol>
<li>md里强制换行时, 需要在行尾写上2个空格. </li>
<li>md里写尖括号时, 需要用转义符. 因为不转义的话, 会被解析为html的标签.</li>
<li>md里写代码段: 用一对左单引号围起来. </li>
<li>在Markdown中要生成一个代码块,只需要在代码块内容的每一行缩进至少四个空格或者一个TAB。<br>
Markdown不会解析代码块中的Markdown标记。如代码块中的星号就是星号,<br>
失去了它原来的Markdown含义.</li>
</ol>
<p>直接markdown.markdown(text)生成的html文本,非常粗略,只是单纯的html内容。<br>
而且在浏览器内查看的时候中文有乱码(在chrome中).<br>
因为没有设置css样式文件, 外观也太丑了。</p>
<p>解决办法也很简单,在保存文件的时候,将<br>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 和<br>
<code><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></code> 和<br>
css样式添加上。就这么简单解决了。</p>
<pre><code>#markdown 文本里, 缩进后, 表示其内容不再具有markdown功能了. 就是普通文本了
#可以随便写注释, 或者是python源码.
#
<img width="200px" height="500px" />

# 用html语言的img标签来显示并控制显示图片的大小
#<img src="http://pp.myapp.com/ma_pic2/0/shot_42391053_1_1488499316/550" height="55" width="33" >
# 下面是python源码的另一种方案: ```python ... ```
```python
def slicing_forward(ohlc, length=200):
# =============================================================================
# 从后往前提取切片的左右位置, 为切片操作做准备
# 参数:
# ohlc: df对象,
# length: 切片的大小
# 返回:
# list of each slice at (left, right)
# Examples:
# >>> subsets = slicing_forward(c, 200)
# for sub in subsets:
# tmp=c[slice(*sub)]
# print(tmp.index[0], tmp.index[-1])
# =============================================================================
out=[]
for i in range(len(ohlc)//length+1):
start,end=[-length*(i+1), -length*i, ]
if end==0: end=None
out.append((start,end))
#print(out)
return out
```
</code></pre>
</body>
</html>
<h1>python源代码</h1>
<div><pre>
<code><p>> 0 # -*- coding: utf-8 -*-
> 1 """strat_sz100iw.py
> 2 一种趋势策略的尝试, 针对深证100指数周线数据
> 3 """
> 4 import itertools
> 5 import os, pathlib, datetime; type(os); type(pathlib);type(datetime)
> 6 import pandas as pd; type(pd)
> 7 import numpy as np; type(np)
> 8 import matplotlib.pyplot as plt
> 9
> 10 from copy import deepcopy;type(deepcopy)
> 11 from collections import OrderedDict ; type(OrderedDict)
> 12
> 13 import toolkit.myDataIO as mdio
> 14 import util.ttr as ttr
> 15
> 16 import strat_sz100iw_report as wr; type(wr)
> 17
> 18 import imp; type(imp)
> 19 #imp.reload(mdio)
> 20 #imp.reload(ttr)
> 21
> 22 global g
> 23 g=ttr.GlobalEnv()
> 24 g.params=OrderedDict(
> 25 atr_n=14, delta=0.5, sig_filter_n=3,
> 26 start_year=None,
> 27 code='399330',
> 28 maxloss_pct=0.12,
> 29 with_plot=False,
> 30 )
> 31 g.title_info=OrderedDict()
> 32 #g.title_info=dict(asset_name='深证100 (399330)')
> 33 #%%
> 34
> 35 #def simulation_LineMode(atr_n, delta, sig_filter_n, start_year=None, code='399330'):
> 36 def simulation_LineMode(**kwargs):
> 37 '''
> 38 Python里的可变参数(*和**字头的参数):
> 39 在函数应用中(被定义或者被调用),
> 40 有时候我们不确定调用的时候会传递多少个参数(不传参也可以)。
> 41 此时,可用包裹(packing)位置参数/包裹型位置参数,或者包裹型关键字参数,
> 42 来进行参数传递, 会显得非常方便灵活。
> 43
> 44 关键字参数(双星号字头的参数)允许你传入0个或任意个含参数名的参数,
> 45 这些关键字参数在函数内部会自动组装为一个dict.
> 46
> 47 >>> df_line=simulation_LineMode(**g.params)
> 48
> 49 atr14_pct=ttr.atr(df_line,14)/df_line.close *100
> 50 atr14_pct.quantile() # 4.85%
> 51 atr14_pct.describe()
> 52
> 53 count 716.000000
> 54 mean 5.476807
> 55 std 2.481463
> 56 min 2.134225
> 57 25% 3.923625
> 58 50% 4.851406
> 59 75% 6.285523
> 60 max 15.688897
> 61
> 62 所以: stoploss的选择: 应该 > mean (or 1/2 quantile)
> 63
> 64 '''
> 65 global g
> 66 # 解包裹, 获取本函数所需的每个参数
> 67 atr_n =kwargs['atr_n']
> 68 delta =kwargs['delta']
> 69 sig_filter_n=kwargs['sig_filter_n']
> 70 start_year =kwargs['start_year']
> 71 code =kwargs['code']
> 72 with_plot =kwargs['with_plot']
> 73
> 74 fname = 'd:/new_haitong/T0002/export/{}.txt'.format(code)
> 75
> 76 with open(fname, encoding='gbk') as f:
> 77 first_line_data=f.readline()
> 78 asset_name=first_line_data.strip()
> 79 title_='标的资产的代码和名称是: {}'.format(asset_name)
> 80 print(title_)
> 81 print('+'*(len(title_) + ttr.cchar(title_)))
> 82 # 立即更新模块级的全局变量: 把数据文件路径, 标的名称存储到字典里
> 83 g.title_info.update(
> 84 fname=fname,
> 85 asset_name=asset_name,
> 86 )
> 87
> 88 ohlc_ = mdio.read_tdxExport_txtFile(fname)
> 89 ohlc=ohlc_[0]
> 90 ohlc=ohlc.iloc[:, 0:5]
> 91
> 92 if start_year:
> 93 ohlc = ohlc[start_year:]
> 94 out, perf_dict = ttr.strat_sz100iw_lm(ohlc, atr_n, delta, sig_filter_n, start_year)
> 95
> 96 if with_plot:
> 97 fig, ax=plt.subplots(1,1)
> 98 ohlc.close.plot(ax=ax)
> 99 out.bprice.plot(ax=ax)
> 100 out.sprice.plot(ax=ax)
> 101 out.equity.plot()
> 102
> 103 print('\nEnd equity : {:12.2f}\n'.format(out.equity[-1] ,))
> 104 [print('{0:{2:}s} : {1:}'.format(k, v, (18-ttr.cchar(k)))) for k, v in perf_dict.items()]
> 105 print()
> 106 return out
> 107
> 108 #%%
> 109
> 110 def simu_with_stoploss(
> 111 atr_n=14, delta=0.5, sig_filter_n=3,
> 112 start_year=None,
> 113 code='399330',
> 114
> 115 signal_type=1, # exRemoved, 0=original
> 116 trx_timing='closing',
> 117 maxloss_pct=0.11,
> 118 stoploss_mode=1, # (0, 1)分别表示当日尾盘止损, 次日尾盘止损
> 119
> 120 with_plot=False,
> 121 savefig=False,
> 122 subset=None,
> 123 ):
> 124 '''
> 125 >>> reset -f
> 126 >>> # F5
> 127 >>> pos,cagr,mdd,sharpe = (
> 128 simu_with_stoploss(
> 129 signal_type=1,
> 130 trx_timing='closing',
> 131 maxloss_pct=0.13, ##### 不错的止损值
> 132 stoploss_mode=1,
> 133
> 134 with_plot=True,
> 135 savefig=True,
> 136 subset=None, #(-200,None) # 最后200个棒棒的数据切片
> 137 ))
> 138
> 139
> 140
> 141 >>> pos,cagr,mdd,sharpe = simu_with_stoploss(maxloss_pct=0.13, signal_type=1, stoploss_mode=1, with_plot=False, trx_timing='closing') #### 不错的止损值
> 142 >>> pos,cagr,mdd,sharpe = simu_with_stoploss(maxloss_pct=0.13, signal_type=0, stoploss_mode=1, with_plot=False, trx_timing='closing') #### 不错的止损值
> 143
> 144 >>> pos,cagr,mdd,sharpe = simu_with_stoploss(maxloss_pct=0.13, stoploss_mode=1, with_plot=False, trx_timing='opening') #
> 145
> 146 >>> pos,cagr,mdd,sharpe = simu_with_stoploss(maxloss_pct=0.13, stoploss_mode=0, with_plot=False, trx_timing='closing') #
> 147 >>> pos,cagr,mdd,sharpe = simu_with_stoploss(maxloss_pct=0.13, stoploss_mode=0, with_plot=False, trx_timing='opening') #
> 148
> 149 >>> pos,cagr,mdd,sharpe = simu_with_stoploss(maxloss_pct=0.11, stoploss_mode=0, with_plot=True) #### 不错的止损值
> 150 >>> pos,cagr,mdd,sharpe=simu_with_stoploss(maxloss_pct=0.12, trx_timing='opening') #### 不错的止损值
> 151
> 152
> 153 fig=plt.gcf()
> 154 fig.get_size_inches() #array([6.4 , 4.81])
> 155
> 156
> 157 参数: OrderedDict(
> 158 [('atr_n', 14), ('delta', 0.5), ('sig_filter_n', 3), ('start_year', None), ('code', '399330'),
> 159 ('maxloss_pct', 0.12), ('trx_timing', 'closing'), ('with_plot', False)])
> 160
> 161 下单指令集合: {'满仓寻出', '止损', '开仓', '空仓寻进', '清仓'}
> 162
> 163 dk 的次数: 49
> 164 dp 的次数: 45
> 165 gr 的次数: 4
> 166 hold_equity 的次数: 264
> 167 hold_cash 的次数: 326
> 168
> 169 end_equity : 11541.354 if trx_timing=='opening'
> 170 end_nav : 12.003 7.996
> 171 cagr : 0.19 0.156
> 172 mdd : 0.235 0.274
> 173 sharpe : 1.151
> 174 annu_volatility : 0.165
> 175 净值的标准差 : 0.023
> 176 '''
> 177 global g # 全局变量是是模块级别的, 不能在不同的模块之间共享
> 178 #打包所需的关键字参数为: g.params, 方便调用函数时使用.
> 179 g.params.update( #=OrderedDict(
> 180 atr_n=atr_n, delta=delta, sig_filter_n=sig_filter_n,
> 181 start_year=start_year,
> 182 code=code,
> 183
> 184 signal_type=signal_type,
> 185 trx_timing=trx_timing,
> 186 maxloss_pct=maxloss_pct,
> 187 stoploss_mode=stoploss_mode,
> 188
> 189 with_plot=with_plot,
> 190 )
> 191
> 192 df = simulation_LineMode(**g.params)
> 193 # print(df.columns)
> 194 # Index(['open', 'high', 'low', 'close', 'trend',
> 195 # 'b_sig', 's_sig', 'bprice', 'sprice', 'buybars', 'sellbars',
> 196 # 'pos', 'equity', 'b22_sig', 's22_sig'],
> 197
> 198 pos = ttr.simulation_BarMode(df, **g.params)
> 199 pos = pos.set_index('dt', drop=False)
> 200
> 201 print('\n参数: {}'.format(g.params))
> 202 ttr.print_orders_count(pos)
> 203
> 204 pos_=pos.reindex(df.index)
> 205 pos_.position.fillna(0.0, inplace=True)
> 206 #print(set(pos_.position))
> 207 roc1=df.close.pct_change().fillna(0)
> 208 #交割时机的把握逻辑:
> 209 #收盘时刻观察信号, 按收盘价成交:
> 210 if trx_timing=='closing':
> 211 eq = (1+roc1*pos_.position).cumprod() * df.close[0]
> 212 elif trx_timing=='opening':
> 213 # 校正持仓第一日的roc1: 应该为: 该日收盘价 to 该日开盘价
> 214 #roc1_B = ttr.IF((df.b_sig.shift(1)>0, (df.open/df.close.shift(1)-1), roc1))
> 215 roc1_B = ttr.IF((df.b_sig.shift(1)>0, (df.close/df.open-1), roc1))
> 216 # 校正持仓最后日的roc1: 应该为: 次日开盘价 to 昨日收盘价
> 217 # 下述方法仅保证了正常卖出时的收益率的正确性, 止损时的情形需要完善.
> 218 #roc1_C = ttr.IF((df.s_sig>0, (df.open.shift(-1)/df.close.shift(1)-1), roc1_B))
> 219 exit_case = ttr.downCross(pos_.position, 0.5).shift(-1)
> 220 roc1_C = ttr.IF( (exit_case>0,
> 221 (df.open.shift(-1)/df.close.shift(1)-1),
> 222 roc1_B))
> 223 eq = (1+roc1_C * pos_.position).cumprod() * df.close[0]
> 224 pos_['open']=df.open
> 225 pos_['close']=df.close
> 226 pos_['equity']=eq
> 227
> 228
> 229 perf_dict=ttr.perf(pos_)
> 230 print()
> 231 #[print('{:15s} : {}'.format(k, v)) for k, v in perf_dict.items()]
> 232 for k, v in perf_dict.items():
> 233 pwidth = 18 - ttr.cchar(k)
> 234 print('{1:{0:}s} : {2:}'.format(pwidth, k, v))
> 235 print()
> 236
> 237 if with_plot:
> 238 fig, ax=plt.subplots(1,1)
> 239 pos_.close.plot(ax=ax)
> 240 #out.bprice.plot(ax=ax)
> 241 #out.sprice.plot(ax=ax)
> 242 pos_.equity.plot()
> 243
> 244 kwargs=dict(name_string=g.title_info['asset_name'])
> 245 if subset==None:
> 246 for subset in ttr.slicing_forward(df, length=200):
> 247 ttr.plot_signal(df, pos_,
> 248 subset=subset,
> 249 savefig=savefig, plot_action=True, **kwargs)
> 250 subset=(None,None)
> 251 ttr.plot_signal(df, pos_,
> 252 subset=subset,
> 253 savefig=savefig, plot_action=True, **kwargs)
> 254 else:
> 255 ttr.plot_signal(df, pos_,
> 256 subset=subset,
> 257 savefig=savefig, plot_action=True, **kwargs)
> 258
> 259
> 260 return pos_, perf_dict['cagr'], perf_dict['mdd'], perf_dict['sharpe']
> 261
> 262
> 263 #%%
> 264 def opt(trx_timing='closing', stoploss_mode=1, signal_type=1,):
> 265 '''参数寻优
> 266 最佳参数大概为:
> 267 14 atr_n,
> 268 13% maxloss_pct,
> 269 'closing' trx_timing
> 270 1 stoploss_mode (次日止损)
> 271 绩效指标:
> 272 CAGR MDD SHARPE
> 273 19.5% 23.5% 1.180
> 274
> 275
> 276 >>> opt_df, opt_summary=(
> 277 opt(trx_timing='closing', stoploss_mode=1, ))
> 278
> 279
> 280
> 281 >>> opt_df=opt(trx_timing='closing', stoploss_mode=1, signal_type=0) #用了原始信号后, 结果较差
> 282 >>> opt_df=opt(trx_timing='opening', stoploss_mode=1)
> 283
> 284 >>> opt_df=opt(trx_timing='closing', stoploss_mode=0, )
> 285 >>> opt_df=opt(trx_timing='opening', stoploss_mode=0, signal_type=0) #更差
> 286
> 287 stoploss_mode trx_timing atr_n maxloss_pct cagr mdd sharpe
> 288 0 1 closing 13 0.05 0.173 0.359 1.107
> 289 1 1 closing 13 0.08 0.171 0.395 1.043
> 290 2 1 closing 13 0.11 0.181 0.395 1.098
> 291 3 1 closing 13 0.14 0.187 0.395 1.093
> 292 4 1 closing 14 0.05 0.160 0.248 1.058
> 293 5 1 closing 14 0.08 0.167 0.318 1.047
> 294 6 1 closing 14 0.11 0.184 0.235 1.142
> 295 7 1 closing 14 0.14 0.189 0.235 1.135
> 296
> 297 8 1 closing 15 0.05 0.152 0.391 0.987
> 298 9 1 closing 15 0.08 0.142 0.426 0.886
> 299 10 1 closing 15 0.11 0.150 0.445 0.923
> 300 11 1 closing 15 0.14 0.161 0.407 0.950
> 301
> 302
> 303 if 次日开盘成交: 那么结果如下:
> 304 成交时机选择当日尾盘略微好一点点(cagr能有3%的提升)
> 305 但是没有明显的优势
> 306 sn stoploss_mode trx_timing atr_n maxloss_pct cagr mdd sharpe
> 307 0 1 opening 13 0.05 0.161 0.376 1.037
> 308 1 1 opening 13 0.08 0.165 0.376 1.010
> 309 2 1 opening 13 0.11 0.185 0.376 1.114
> 310 3 1 opening 13 0.14 0.176 0.392 1.022
> 311 4 1 opening 14 0.05 0.153 0.245 1.019
> 312 5 1 opening 14 0.08 0.160 0.310 1.013
> 313 6 1 opening 14 0.11 0.187 0.222 1.159
> 314 7 1 opening 14 0.14 0.180 0.222 1.076
> 315 8 1 opening 15 0.05 0.139 0.378 0.908
> 316 9 1 opening 15 0.08 0.134 0.378 0.842
> 317 10 1 opening 15 0.11 0.154 0.378 0.942
> 318 11 1 opening 15 0.14 0.151 0.383 0.879
> 319
> 320 '''
> 321 global g
> 322
> 323 #把参数字典, 通过笛卡尔乘积, 转换为参数数据框
> 324 par_dict = OrderedDict(
> 325 atr_n=range(13,16),
> 326 #maxloss_pct=np.arange(5,17,1)/100,
> 327 maxloss_pct=np.arange(5,17,1)/100,
> 328 )
> 329 prod = itertools.product(*tuple(par_dict.values())) # 传递包裹型位置参数
> 330 par_df = pd.DataFrame(list(prod), columns=par_dict.keys())
> 331
> 332 out=pd.DataFrame()
> 333 opt_summary=pd.DataFrame()
> 334 for (i, atr_n, maxloss_pct ) in par_df.itertuples():
> 335 pos, cagr, mdd, sharpe = simu_with_stoploss(
> 336 atr_n=atr_n,
> 337 maxloss_pct=maxloss_pct,
> 338 signal_type=signal_type,
> 339 trx_timing=trx_timing,
> 340 stoploss_mode=stoploss_mode)
> 341
> 342 out['equity{}'.format(i)]=pos.equity
> 343 opt_summary = opt_summary.append(
> 344 pd.DataFrame(
> 345 OrderedDict(
> 346 atr_n=atr_n,
> 347 maxloss_pct=maxloss_pct,
> 348 stoploss_mode=g.params['stoploss_mode'],
> 349 trx_timing=g.params['trx_timing'],
> 350 cagr=cagr, mdd=mdd, sharpe=sharpe
> 351 ),
> 352 index=[1],
> 353 ),
> 354 ignore_index=True,
> 355 )
> 356 out['close']=pos.close
> 357 print(opt_summary)
> 358
> 359 # out.plot()
> 360 return out, opt_summary
> 361
> 362
> 363 #%%
> 364
> 365
> 366 #%%
> 367 #wr.write_report_md()
> 368 #%%
> 369
> 370 if __name__=="__main__":
> 371 #atr_n=int(input('Please enter parameter: atr_n: '))
> 372 #for atr_n in range(12, 18):
> 373 pass
> 374
> 375 #用matplotlib制作的比较满意的蜡烛图 - duanqs - 博客园
> 376 #https://www.cnblogs.com/duan-qs/p/8074818.html</p>
</code>
</pre></div>
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。