自己动手写一个印钞机 第二章

房东的猫 提交于 2021-02-13 16:39:34

作者:阿布🐶

未经本人允许禁止转载

ipython notebook git版本

目录章节地址: 自己动手写一个印钞机 第一章 自己动手写一个印钞机 第二章 自己动手写一个印钞机 第三章 自己动手写一个印钞机 第四章 自己动手写一个印钞机 第五章 自己动手写一个印钞机 第六章 自己动手写一个印钞机 第七章

简书目录章节地址: 自己动手写一个印钞机 第一章 自己动手写一个印钞机 第二章 自己动手写一个印钞机 第三章 自己动手写一个印钞机 第四章 自己动手写一个印钞机 第五章 自己动手写一个印钞机 第六章 自己动手写一个印钞机 第七章 自己动手写一个印钞机 附录章

股票量化专题地址,请关注,谢谢!


非均衡胜负收益带来的必然非均衡胜负比例,目标由因子的能力解决一部分,模式识别提升关键的一部分

本章开始说文章的核心了,模式识别提升关键的一部分 本章的内容主要是通过机器学习如svm,随机森林等对stock模式识别的初步探索,俗称罪恶的第一步,但还是要坚定的卖出,毕竟目标是印钞机

下面运行因子对多年数据进行回测,模式识别中基本的需求就是生成训练集数据与测试集数据,对训练集的数据抽取特质,总结规律,在测试集上指导交易,与没有指导交易的测试集进行比对,查看效果。

BuyGoldenFactor.g_enable_filter_ml = True # 回测因子的历史且结果集加入机器学习需要的数据
BuyGoldenFactor.g_enable_snap = True # 生成交易这一时刻60日图像,为深度学习准备, 详情见第四章
buy_factors = [{'XD': 42, 'class': BuyGoldenFactorClass, 'draw': True}]

# n_folds: 6年数据回测生成五年单子
# train_test_split:回测时预留一份stock代码表作为测试集,生成9份训练集,当use_last_test为True 时只用一份测试stock代码表进行因子回测
# ret_cnt_need = 0:回测所有stock
out, orders_pd_train_snap = MetricsManger.make_metrics_rsc_mul_symbol_grid(buy_factors, n_folds=6, 
    score_type=METRICSTYPE.SYSMBOL_R_SCORES_GOLDEN.value, ret_cnt_need=0, train_test_split=True, 
    use_last_test=False, force_one_process=False)

pd.options.display.max_columns = 40
orders_pd_train_snap.tail(2) # 看看添加了提供机器学习数据的pandas

由于简书不支持html的表格,完整表格请查阅git上完整版ipython notebook


Snip20161020_19.png

这些特征都是什么比如deg_windowPd就是买入stock这一天前42天k线图的线性拟合斜率,deg_hisWindowPd是252天k线图的线性拟合斜率,它们代表了买入前stock的一种状态也就能代表一种特征,你可以理解为这些特征都是发生交易前的一些状态的量化值特征,暂时没有必要全部深入了解,知道是特征就行。

下面生成测试集数据

BuyGoldenFactor.g_enable_fiter = False
BuyGoldenFactor.g_enable_snap = True
buy_factors = [{'XD': 42, 'class': BuyGoldenFactorClass, 'draw': True}]
out, orders_pd_test = MetricsManger.make_metrics_rsc_mul_symbol_grid(buy_factors, n_folds=6, 
    score_type=METRICSTYPE.SYSMBOL_R_SCORES_GOLDEN.value, ret_cnt_need=0, train_test_split=False, 
    use_last_test=True, force_one_process=False)

orders_pd_train_snap.shape, orders_pd_test_snap.shape
    # out
    ((44412, 32), (4956, 32))

对训练集及测试集的结果进行大体的度量:主要就是看看非均衡胜负收益带来的必然非均衡胜负比例,目标由因子的能力解决一部分效果怎么样

train_ump = UmpMainClass(orders_pd_train_snap, MlFiterGoldenPdClass)
train_ump.show_general()
    # out
	all fit order = (41225, 32)
	win rate = 0.493559733172
	profit_cg.sum() = 281.687935222
	win mean = 0.0770327160087 loss_mean = -0.061738192442 

output_14_1.png

test_ump = UmpMainClass(orders_pd_test_snap, MlFiterGoldenPdClass)
test_ump.show_general()
	# out
	all fit order = (4612, 32)
	win rate = 0.5
	profit_cg.sum() = 37.4002795407
	win mean = 0.076550446692 loss_mean = -0.0605681543452 

output_15_1.png

显示在所有有结果的单子中胜率可以接近一半,且每次赢的0.07比没次输的0.06多, 但是贪婪的我仍然认为有优化空间,这个空间就是利用这个因子产生的输出数据 作为特征识别基础,提炼特征,指导交易,

模式识别提升关键的一部分

下面我们看看如何做到的呢

首先确认ml封装库是否能正常运行

test_fiter_more = MlFiterClass.create_test_more_fiter()

学习曲线

test_fiter_more.estimator.logistic_regression()
test_fiter_more.plot_learning_curve()

output_20_0.png

特征权重

test_fiter.importances_coef_pd()

Snip20161020_20.png

树逻辑图

test_fiter.plot_graphviz_tree()

output_24_0.png

混淆矩阵

test_fiter_more.plot_confusion_matrices()
    # out
    [[453  96]
     [100 242]]

output_26_1.png

roc

test_fiter_more.plot_roc_estimator()

output_28_1.png

特征选择

test_fiter_more.feature_selection()
    # out
	RFE selection
	             ranking support
	SibSp              1    True
	Parch              1    True
	Cabin_No           1    True
	Cabin_Yes          6   False
	Embarked_C         2   False
	Embarked_Q         5   False
	Embarked_S         3   False
	Sex_female         8   False
	Sex_male           1    True
	Pclass_1           4   False
	Pclass_2           7   False
	Pclass_3           1    True
	Age_scaled         1    True
	Fare_scaled        1    True

	RFECV selection
	             ranking support
	SibSp              1    True
	Parch              2   False
	Cabin_No           1    True
	Cabin_Yes          7   False
	Embarked_C         3   False
	Embarked_Q         8   False
	Embarked_S         4   False
	Sex_female         1    True
	Sex_male           9   False
	Pclass_1           5   False
	Pclass_2           6   False
	Pclass_3           1    True
	Age_scaled         1    True
	Fare_scaled        1    True

决策边界

test_fiter.plot_decision_function()

output_32_0.png

output_32_1.png

train test score

test_fiter_more.cross_val_accuracy_score()
    # out
    accuracy mean: 0.776812507093
    array([ 0.75555556,  0.72222222,  0.73033708,  0.75280899,  0.83146067,
    0.78651685,  0.80898876,  0.71910112,  0.82022472,  0.84090909])

切换使用其它学习方法

test_fiter_more.estimator.adaboost_classifier()
test_fiter_more.cross_val_accuracy_score()
    # out
    accuracy mean: 0.810433548973
    array([ 0.78888889,  0.78888889,  0.78651685,  0.80898876,  0.84269663,
    0.78651685,  0.82022472,  0.82022472,  0.79775281,  0.86363636])

可以证明封装库没有问题,可以放心使用,下一步上真正的stock数据

由252,60, 42天组成的走势数剧作为特质开始

from MlFiterDegPd import MlFiterDegPdClass
deg = MlFiterDegPdClass(orderPd=orders_pd_train_snap)
deg.df.head()

Snip20161020_21.png

deg().estimator.svc()
deg().cross_val_accuracy_score()
    # out
    accuracy mean: 0.491279520472
    array([ 0.48920689,  0.51758428,  0.49987873,  0.49551298,  0.48168809,
    0.4887218 ,  0.47610963,  0.47355653,  0.4853191 ,  0.50521718])

0.49的准确率,相当于是乱猜 是不是特征选择的不好呢,换一些特征试试

from MlFiterMainPd import MlFiterMainPdClass
main = MlFiterMainPdClass(orderPd=orders_pd_train_snap)
main.df.head()

Snip20161020_22.png

main().cross_val_accuracy_score()
    # out
    accuracy mean: 0.493608245706
    array([ 0.5008489 ,  0.49890856,  0.49793839,  0.48678147,  0.50303177,
    0.47125879,  0.49648314,  0.49369238,  0.49332686,  0.49381218])

0.49的准确率,还是乱猜 是不是特征太少了,构建一个特征多的试试

from MlFiter import MlFiterClass
order_has_ret = orders_pd_train_snap[(orders_pd_train_snap.result <> 0)]

all_pd = order_has_ret.filter(['result', 'deg_hisWindowPd', 'deg_windowPd', 'deg_60WindowPd', 'atr_std', 'jump_power', 
                               'diff_days', 'wave_score1', 'wave_score2', 'wave_score23'])
train_np = all_pd.as_matrix()
y = train_np[:, 0]
x = train_np[:, 1:]
all_filter = MlFiterClass(x, y, all_pd)
all_pd.head()

Snip20161020_23.png

# 这回使用随机森林
all_filter.estimator.random_forest_classifier()
all_filter.cross_val_accuracy_score()
    # out
    accuracy mean: 0.505349477658
    array([ 0.48678147,  0.50788261,  0.53019646,  0.50497211,  0.51297599,
    0.46058695,  0.51564395,  0.50994663,  0.4942975 ,  0.53021111])

0.50的准确率,这算是有所提升吗?😥

下面把数据离散化后,换种分类器测试

deg = MlFiterDegPdClass(orderPd=orders_pd_train_snap, dummies=True, invoke_hmm=False,
                       invoke_pca=False)
deg.df.head()

由于简书不支持html的表格,完整表格请查阅git上完整版ipython notebook


Snip20161022_52.png

上边封住好了的,在离散值的选择上不是瞎来的,会通过可视化来选择离散值bins,通过数据来指导数据最终指导交易

deg().estimator.random_forest_classifier()
deg().cross_val_accuracy_score()
    # out
    accuracy mean: 0.487590577522
    array([ 0.48217317,  0.51564395,  0.4962406 ,  0.49890856,  0.49745331,
    0.48338588,  0.49527043,  0.45414847,  0.44479495,  0.50788644])

结果还是乱猜

用其它等等方式仍然是胡猜,自己写的类似adaboost依然效果很差, 通过非均衡概率降低假阳,提高假阴的方式,最后统计所有测试集样本的判别概率发现其实还瞎猜

提高分类数量,设置阀值,提高准确率的方案

通过将profit cg qcut 100份分类

orders_pd_train_snap.profit_cg.fillna(0, inplace=True)
order_has_ret = orders_pd_train_snap[(orders_pd_train_snap.result <> 0)]
n_class = 100
order_has_ret['class'] = pd.qcut(order_has_ret.profit_cg, n_class, labels=range(0, n_class))
order_has_ret['class'] = order_has_ret['class'].astype(int)
ZLog.info(np.unique(order_has_ret['class']))

deg_pd = order_has_ret.filter(['class', 'result', 'deg_hisWindowPd', 'deg_windowPd', 'deg_60WindowPd'])
train_np = deg_pd.as_matrix()
y = train_np[:, 0]
x = train_np[:, 1:]
deg = MlFiterClass(x, y, deg_pd, force_clf=True)
deg_pd.head()

Snip20161020_24.png

  • y为class train_test_split进行分类

  • 使用cv数据集的 predict < class阀值 使用result==0的情况查看概率

    from sklearn.cross_validation import train_test_split from sklearn.metrics import accuracy_score from sklearn.metrics import classification_report

    deg.estimator.random_forest_classifier()

    train_df, cv_df = train_test_split(deg.df, test_size=0.1, random_state=0)

    fiter = deg.get_fiter() fiter.fit(train_df.as_matrix()[:, 2:], train_df.as_matrix()[:, 0])

    predictions = fiter.predict(cv_df.as_matrix()[:, 2:])

    cv_df['predict'] = predictions cv_df.head()

Snip20161020_25.png

cv_df['predict'].value_counts().sort_index().head(10)
    # out
	0.0    56
	1.0    50
	2.0    43
	3.0    47
	4.0    44
	5.0    45
	6.0    47
	7.0    30
	8.0    46
	9.0    39
	Name: predict, dtype: int64        

for threshold in np.arange(0, 10):
    ppv = cv_df[cv_df['predict'] <= threshold].result.value_counts()
    ZLog.info('threshold: {}, ppv: {}'.format(threshold, float(ppv[-1])/ppv.sum()))
    # out
	threshold: 0, ppv: 0.607142857143
	threshold: 1, ppv: 0.632075471698
	threshold: 2, ppv: 0.58389261745
	threshold: 3, ppv: 0.586734693878
	threshold: 4, ppv: 0.579166666667
	threshold: 5, ppv: 0.571929824561
	threshold: 6, ppv: 0.551204819277
	threshold: 7, ppv: 0.541436464088
	threshold: 8, ppv: 0.526960784314
	threshold: 9, ppv: 0.523489932886

threshold: 0,1,达到0.6了 但是数量上只有100多个,之后会有使用gmm-hmm的方式继续扩展这种思路,提高收益

只能说最后一种的这个思想可以作为扩展使用,实际中由于 '非均衡胜负收益' 很难带来质的好转,突然想到阿西莫夫的小说基地,对心理史学的最开始的评估,‘可能但是不可行’,我们的印钞机之路是否也是这样呢,下一章开始就是真正的印钞机之路了,一个即可能又可行之路!!! 下一章开始将使用深度学习方法来训练数据,提高胜率主要是卷机神经网络的使用


下一章地址 自己动手写一个印钞机 第三章


感谢🙏您能有耐心看到这里

如果有什么问题可以加阿布的微信

微信号:aaaabbbuu

mmexport1475383814280.jpg

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!