我们经常会在交易中使用一些技术指标,但很多时候只是知道这个指标的核心思路,并不太确定它们的实际效果。可能它们的效果和我们的想法有偏差。可能它们的效果是因股票而异的。也可能我们连一个具体的思路都不清楚,只是天马行空地想到,“咦?这个也许能行?”
我们把这些指标写到策略里,有时候回测看着像这么回事,可有时候又不像那么回事,懵懵懂懂的我们也不知道是怎么回事了。
“那…如果,”你说,“嗯,不对,让我再想想…”
时过半晌,“如果,”你又打断了沉默,“有一个系统性的统计方法,能让我们直观地看到这个指标的效果,那就好了。”
诶哟你说得太对了,我就是来找你谈这个的。
统计的对象
现代金融理论认为,证券价格的时间序列在大部分时间服从随机游走,但是在一些特定的时刻(比如基本面发生变化,或者供需关系发生变化),价格序列会偏离随机游走,并且选择向上或者向下的方向。当价格在脱离随机游走时,通常都会产生一些现象或征兆,就是我们常说的“信号”,如果我们捕捉到这些信号,就可以赚取收益。
我们使用利用股票的历史数据计算各种各样的指标(比如MACD,RSI),就是为了通过指标的数值来判断是否出现信号。但很多时候指标的使用是粗糙并且模糊的,比如“当RSI低于20时买入”是一个发出信号的标准,但为什么是20呢?18或者22会不会效果更好?我们想通过历史统计来分析这个问题,那么进行统计的对象就有两个:指标出现的数值,以及出现该数值之后的涨跌结果。
指标
一般而言,一支股票的指标是一个函数Ind(T),它输入的是时间T(确切地说还有时间T之前的所有股票数据),返回的是在那个时间点的指标数值。比如说,我们要考量的指标是过去5天的收益率,那么指标的输出就是今日收盘价除以五天前收盘价的商再减1。
结果
结果指的就是,我们认为指标所预测的事件到底有没有发生,由此把结果分为“赢”、“平”和“输”。举例来说,假设我们认为过去5天的收益率越高,未来两天的收益率就越大;那我们要观测的结果就是未来两天交易量的情况,如果未来两天的平均交易量大于今天的110%,就记作“赢”,小于今天的100%就记作“输”,其余情况记作“平”。这里“赢平输”的计算标准有一定拍脑袋的成分,这么做的缺点就是统计的数据不全面,优点是结果更直观更方便应用,并且如果统计结果不理想,我们可以更改输赢的决定方法再重新来过。
from jqdata import *
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import talib
def select_strategy():
global cs_enabled,cs_memo,cs_class_name,cs_param
cs_enabled,cs_memo,cs_class_name,cs_param = range(4)
'''=====获取需要的数据和时间周期====='''
global get_data_config
get_data_config=[
[True,'获得数据',Get_data,
{
"security":'002230.XSHE'
,"start_date":"2006-02-02"
,"end_date":"2016-02-02"
,"fields":["close"]
}
]
]
'''=====统计不同指标阈值下的胜负结果====='''
global statistical_index_result_config
statistical_index_result_config=[
[False,'前N天收益率为正时,后5天的收益率超过10%',Get_stats,
{
}
],
[True,'双均线',Double_ma,
{
"ma_start":0,"ma_end":50,"ma_interval":5,"Nday":10,"win_return":0.1,"lose_return":-0.1}
]
]
'''=====按照胜负平的情况画出普通柱形图和胜负差柱形图====='''
global plt_config
plt_config=[
[True,'结果图',Result_plt,
{
}
],
[True,'胜负图',Win_lose_plt,
{
}
]
]
'''=====按照设置的跨度区间选择指标的最好的范围====='''
global get_region_config
get_region_config=[
[True,'获得最好的数值区间',Find_best_region,
{
}
]
]
'''======================================获取数据的类=================================='''
class Get_data:
def __init__(self,params):
self.security=params.get("security","000001.XSHG")
self.start_date=params.get("start_date","2006-02-02")
self.end_date=params.get("end_date","2016-02-02")
self.fields=params.get("fields",["close"])
def todo(self):
return get_price(self.security, start_date=self.start_date, end_date=self.end_date, frequency='daily', fields=self.fields, skip_paused=False, fq='pre')
'''========================================判断胜负的类================================'''
'''---------------------------判断胜负的基类------------------------------------'''
class Win_lose_class:
def __init__(self,params):
self.result_df=pd.DataFrame(columns=('win','even','lose',"value"))
def todo(self,df):
pass
def set_result_df(self,key,result):
if key in self.result_df.index:
if result=="win":
self