@Channelchan
2017-11-27T14:06:29.000000Z
字数 7901
阅读 12065
Step_1: 设计编写选股器算法的类,逐行计算合成DataFrame,返回MultiIndex
Step_2: 股票池与数据读取
Step_3: 初始化选股器的类,并获取选股信号
Step_4: 评估选股信号效果
Step_5: 优化选股算法的参数
Step_6: 测算不同参数组下选股信号的绩效
Step_7: 最优绩效结果可视化与保存Excel
import pandas as pd
from talib.abstract import MA
from fxdayu_alphaman.selector.selector import Selector
class DayMA(Selector):
# 在此处设置选股器相关参数
fast = 5
slow = 10
def calculate_MA_signal(self, data):
candle_data = data[1].dropna()
if len(candle_data) == 0:
return
fast = MA(candle_data, timeperiod=self.fast)
slow = MA(candle_data, timeperiod=self.slow)
f_over_s = fast - slow >0
f_under_s = fast - slow <=0
cross_over = (f_under_s.shift(1)) * f_over_s
cross_under = - (f_over_s.shift(1))*f_under_s
choice = pd.DataFrame(cross_over + cross_under)
choice.columns = [data[0],]
return choice
def execute(self, pool, start, end, data=None, data_config=None):
selector_result = map(self.calculate_MA_signal, data.iteritems())
selector_result = pd.concat(selector_result, axis=1).stack()
selector_result.index.names = ["date","asset"]
return selector_result.loc[start:end]
from datetime import datetime
from fxdayu_data import DataAPI
# 测试参数设置
start = datetime(2016, 1, 1)
end = datetime(2017, 11, 24, 15)
periods = (1, 5, 10)
# 获取数据
codes = DataAPI.info.codes('hs300')
PN = DataAPI.candle(codes, 'D', start=start, end=end, adjust="after")
from fxdayu_alphaman.selector.admin import Admin
selector = DayMA()
s_admin = Admin()
result = s_admin.instantiate_selector_and_get_selector_result("DayMA", codes, start, end, Selector=selector, data=PN)
print(result.tail())
date asset
2017-11-24 15:00:00 601997.XSHG 0
601998.XSHG 0
603160.XSHG 1
603858.XSHG 0
603993.XSHG 0
dtype: object
from fxdayu_alphaman.selector.utility import read_benchmark
from fxdayu_alphaman.selector.selector_analysis import *
hs300 = read_benchmark(start, end)
hs300_return = get_stocklist_mean_return(hs300["index"],"hs300",start,end,hs300["close"],periods=periods)
print (hs300_return)
1 5 10
factor_quantile date
hs300 2016-01-01 15:00:00 0.000000 0.000000 0.000000
2016-01-02 15:00:00 0.000000 0.000000 0.000000
2016-01-03 15:00:00 0.000000 0.000000 0.000000
2016-01-04 15:00:00 0.002412 -0.080094 -0.097879
2016-01-05 15:00:00 0.017544 -0.075621 -0.073491
2016-01-06 15:00:00 -0.069334 -0.108461 -0.103234
2016-01-07 15:00:00 0.020392 -0.022101 -0.064665
2016-01-08 15:00:00 -0.050307 -0.072237 -0.073805
2016-01-09 15:00:00 0.000000 0.000000 0.000000
2016-01-10 15:00:00 0.000000 0.000000 0.000000
2016-01-11 15:00:00 0.007286 -0.019333 -0.019909
2016-01-12 15:00:00 -0.018606 0.002304 -0.085580
2016-01-13 15:00:00 0.020815 0.005862 -0.071463
2016-01-14 15:00:00 -0.031922 -0.043525 -0.114171
2016-01-15 15:00:00 0.003848 -0.001690 -0.055356
2016-01-16 15:00:00 0.000000 0.000000 0.000000
2016-01-17 15:00:00 0.000000 0.000000 0.000000
2016-01-18 15:00:00 0.029511 -0.000588 -0.073363
2016-01-19 15:00:00 -0.015122 -0.087682 -0.081223
2016-01-20 15:00:00 -0.029307 -0.076875 -0.071113
2016-01-21 15:00:00 0.010421 -0.073860 -0.031347
2016-01-22 15:00:00 0.004956 -0.053757 -0.048072
2016-01-23 15:00:00 0.000000 0.000000 0.000000
2016-01-24 15:00:00 0.000000 0.000000 0.000000
2016-01-25 15:00:00 -0.060207 -0.072818 -0.058225
2016-01-26 15:00:00 -0.003455 0.007080 0.032828
2016-01-27 15:00:00 -0.026137 0.006242 0.045377
2016-01-28 15:00:00 0.032354 0.045904 0.070062
2016-01-29 15:00:00 -0.015288 0.006008 0.035807
2016-01-30 15:00:00 0.000000 0.000000 0.000000
... ... ... ...
2017-10-25 15:00:00 0.004182 0.004946 0.017868
2017-10-26 15:00:00 0.007109 0.000889 0.020613
2017-10-27 15:00:00 -0.003046 -0.007278 0.022362
2017-10-28 15:00:00 0.000000 0.000000 0.000000
2017-10-29 15:00:00 0.000000 0.000000 0.000000
2017-10-30 15:00:00 -0.000748 0.002786 0.029516
2017-10-31 15:00:00 -0.002521 0.011863 0.023119
2017-11-01 15:00:00 0.000128 0.012858 0.019279
2017-11-02 15:00:00 -0.001108 0.019707 0.026989
2017-11-03 15:00:00 0.007060 0.029857 0.032096
2017-11-04 15:00:00 0.000000 0.000000 0.000000
2017-11-05 15:00:00 0.000000 0.000000 0.000000
2017-11-06 15:00:00 0.008297 0.026656 0.030575
2017-11-07 15:00:00 -0.001539 0.011124 0.040316
2017-11-08 15:00:00 0.006890 0.006339 0.044358
2017-11-09 15:00:00 0.008835 0.007142 0.006502
2017-11-10 15:00:00 0.003930 0.002174 -0.001875
2017-11-11 15:00:00 0.000000 0.000000 0.000000
2017-11-12 15:00:00 0.000000 0.000000 0.000000
2017-11-13 15:00:00 0.000000 0.000000 0.000000
2017-11-14 15:00:00 0.000000 0.000000 0.000000
2017-11-15 15:00:00 0.000000 0.000000 0.000000
2017-11-16 15:00:00 0.000000 0.000000 0.000000
2017-11-17 15:00:00 0.000000 0.000000 0.000000
2017-11-18 15:00:00 0.000000 0.000000 0.000000
2017-11-19 15:00:00 0.000000 0.000000 0.000000
2017-11-20 15:00:00 0.000000 0.000000 0.000000
2017-11-21 15:00:00 0.000000 0.000000 0.000000
2017-11-22 15:00:00 0.000000 0.000000 0.000000
2017-11-23 15:00:00 0.000000 0.000000 0.000000
[693 rows x 3 columns]
performance = s_admin.calculate_performance("DayMA",
result[result>0], #结果大于0的(选出的)
start,
end,
periods=periods,
benchmark_return=hs300_return)
import alphalens
def plot_performance(performance):
# 1.收益概率密度分布图
plot_distribution_of_returns(performance["upside_return"],period=10,return_type="upside")
# 2.收益概率密度分布图-提琴盒图
plot_stock_returns_violin(performance["upside_return"],return_type="upside")
plot_stock_returns_violin(performance["downside_return"],return_type="downside")
# 3.累积收益曲线
alphalens.plotting.plot_cumulative_returns_by_quantile(performance["mean_return"],period=10)
plt.show()
plot_performance(performance)
performance["upside_return"][10].quantile(0.75)
0.07266650400620958
performance["downside_return"][10].quantile(0.25)
-0.062460970024979176
#优化选股器参数
para_range_dict = {"fast":range(2,7,1),"slow":range(10,20,1)}
results_list, para_dict_list = s_admin.enumerate_parameter("DayMA",
para_range_dict,
codes,
start,
end,
Selector=selector,
data=PN,
parallel=False)
len(results_list)
50
# 生成策略名称与策略结果的列表
strategy_dict = {}
for i in range(len(results_list)):
strategy_name = "DayMA+" + str(para_dict_list[i])
strategy_result = results_list[i][results_list[i]>0]
strategy_dict[strategy_name]=strategy_result
performance_list = s_admin.show_strategies_performance(strategy_dict,
start,
end,
periods=periods,
benchmark_return=hs300_return,
parallel=False)
# 按夏普率对选股信号-10天持仓目标寻优
performance_rank = s_admin.rank_performance(performance_list,
target_period=10,
target_indicator="Sharpe ratio",
ascending=False)
print (performance_rank[0].strategy_name)
print (performance_rank[0].key_performance_indicator)
DayMA+{'fast': 6, 'slow': 15}
{'period_1': Annual return -0.083201
Cumulative returns -0.212494
Annual volatility 0.199780
Sharpe ratio -0.334403
Calmar ratio -0.249621
Stability 0.089731
Max drawdown -0.333308
Omega ratio 0.917034
Sortino ratio -0.458437
Skew -0.473311
Kurtosis 18.072241
Tail ratio 1.007174
Daily value at risk -0.025435
Alpha -0.127551
Beta 0.841140
dtype: float64, 'period_5': Annual return 0.073386
Cumulative returns 0.215008
Annual volatility 0.414937
Sharpe ratio 0.374523
Calmar ratio 0.140593
Stability 0.011811
Max drawdown -0.521978
Omega ratio 1.092453
Sortino ratio 0.589663
Skew 1.078674
Kurtosis 7.584723
Tail ratio 0.933924
Daily value at risk -0.051660
Alpha -0.117579
Beta 0.743836
dtype: float64, 'period_10': Annual return 0.383552
Cumulative returns 1.441954
Annual volatility 0.536604
Sharpe ratio 0.867059
Calmar ratio 0.646380
Stability 0.206264
Max drawdown -0.593384
Omega ratio 1.221870
Sortino ratio 1.367665
Skew 1.316101
Kurtosis 13.863635
Tail ratio 1.012346
Daily value at risk -0.065759
Alpha -0.129780
Beta 0.679332
dtype: float64}
plot_performance(performance_rank[0])
performance_rank[0]["upside_return"][10].quantile(0.75)
0.07279166815279806
performance_rank[0]["downside_return"][10].quantile(0.25)
-0.05795350860912572
import numpy as np
selector_sheet = s_admin.instantiate_selector_and_get_selector_result("DayMA",
codes,
start,
end,
Selector=selector,
data=PN,
para_dict={"slow":16, "fast":4})
selector_sheet = selector_sheet.unstack().replace(np.nan,0)
selector_sheet.to_excel('selector_opt.xlsx')