IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 区块链 -> Python双均线策略回测(2021-10-12) -> 正文阅读

[区块链]Python双均线策略回测(2021-10-12)

Python双均线策略回测
1.择时策略简介
根据百度百科的解释,择时交易是指利用某种方法来判断大势的走势情况,是上涨还是下跌或者是盘整。如果判断是上涨,则买入持有;如果判断是下跌,则卖出清仓,如果是盘整,可以高抛低吸。
从量化角度来说,择时是通过资产的数据构造出买卖信号,按照买卖信号进行交易。回测就是实现这整个过程。
本文以最简单的双均线策略为例进行回测,具体规则如下:
·短均线上穿长均线(金叉),且当前无持仓:买入;
·短均线下穿长均线(死叉),且当前持仓,卖出;
·其他情况,保持之前仓位;
·可以考虑控制回撤,单次亏损超过一定幅度平仓。
2.回测评价
年化收益
回测起点到终点的累积收益年化,算复利或单利都可以,复利假设策略的盈利也会被用于投资,因此复利算出来结果会更好看一些。
夏普比
夏普比 = (策略期望收益率 - 无风险收益率)/策略波动率
夏普比综合衡量了收益和风险,是最广泛应用的指标。
胜率
统计胜率要先统计交易次数,然后计算所以交易中盈利次数占的比例
最大回撤率
回撤是策略从前期最高点到当前时点的亏损,最大回撤是所有回撤中的最大值,反映的是策略的最大可能损失。
单次最大亏损
所有单次交易中的最大亏损
策略阶段性表现
对策略时间段进行分割,统计每个时间段内上述指标的变化情况,本文按年进行分割,统计测年逐年的收益率和相对于基准的超额收益率。
其他
除此外,还有波动率、下行风险、索提诺比率等各种指标,python中有专门的模块可以计算各种指标,这里我们自己算出各种指标,供参考。

此外,还需要测试策略的稳定性,对策略中参数进行扰动,检验策略的敏感性情况,好的策略应该是参数不敏感的。
3.回测说明
回测标的:贵州茅台(600519.SH)
回测区间:2011.01.01-2021.10.08
代码说明:回测代码分成两块,一块是策略函数(Strategy),一块是评价函数(Performance),策略函数通过指数的收盘价构造信号,计算策略净值,统计策略的每笔交易的情况。评价函数根据策略净值和策略每笔交易的情况计算策略的上述各个指标。
数据说明:策略所用数据来源于“Tushare大数据社区”,https://waditu.com/,大家可自行注册学习(强烈推荐)!!!
4.策略代码
导入所需数据库

import tushare as ts
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from pyecharts.charts import *
from pyecharts import options as opts
from pyecharts.globals import ThemeType

#=1.以贵州茅台(600519.SH)为例获取数据=

token='你的token'
pro=ts.pro_api(token)
df_price=pro.daily(ts_code='600519.SH',start_date='20110101',end_date='20211008',fields='ts_code,trade_date,close,open,high,low')
df_price.index=pd.to_datetime(df_price.trade_date)
df_price['year']=df_price.index.year
df_price=df_price.sort_index()
print(df_price.iloc[0:5,:])

在这里插入图片描述
#=2.策略函数=

def Strategy(data_price,window_short=5,window_long=10,loss_ratio=0.20):
    #df_price:价格数据;
    #window_short:短均线周期,默认为5;
    #window_long:长均线周期,默认为10;
    #lossratio:止损率,默认为1%,即开仓后下跌超过1%止损。

    ##2.1绘制K线和均线
    data_price=data_price.copy()
    data_price.index=data_price.index.strftime('%Y%m%d')
    data_price['sma']=data_price.close.rolling(window_short).mean()
    data_price['lma']=data_price.close.rolling(window_long).mean()
    data_price['position']=0#记录仓位
    data_price['flag']=0#记录买卖

    kline=Kline( init_opts=opts.InitOpts(width='1200px',height='600px',theme=ThemeType.DARK) )  
    kline.add_xaxis( data_price.index.tolist() )
    y=list( data_price.loc[:,['open','close','low','high']].round(2).values )#现在里面的单个元素是数组
    y=[i.tolist() for i in y]#里面的单个数组也必须转换成list
    kline.add_yaxis( 'K线',y )
    #kline.extend_axis(yaxis=opts.AxisOpts( axislabel_opts=opts.LabelOpts(formatter="{value}") ))
    kline.set_series_opts(label_opts=opts.LabelOpts(is_show=False))#是否显示数据标签                        
    kline.set_global_opts(
        xaxis_opts=opts.AxisOpts(is_scale=True,axislabel_opts=opts.LabelOpts(rotate=60)),
        yaxis_opts=opts.AxisOpts( axislabel_opts=opts.LabelOpts(formatter="{value}") ),
        datazoom_opts=[opts.DataZoomOpts(type_='inside')],#内部滑动
        title_opts=opts.TitleOpts(title="贵州茅台(600519.SH)K线及均线",pos_left='45%'),#题目位置
        legend_opts=opts.LegendOpts(pos_right="35%",pos_top="5%"),#图例位置
        tooltip_opts=opts.TooltipOpts(trigger="axis", axis_pointer_type="cross")#添加趋势线
    )

    line=Line()
    line.add_xaxis( data_price.index.tolist() )
    line.add_yaxis( 'MA5',data_price.sma.round(2).tolist(),is_smooth=True )
    line.add_yaxis( 'MA10',data_price.lma.round(2).tolist(),is_smooth=True )
    line.set_series_opts(label_opts=opts.LabelOpts(is_show=False))#是否显示数据标签
    line.set_global_opts(
        datazoom_opts=[opts.DataZoomOpts(type_='inside')],#内部滑动
        legend_opts=opts.LegendOpts(pos_right="20%",pos_top="5%"),#图例位置
        tooltip_opts=opts.TooltipOpts(trigger="axis", axis_pointer_type="cross")#添加趋势线
    )

    kline.overlap(line)
    kline.render("16.1 贵州茅台(600519.SH)K线及均线.html")

    ##2.2均线策略的交易记录
    Buy=[]#保存买入记录
    Sell=[]#保存卖出记录
    price_in=1#初始买入价设置为1

    for i in range( max(1,window_long),data_price.shape[0]-1 ): 
        #情形一:当前无仓位且短均线上穿长均线(金叉),则买入股票
        if (data_price['position'][i]==0)and(data_price['sma'][i-1]<data_price['lma'][i-1])and(data_price['sma'][i]>data_price['lma'][i]):
            data_price.ix[i,'flag']=1
            data_price.ix[i+1,'position']=1

            date_in=data_price.index[i]
            price_in=data_price.ix[i,'close']
            Buy.append( [date_in,price_in,'金叉买入'] )

        #情形二:当前持仓且下跌超过止损率,则平仓止损
        elif ( data_price['position'][i]==1 ) & ( 1-data_price['close'][i]/price_in>loss_ratio ):
            data_price.ix[i,'flag']=-1
            data_price.ix[i+1,'position']=0

            date_out=data_price.index[i]
            price_out=data_price.ix[i,'close']
            Sell.append( [date_out,price_out,'止损平仓'] )

        #情形三:当前持仓且短均线下穿长均线(死叉),则卖出股票
        elif ( data_price['position'][i]==1 ) & ( data_price['sma'][i-1]>data_price['lma'][i-1] ) & ( data_price['sma'][i]<data_price['lma'][i] ):
            data_price.ix[i,'flag']=-1
            data_price.ix[i+1,'position']=0

            date_out=data_price.index[i]
            price_out=data_price.ix[i,'close']
            Sell.append( [date_out,price_out,'死叉卖出'] )

        #其他情形:保持之前的仓位不变
        else:
            data_price.ix[i+1,'position']=data_price.ix[i,'position']
        
    p1=pd.DataFrame( Buy,columns=['买入日期','买入价格','备注'] )
    p2=pd.DataFrame( Sell,columns=['卖出日期','卖出价格','备注'] )
    transactions=pd.concat( [p1,p2],axis=1 )#交易记录

    data_price = data_price.iloc[window_long:,:]
    data_price['ret'] = data_price.close.pct_change(1).fillna(0)
    data_price['nav'] = (1 + data_price.ret*data_price.position).cumprod()
    data_price['benchmark'] = data_price.close/data_price.close[0]

    ##2.3返回交易记录和全过程数据
    return transactions,data_price

#=3.评价函数=

def performance( transactions,strategy ):
    ##3.1策略评价指标
    #年化收益率
    N = 250
    rety = strategy.nav[strategy.shape[0] - 1]**(N/strategy.shape[0]) - 1
    
    #夏普比
    Sharp = (strategy.ret*strategy.position).mean()/(strategy.ret*strategy.position).std()*np.sqrt(N)
    
    #胜率
    VictoryRatio = ( (transactions['卖出价格'] - transactions['买入价格'])>0 ).mean()

    #最大回撤率
    DD = 1 - strategy.nav/strategy.nav.cummax()
    MDD = max(DD)

    #单次最大亏损
    maxloss = min(transactions['卖出价格']/transactions['买入价格'] - 1)

    #月均交易次数
    trade_count=strategy.flag.abs().sum()/strategy.shape[0]*20

    print('------------------------------')
    print('夏普比率为:',round(Sharp,2))
    print('年化收益率为:{}%'.format(round(rety*100,2)))
    print('胜率为:{}%'.format(round(VictoryRatio*100,2)))
    print('最大回撤率为:{}%'.format(round(MDD*100,2)))
    print('单次最大亏损为:{}%'.format(round(-maxloss*100,2)))
    print('月均交易次数为:{}(买卖合计)'.format(round(trade_count,2)))
    print('------------------------------')

    result = {'Sharp':Sharp,
              'RetYearly':rety,
              'WinRate':VictoryRatio,
              'MDD':MDD,
              'maxlossOnce':-maxloss,
              'num':round(strategy.flag.abs().sum()/strategy.shape[0],1)}
    
    result = pd.DataFrame.from_dict(result,orient='index').T
    print(result)
    
    ##3.2策略逐年表现
    nav_peryear = strategy.nav.groupby(strategy.year).last()/strategy.nav.groupby(strategy.year).first() - 1
    benchmark_peryear = strategy.benchmark.groupby(strategy.year).last()/strategy.benchmark.groupby(strategy.year).first() - 1
    
    excess_ret = nav_peryear - benchmark_peryear
    result_peryear = pd.concat([nav_peryear,benchmark_peryear,excess_ret],axis = 1)
    result_peryear.columns = ['strategy_ret','bench_ret','excess_ret']
    result_peryear = result_peryear.T
    print('------------------------------')
    print(result_peryear)
    print('------------------------------')
    
    ##3.3策略净值可视化
    line1=Line( init_opts=opts.InitOpts(width='1200px',height='600px',theme=ThemeType.DARK) )
    line1.add_xaxis( strategy.index.tolist() )
    line1.add_yaxis( '策略净值',strategy.nav.round(2).to_list(),yaxis_index=0,is_smooth=True )
    line1.add_yaxis( '基准净值',strategy.benchmark.round(2).to_list(),yaxis_index=0,is_smooth=True )
    line1.extend_axis(yaxis=opts.AxisOpts( min_=0.8,axislabel_opts=opts.LabelOpts(formatter="{value}") ))
    line1.set_series_opts(label_opts=opts.LabelOpts(is_show=True))#是否显示数据标签                        
    line1.set_global_opts(
        xaxis_opts=opts.AxisOpts(is_scale=True,axislabel_opts=opts.LabelOpts(rotate=60)),
        yaxis_opts=opts.AxisOpts( min_=0.75,axislabel_opts=opts.LabelOpts(formatter="{value}") ),
        datazoom_opts=[opts.DataZoomOpts(type_='inside')],#内部滑动
        title_opts=opts.TitleOpts(title="双均线择时策略回测",pos_left='45%'),#题目位置
        legend_opts=opts.LegendOpts(pos_right="35%",pos_top="5%"),#图例位置
        tooltip_opts=opts.TooltipOpts(trigger="axis", axis_pointer_type="cross")#添加趋势线
    )

    line2=Line()
    line2.add_xaxis( strategy.index.tolist() )
    line2.add_yaxis( '净值之比',(strategy.nav/strategy.benchmark).round(2).tolist(),yaxis_index=1,is_smooth=True )
    line2.set_global_opts(
        datazoom_opts=[opts.DataZoomOpts(type_='inside')],#内部滑动
        legend_opts=opts.LegendOpts(pos_right="20%",pos_top="5%"),#图例位置
        tooltip_opts=opts.TooltipOpts(trigger="axis", axis_pointer_type="cross")#添加趋势线
    )

    line1.overlap(line2)
    line1.render("16.2 双均线择时策略回测.html")

    return result,result_peryear

#=4.结果展示=

trans,data=Strategy(df_price,window_short=25,window_long=50,loss_ratio=0.10)
print('交易记录:\n',trans)
print('结果展示:\n',data)

在这里插入图片描述
在这里插入图片描述

performance( trans,data ) 

在这里插入图片描述

  区块链 最新文章
盘点具备盈利潜力的几大加密板块,以及潜在
阅读笔记|让区块空间成为商品,打造Web3云
区块链1.0-比特币的数据结构
Team Finance被黑分析|黑客自建Token“瞒天
区块链≠绿色?波卡或成 Web3“生态环保”标
期货从入门到高深之手动交易系列D1课
以太坊基础---区块验证
进入以太坊合并的五个数字
经典同态加密算法Paillier解读 - 原理、实现
IPFS/Filecoin学习知识科普(四)
上一篇文章      下一篇文章      查看所有文章
加:2021-10-15 11:51:19  更:2021-10-15 11:51:32 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/28 3:13:54-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计