弱人工智能帮助无知小散从市场获利吗?

In [1]:
# 基础库导入

from __future__ import print_function
from __future__ import division

import warnings
# warnings.filterwarnings('ignore')
# warnings.simplefilter('ignore')

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import ipywidgets
%matplotlib inline

import os
import sys
# 使用insert 0即只使用github,避免交叉使用了pip安装的abupy,导致的版本不一致问题
sys.path.insert(0, os.path.abspath('../'))
import abupy

from abupy import AbuFactorAtrNStop, AbuFactorPreAtrNStop, AbuFactorCloseAtrNStop, AbuFactorBuyBreak
from abupy import AbuFactorSellBreak
from abupy import abu, EMarketTargetType, AbuMetricsBase, ABuMarketDrawing, ABuProgress, ABuSymbolPd
from abupy import EMarketTargetType, EDataCacheType, EMarketSourceType, EMarketDataFetchMode, EStoreAbu, AbuUmpMainMul

from abupy import AbuUmpMainDeg, AbuUmpMainJump, AbuUmpMainPrice, AbuUmpMainWave, feature, AbuFeatureDegExtend
from abupy import AbuUmpEdgeDeg, AbuUmpEdgePrice, AbuUmpEdgeWave, AbuUmpEdgeFull, AbuUmpEdgeMul, AbuUmpEegeDegExtend
from abupy import AbuUmpMainDegExtend, ump, Parallel, delayed, AbuMulPidProgress


pd.options.display.max_rows = 1000
from IPython.display import display
from IPython.core.display import HTML
from pprint import pprint, pformat 

# 关闭沙盒数据
abupy.env.disable_example_env_ipython()
 
#os.path.join(ABuEnv.g_project_cache_dir, 'abu_socket_progress')
NumExpr defaulting to 8 threads.
disable example env

股池

股池为上证50 + 创业50 + 沪深300 + 中证500 几大指数的成分股

In [2]:
import random
from  stock_pool import stock_pool

def custom_symbols():
    symbols = []    
    symbols.extend( random.sample(stock_pool.get('zh500'), 500))
    symbols.extend( random.sample(stock_pool.get('hs300'), 300))
    symbols.extend( random.sample(stock_pool.get('sh50'), 49))
    symbols.extend( random.sample(stock_pool.get('chuang50'), 50))

    return symbols

symbols = custom_symbols()
print(symbols)
/opt/notebooks/abupy_lecture
['600458', '600138', '002030', '600143', '002244', '601200', '600971', '300088', '000732', '600655', '603233', '600657', '601179', '601231', '600277', '002354', '000547', '600597', '601678', '600645', '600874', '002317', '002385', '600557', '601168', '300199', '000158', '000937', '600611', '002152', '000926', '600717', '600120', '601128', '603650', '000877', '600536', '002128', '000012', '600350', '000878', '000600', '002221', '002233', '600329', '002250', '300113', '002807', '002251', '600755', '600751', '600435', '600808', '600885', '600298', '002212', '600848', '601311', '002818', '000829', '601016', '000970', '600839', '600859', '600639', '600939', '002709', '000009', '600021', '002603', '600022', '300166', '600312', '600460', '603056', '002308', '600169', '603568', '000960', '601969', '000596', '600216', '002588', '300287', '300257', '002358', '000501', '000681', '603556', '600884', '600996', '002690', '600338', '002371', '002242', '002416', '002505', '000049', '300026', '603866', '600750', '601801', '002500', '603228', '600307', '600256', '000980', '002266', '600642', '600811', '600122', '600073', '600056', '000536', '002375', '002635', '000848', '000690', '002268', '000028', '600500', '002051', '000975', '002465', '601001', '600863', '002440', '000519', '002118', '002041', '601020', '600079', '601966', '002038', '000090', '002254', '000039', '002670', '000552', '300315', '300133', '600804', '603198', '000766', '600835', '002672', '603369', '000401', '600895', '002372', '603486', '603659', '600184', '002285', '600582', '600773', '600428', '600643', '002129', '300418', '000008', '603000', '601689', '000513', '002434', '000738', '300383', '300297', '600782', '300146', '000969', '000987', '002332', '300316', '603328', '300182', '000488', '603225', '601990', '000997', '000998', '600167', '000723', '000587', '601003', '600258', '601098', '002384', '002506', '603377', '300168', '603885', '600282', '000623', '000685', '300156', '002373', '600594', '000990', '601005', '002424', '600166', '601718', '000712', '601717', '601326', '600754', '002368', '603877', '300266', '000718', '600777', '002681', '000750', '600575', '603355', '600862', '000078', '002437', '600511', '601928', '600673', '002028', '002444', '600062', '300055', '002299', '002831', '600380', '600409', '002390', '002477', '002491', '600584', '600970', '600315', '600259', '600525', '600648', '002414', '600388', '002078', '600572', '600291', '002276', '000988', '000564', '002489', '600026', '002920', '300450', '600687', '601000', '603169', '600183', '600240', '002517', '600155', '300002', '002589', '002093', '002439', '600325', '002174', '000031', '300058', '600801', '600640', '600881', '600373', '000807', '603806', '002048', '000686', '600008', '000559', '600418', '600879', '600410', '002563', '002916', '300001', '601019', '002340', '002155', '300413', '600993', '600567', '300291', '300376', '000543', '300244', '600499', '601598', '000778', '000761', '600633', '600037', '002127', '600316', '600426', '600827', '600060', '300308', '600623', '300324', '002002', '002195', '603766', '002359', '002665', '601872', '603712', '600503', '600267', '600545', '600416', '600875', '002019', '002426', '600649', '601608', '603868', '000426', '002183', '002640', '002707', '300202', '600757', '600161', '000932', '002463', '600565', '002400', '000400', '000758', '600058', '600039', '000563', '002663', '300010', '600466', '600160', '600978', '002344', '600392', '002074', '600126', '000025', '603899', '002699', '600053', '600064', '002191', '601866', '601127', '600737', '600694', '600779', '600528', '600376', '000062', '000667', '600743', '603444', '600141', '600664', '600759', '603515', '002110', '600086', '600618', '000541', '002131', '002064', '002249', '000717', '002470', '000418', '300027', '002815', '603658', '300159', '002407', '000830', '002273', '002366', '000860', '601811', '600094', '002281', '002399', '000089', '600967', '002004', '600125', '600393', '600765', '000887', '600195', '600098', '000930', '601777', '600770', '603025', '600787', '300459', '600598', '601106', '002056', '002280', '601880', '600006', '002410', '600335', '000027', '002092', '600179', '000729', '000156', '002839', '601958', '600820', '603816', '600171', '600478', '000537', '603888', '600908', '002353', '000061', '002013', '002302', '600260', '002544', '002176', '300274', '300253', '002642', '603883', '002223', '601869', '600917', '300115', '600699', '000727', '600201', '600507', '600872', '002509', '000006', '000813', '002431', '002345', '002573', '300347', '002701', '002277', '600348', '000612', '002745', '600729', '600959', '002583', '002408', '600600', '000999', '000528', '600748', '600580', '600280', '600718', '002507', '000636', '300134', '603077', '000656', '002512', '600823', '601100', '000060', '002049', '002482', '600017', '002147', '600901', '603569', '300197', '600869', '600158', '002503', '000066', '600614', '000021', '600366', '600151', '000581', '600266', '600563', '000598', '601328', '000671', '000157', '002352', '002555', '601066', '601088', '600674', '601668', '601021', '002411', '600066', '300003', '000423', '600115', '001965', '601018', '000338', '600050', '600019', '002050', '002456', '601939', '601198', '002673', '600011', '600919', '000895', '600219', '601901', '600886', '600606', '601228', '601012', '603993', '600085', '601800', '600352', '601988', '601997', '600100', '002146', '601985', '601898', '300124', '601225', '002120', '600153', '603156', '002179', '603260', '600004', '002008', '601238', '600390', '000402', '601878', '603160', '600010', '000961', '601601', '600637', '000963', '600688', '601998', '601919', '601688', '000783', '600660', '002925', '600309', '600438', '601360', '300296', '600339', '600690', '601166', '000858', '300408', '601216', '601857', '601618', '001979', '002252', '600519', '002714', '600837', '000826', '600998', '603833', '600809', '000568', '600015', '600415', '600068', '002466', '600436', '002007', '600704', '600089', '600760', '002024', '601211', '601992', '600498', '300059', '002001', '600522', '300024', '600036', '002594', '601229', '000792', '000938', '002475', '000001', '600816', '600018', '000709', '600271', '300033', '600977', '600398', '002493', '002304', '002202', '600027', '600048', '002230', '600900', '603259', '000100', '600926', '601727', '600016', '600030', '002422', '002236', '600570', '000415', '600118', '600028', '600038', '600547', '002558', '000703', '601808', '300072', '600221', '600549', '600585', '601633', '600893', '600111', '600276', '300251', '600516', '600372', '600157', '000786', '000630', '600208', '002625', '601989', '600583', '600031', '300144', '600029', '601377', '600340', '601828', '000898', '600104', '000069', '000983', '600362', '000959', '000503', '600487', '002294', '000166', '002468', '300122', '002085', '603799', '601607', '600958', '601111', '000408', '600332', '000333', '600023', '603288', '600000', '601991', '002508', '600109', '000425', '002415', '601336', '600909', '002271', '002736', '601288', '002572', '600346', '002142', '000661', '601628', '600383', '000651', '601788', '002153', '000876', '600009', '000063', '601318', '600061', '000768', '600489', '300017', '600196', '601333', '002602', '601766', '600297', '601838', '600369', '000553', '600739', '600170', '002311', '002797', '002773', '600233', '601117', '600535', '600999', '600887', '601933', '601398', '002450', '600867', '000002', '601818', '601169', '300142', '002027', '601186', '601888', '000627', '002081', '601555', '600025', '600795', '002601', '002241', '000839', '000538', '600566', '002044', '600177', '601212', '000728', '600188', '601390', '603858', '600588', '300136', '000776', '300433', '002310', '601006', '600176', '600703', '601155', '601108', '601611', '002460', '601881', '000413', '601669', '002032', '600741', '000725', '601899', '601600', '601138', '002065', '600518', '603986', '600406', '002624', '300015', '601009', '601877', '000625', '600482', '600705', '300070', '603993', '601211', '601398', '601138', '601328', '601169', '601888', '601989', '601288', '601318', '600340', '601818', '601988', '601186', '600029', '601800', '600104', '600048', '601668', '601628', '603259', '600196', '601006', '601766', '600030', '600309', '601088', '601939', '601360', '601688', '600019', '600028', '600547', '601390', '600606', '600585', '600050', '601601', '601229', '600887', '601336', '600703', '600690', '600036', '601166', '600276', '601857', '600016', '600000', '300750', '300098', '300059', '300136', '300496', '300747', '300146', '300170', '300072', '300088', '300454', '300666', '300413', '300115', '300113', '300251', '300274', '300070', '300024', '300122', '300450', '300033', '300009', '300168', '300383', '300073', '300347', '300017', '300315', '300634', '300433', '300014', '300253', '300355', '300618', '300078', '300124', '300601', '300015', '300377', '300676', '300003', '300287', '300418', '300027', '300699', '300038', '300316', '300760', '300408']
/opt/conda/lib/python3.7/site-packages/openpyxl/worksheet/header_footer.py:48: UserWarning: Cannot parse header or footer so it will be ignored
  warn("""Cannot parse header or footer so it will be ignored""")

策略

一个经典的均线多头排列策略,策略本身优秀与否不是重点,本次主要是研究 弱人工智能如何帮我们提高收益,是观察没有使用AI和使用AI后 的对比。

In [3]:
from picker.WzPickNonNew import WzPickNonNew
from picker.WzPickMaAng import WzPickMaAng
from abupy import AbuPtPosition
from factor.WzFactorBuyRsiV8 import WzFactorBuyRsiV8
from factor.WzFactorSellRsiV8 import WzFactorSellRsiV8
from factor.WzFactorBuyMaV6 import WzFactorBuyMaV6
from factor.WzFactorSellMaV5 import WzFactorSellMaV5

from abupy import slippage 
# 开启针对非集合竞价阶段的涨停,滑点买入价格以高概率在接近涨停的价格买入 
slippage.sbb.g_enable_limit_up = True 
# 将集合竞价阶段的涨停买入成功概率设置为0,如果设置为0.2即20%概率成功买入 
slippage.sbb.g_pre_limit_up_rate = 0 
# 开启针对非集合竞价阶段的跌停,滑点卖出价格以高概率在接近跌停的价格卖出 
slippage.ssb.g_enable_limit_down = True 
# 将集合竞价阶段的跌停卖出成功概率设置为0, 如果设置为0.2即20%概率成功卖出 
slippage.ssb.g_pre_limit_down_rate = 0


abupy.env.g_data_cache_type = EDataCacheType.E_DATA_CACHE_CSV
abupy.env.g_market_target = EMarketTargetType.E_MARKET_TARGET_CN
abupy.env.g_data_fetch_mode = EMarketDataFetchMode.E_DATA_FETCH_FORCE_LOCAL

buy_factors=[{'buy_default': 'post=36.88',
  'class': WzFactorBuyRsiV8,
#   'position': {'class': AbuPtPosition,
#                'past_day_cnt': 68,
#                'pos_base': pt_pos_base },
  'rsi_timeperiod': 6,
  'stock_pickers': [{'class': WzPickNonNew,
                     'pick_period': 'week',
                     'weeks': 24},
#                      {'class':WzPickMaAng,
#                         'ma_timeperiod': 60,
#                         'xdd': 20,
#                         'min_ang':-1.2, # 2.7 , 5.0 , 7.1
#                         'max_ang':90,
#                         'pick_period': 'week',
#                     },
                  ]
             }]

# 卖出因子继续使用上一节使用的因子
sell_factors = [
#     {'stop_loss_n': 1.0, 'stop_win_n': 3.0,
#      'class': AbuFactorAtrNStop},
#     {'class': AbuFactorPreAtrNStop, 'pre_atr_n': 1.5},
    {'class': WzFactorSellMaV5 ,
      'ma_type': 1,
      'sell_x': 'rvv=5,6,0.22,yc,1.0'},
    {'class': WzFactorSellRsiV8,
      'rsi_timeperiod': 6,
      'sell_default':'rvv=10,-,78,16,65,1.0' }, #  
    {'class': AbuFactorCloseAtrNStop, 'close_atr_n': 1.75},
    {'class': AbuFactorAtrNStop, 'stop_loss_n': 2.1},
    {'class': WzFactorSellRsiV8,
      'rsi_timeperiod': 6,
      'sell_default': 'lt=2,29,1.0|lt=3,39,1.0'}, 
]


print("随便输出点什么表示已经执行过: ")
随便输出点什么表示已经执行过: 

策略回测 - 准备交割单数据用于机器人裁判训练

将股池所有股票分切成4块,拿3/4用于机器人裁判训练, 剩下1/4是测试集用途。

In [4]:
# import psutil

# from warnings import simplefilter
# simplefilter(action='ignore', category=FutureWarning)
# simplefilter(action='ignore', category=ResourceWarning)

# g_cpu_cnt = psutil.cpu_count(logical=True) * 1
# print ("g_cpu_cnt:", g_cpu_cnt)

# 回测生成买入时刻特征
abupy.env.g_enable_ml_feature = True
# 回测开始时将symbols切割分为训练集数据和测试集两份,使用训练集进行回测
abupy.env.g_enable_train_test_split = True
# 训练:测试 = 3:1
abupy.env.g_split_tt_n_folds = 4

feature.clear_user_feature()
feature.append_user_feature(AbuFeatureDegExtend)

read_cash = 5000000 #500w资金
o_pos_base =0.1 #abupy.beta.atr.g_atr_pos_base
print('o_pos_base:', o_pos_base)
abupy.beta.atr.g_atr_pos_base =  o_pos_base / 25
print('abupy.beta.atr.g_atr_pos_base:' , abupy.beta.atr.g_atr_pos_base)

abu_result_tuple = None

def run_loop_back():
    global abu_result_tuple, symbols    
    print(symbols)
    abu_result_tuple, _ = abu.run_loop_back(read_cash,
                                            buy_factors,
                                            sell_factors,
                                            choice_symbols = symbols,
#                                           choice_symbols=None,
                                            start='2016-02-02', end='2019-09-12',
#                                             stock_picks= stock_pickers,
#                                             n_process_kl = g_cpu_cnt,
#                                             n_process_pick= g_cpu_cnt,
                                           )

    # 把运行的结果保存在本地,以便之后分析回测使用,保存回测结果数据代码如下所示
    abu.store_abu_result_tuple(abu_result_tuple, n_folds=3, store_type=EStoreAbu.E_STORE_CUSTOM_NAME, 
                               custom_name='train_cn')
    ABuProgress.clear_output()
    AbuMetricsBase.show_general(*abu_result_tuple, only_show_returns=True).plot_max_draw_down()

def run_load_train():
    global abu_result_tuple
    abu_result_tuple = abu.load_abu_result_tuple(n_folds=3, store_type=EStoreAbu.E_STORE_CUSTOM_NAME, 
                                                 custom_name='train_cn')
    AbuMetricsBase.show_general(*abu_result_tuple, only_show_returns=True).plot_max_draw_down()

def select(select):
    if select == 'run loop back':
        run_loop_back()
    else:
        run_load_train()

# _ = ipywidgets.interact_manual(select, select=[ 'load train data', 'run loop back'])
run_load_train()
o_pos_base: 0.1
abupy.beta.atr.g_atr_pos_base: 0.004
买入后卖出的交易数量:30472
买入后尚未卖出的交易数量:500
胜率:36.5844%
平均获利期望:6.8907%
平均亏损期望:-4.0263%
盈亏比:1.0016
策略收益: 3.2309%
基准收益: 8.8748%
策略年化收益: 0.9231%
基准年化收益: 2.5357%
策略买入成交比例:41.2017%
策略资金利用率比例:83.4360%
策略共执行882个交易日
最大回撤: 0.291641
最大回测启始时间:2018-03-12, 结束时间2019-01-03, 共回测1858966.707000

策略效果基本和大盘同步

训练集和测试集回顾:

上面的abupy.env.g_enable_train_test_split = Trueabupy.env.g_split_tt_n_folds = 4配置自动把训练集和测试集分切好了,打印出来看看。

In [5]:
from abupy import ABuFileUtil

a = ['1', '2', '3', 'a', 'b', 'c']
b = ['0','2','b','f**k']
print('a&b交集为:', set(a).intersection(b) )


train = ABuFileUtil.load_pickle("/root/abu/data/cache/market_train_symbols_hs")
test = ABuFileUtil.load_pickle("/root/abu/data/cache/market_test_symbols_hs")

print('训练集和测试集交集为:', set(train).intersection(test) )

print( len(train), "个训练集股票:\r\n", train, "\r\n") 
print( len(test), "个测试集股票:\r\n", test) 
674 个训练集股票:
 ['002400', '002041', '600167', '603000', '000418', '000401', '002414', '300197', '000778', '600808', '600511', '600507', '600184', '002437', '000049', '002176', '000012', '002818', '000587', '000061', '603169', '000717', '000060', '603377', '000988', '000975', '000156', '002128', '002372', '601020', '600056', '000636', '002191', '002354', '600611', '000612', '000723', '600260', '002491', '600161', '300316', '000937', '600879', '603712', '600575', '600466', '600022', '600388', '300001', '002373', '000681', '600770', '002500', '002174', '600062', '600623', '002707', '601869', '002407', '002183', '300297', '002254', '000563', '002701', '601801', '002030', '000848', '600748', '600073', '300156', '002317', '603883', '002366', '600060', '002640', '300146', '300266', '000158', '600393', '002129', '600649', '002221', '600694', '002004', '002110', '600777', '000712', '300459', '601928', '000980', '000960', '600737', '002434', '002344', '000598', '002195', '600141', '600021', '600839', '600277', '600316', '600699', '600645', '002064', '002302', '600580', '000930', '300450', '002285', '601777', '600869', '002670', '603369', '600773', '000025', '002681', '002665', '002048', '600125', '603056', '000559', '000596', '002345', '000887', '600478', '600754', '002635', '601168', '603766', '600435', '002155', '002424', '601016', '600499', '603899', '600120', '600597', '600143', '600325', '002056', '601003', '000519', '600094', '300159', '600759', '000932', '002440', '300418', '600373', '002603', '002831', '000718', '002583', '600348', '600751', '002249', '300291', '601311', '300115', '002276', '600171', '600079', '600618', '002127', '000581', '002371', '300058', '000021', '002431', '002353', '603515', '600757', '000667', '603866', '600410', '600779', '600908', '603486', '002273', '002489', '002589', '000970', '600418', '600338', '603877', '000761', '300376', '600820', '603328', '601001', '002385', '300324', '600835', '603233', '000541', '600380', '601106', '600811', '600565', '601969', '300257', '600614', '002573', '000062', '600179', '000998', '600648', '603198', '601811', '000997', '600657', '600743', '000089', '000990', '601598', '600409', '600967', '600259', '002251', '000501', '000813', '600787', '600307', '000090', '603569', '300274', '002390', '002509', '000656', '000732', '601326', '300133', '600195', '601000', '600298', '002477', '300088', '600557', '600859', '002465', '000039', '600823', '002250', '300347', '601880', '600216', '600428', '600874', '000426', '601100', '002699', '601678', '002512', '600598', '600376', '002463', '000008', '600458', '601179', '600600', '601098', '600416', '600872', '600503', '002563', '603658', '000877', '600169', '600098', '002092', '600282', '600584', '002074', '600917', '002038', '603355', '002709', '000727', '000623', '002384', '000009', '600126', '600863', '300413', '002408', '600037', '600350', '600563', '002078', '600366', '600335', '000027', '002051', '600642', '600064', '600266', '002233', '000528', '002277', '601200', '600536', '600500', '002503', '300199', '600827', '002308', '002588', '000006', '601958', '300308', '000829', '600329', '300383', '002482', '002013', '000600', '002268', '601872', '002358', '002506', '000031', '600006', '600655', '600971', '600901', '600122', '603556', '002839', '603650', '300027', '601866', '002299', '600026', '000400', '300026', '000690', '600017', '600312', '601966', '600640', '300244', '002517', '002672', '600086', '300113', '300182', '000552', '601718', '600256', '600862', '603077', '002375', '002815', '000729', '600970', '300010', '600460', '603025', '600160', '600594', '600058', '002439', '600258', '600848', '300002', '600183', '000987', '600053', '600280', '603885', '600545', '603659', '600765', '002152', '000750', '600884', '600718', '300166', '603868', '002007', '600606', '000402', '600208', '601991', '600000', '600276', '002456', '600111', '600153', '300251', '002050', '601328', '002311', '000728', '000792', '300015', '000786', '600176', '600352', '002475', '002236', '000157', '601838', '603156', '002625', '600104', '600999', '603993', '601318', '000166', '000002', '601828', '002558', '000538', '000651', '601333', '000983', '601997', '002008', '601888', '600436', '002422', '600233', '600346', '601166', '300408', '600157', '601989', '002202', '600741', '600085', '600027', '600068', '600390', '000100', '601898', '000338', '002024', '600050', '600998', '002085', '603260', '600188', '600048', '600795', '600019', '600221', '600115', '002044', '600028', '600066', '002411', '600760', '601021', '600340', '600588', '000839', '000876', '600196', '600009', '002925', '601238', '600637', '600739', '300024', '600271', '002773', '601009', '000625', '601857', '600025', '601225', '601216', '000413', '601390', '002065', '600029', '002146', '002294', '600309', '603799', '600518', '002736', '002271', '000768', '601668', '601212', '600118', '002493', '300003', '601117', '002797', '600837', '002081', '300017', '000423', '601186', '000568', '600887', '600674', '601198', '600061', '601229', '000959', '603858', '600018', '002601', '000425', '600549', '601169', '300033', '600566', '601788', '603160', '002572', '000858', '600036', '000001', '600919', '002460', '300296', '601933', '601992', '600415', '002142', '601601', '600816', '000661', '601360', '000783', '600406', '601881', '002032', '600010', '601808', '300433', '600297', '000776', '300144', '002179', '600535', '300142', '603986', '600038', '000630', '600926', '600688', '002450', '002241', '600886', '000961', '601398', '300122', '601555', '002310', '000671', '601901', '002352', '000408', '002027', '000898', '002508', '601111', '600519', '600690', '600547', '601899', '600585', '001979', '600958', '000725', '002673', '000938', '600339', '300070', '002555', '600023', '000553', '000895', '600170', '600100', '601628', '600332', '600583', '600703', '002466', '603288', '600438', '600893', '300136', '600015', '000063', '603259', '600177', '002304', '601800', '000503', '601006', '600031', '601377', '601318', '601211', '601688', '601668', '600309', '600104', '600019', '601988', '601088', '603993', '601398', '601888', '601800', '600029', '600690', '600016', '601857', '600703', '601989', '601939', '601138', '600547', '600606', '600196', '601169', '601766', '600028', '600050', '601006', '601390', '601601', '601360', '600030', '600036', '600048', '300070', '300017', '300072', '300634', '300454', '300315', '300033', '300666', '300750', '300122', '300088', '300760', '300274', '300355', '300747', '300618', '300113', '300496', '300003', '300136', '300316', '300124', '300115', '300433', '300287', '300253', '300418', '300251', '300014', '300413', '300383', '300027', '300450', '300408', '300098', '300377', '300146', '300170', '300699'] 

225 个测试集股票:
 ['600782', '300287', '002242', '300202', '000686', '000878', '002368', '000807', '600528', '000926', '600267', '002131', '002399', '600687', '300253', '000078', '600166', '002223', '603444', '002332', '600426', '000685', '600039', '600885', '002212', '601019', '600567', '000564', '601608', '601231', '000999', '600895', '002340', '000766', '601127', '002745', '002642', '603568', '002470', '600240', '600315', '002147', '601717', '603816', '000758', '002002', '600643', '002916', '600639', '000830', '601128', '300134', '000547', '002690', '002266', '002028', '600155', '002505', '600804', '600525', '600750', '000738', '600392', '600881', '300168', '002416', '002920', '000969', '002444', '600151', '600939', '002118', '000860', '600959', '600801', '000543', '603806', '600729', '002663', '300055', '002544', '002280', '000536', '002507', '600633', '000513', '002019', '600664', '002049', '603888', '603225', '603228', '002807', '600996', '000066', '600291', '601005', '600572', '600138', '002281', '600673', '002359', '000028', '300315', '600201', '002093', '002410', '000537', '600008', '600717', '600582', '600158', '002244', '000488', '002426', '600755', '600978', '600875', '601689', '600993', '601990', '300072', '001965', '601611', '601633', '002120', '601607', '600030', '601012', '601138', '600219', '600867', '601878', '601228', '601066', '601818', '601985', '601088', '600704', '600489', '000333', '601018', '601618', '002602', '002001', '601998', '601155', '600809', '600487', '600398', '600011', '600570', '600362', '601336', '600372', '600498', '600383', '601688', '002153', '600004', '002714', '601600', '600909', '600660', '600482', '600977', '601988', '002415', '600089', '601727', '601108', '000709', '300059', '002230', '600516', '000826', '000963', '002624', '000069', '601939', '600522', '002468', '000703', '601919', '300124', '600109', '002252', '000415', '601877', '600900', '603833', '600369', '601669', '601766', '002594', '601288', '600705', '600016', '601211', '000627', '601628', '600340', '601186', '603259', '600276', '601336', '601288', '600000', '600887', '601818', '601166', '601229', '600585', '601328', '300059', '300347', '300015', '300168', '300073', '300078', '300601', '300009', '300038', '300676', '300024']

用上面交割单数据训练机器人裁判

主裁:

In [6]:
# import warnings
# warnings.simplefilter("ignore", ResourceWarning)

# 需要全局设置为A股市场,在ump会根据市场类型保存读取对应的ump
abupy.env.g_market_target = EMarketTargetType.E_MARKET_TARGET_CN
ump_deg=None
ump_jump=None
ump_mul=None
ump_price=None
ump_main_deg_extend=None
ump_wave=None

# 使用训练集交易数据训练主裁
orders_pd_train_cn = abu_result_tuple.orders_pd

def train_main_ump():    
    print('AbuUmpMainDeg begin...') #brust_min=False,      
    AbuUmpMainDeg.ump_main_clf_dump(orders_pd_train_cn, save_order=False, show_order=False)
    
    print('AbuUmpMainWave begin...')
    AbuUmpMainWave.ump_main_clf_dump(orders_pd_train_cn, save_order=False, show_order=False)    
    
    print('AbuUmpMainPrice begin...')
    AbuUmpMainPrice.ump_main_clf_dump(orders_pd_train_cn, save_order=False, show_order=False)   
    
    print('AbuUmpMainJump begin...')
    AbuUmpMainJump.ump_main_clf_dump(orders_pd_train_cn, save_order=False, show_order=False)
    
    print('AbuUmpMainMul begin...')
    AbuUmpMainMul.ump_main_clf_dump(orders_pd_train_cn, save_order=False, show_order=False)
    
    print('AbuUmpMainDegExtend begin...')
    AbuUmpMainDegExtend.ump_main_clf_dump(orders_pd_train_cn, save_order=False, show_order=False)    
    # 依然使用load_main_ump,避免下面多进程内存拷贝过大
    load_main_ump()
    
def load_main_ump():
    global ump_deg, ump_jump, ump_mul, ump_price, ump_main_deg_extend, ump_wave
    ump_deg = AbuUmpMainDeg(predict=True)
    ump_jump = AbuUmpMainJump(predict=True)
    ump_mul = AbuUmpMainMul(predict=True)
    ump_price = AbuUmpMainPrice(predict=True)
    ump_main_deg_extend = AbuUmpMainDegExtend(predict=True)
    ump_wave =  AbuUmpMainWave(predict=True )
    print('load main ump complete!')

def select(select):
    if select == 'train main ump':
        train_main_ump()
    else:
        load_main_ump()

# _ = ipywidgets.interact_manual(select, select=['load main ump', 'train main ump'])

load_main_ump()
load main ump complete!

边裁

In [7]:
# from abupy import AbuUmpEdgeDeg, AbuUmpEdgePrice, AbuUmpEdgeWave, AbuUmpEdgeFull, AbuUmpEdgeMul, AbuUmpEegeDegExtend
# AbuUmpEdgeWave, AbuUmpEdgeFull, AbuUmpEdgeMul
# 需要全局设置为A股市场,在ump会根据市场类型保存读取对应的ump
abupy.env.g_market_target = EMarketTargetType.E_MARKET_TARGET_CN

# 使用训练集交易数据训练
orders_pd_train_cn = abu_result_tuple.orders_pd

print('AbuUmpEdgeDeg begin...')
AbuUmpEdgeDeg.ump_edge_clf_dump(orders_pd_train_cn)
edge_deg = AbuUmpEdgeDeg(predict=True)

print('AbuUmpEdgePrice begin...')
AbuUmpEdgePrice.ump_edge_clf_dump(orders_pd_train_cn)
edge_price = AbuUmpEdgePrice(predict=True)

print('AbuUmpEdgeMul begin...')
AbuUmpEdgeMul.ump_edge_clf_dump(orders_pd_train_cn)
edge_mul = AbuUmpEdgeMul(predict=True)

print('AbuUmpEegeDegExtend begin...')
AbuUmpEegeDegExtend.ump_edge_clf_dump(orders_pd_train_cn)
edge_deg_extend = AbuUmpEegeDegExtend(predict=True)

print('AbuUmpEdgeWave begin...')
AbuUmpEdgeWave.ump_edge_clf_dump(orders_pd_train_cn)
edge_wave = AbuUmpEdgeWave(predict=True)

print('AbuUmpEdgeFull begin...')
AbuUmpEdgeFull.ump_edge_clf_dump(orders_pd_train_cn)
edge_full = AbuUmpEdgeFull(predict=True)

print('fit edge complete!')
/opt/notebooks/abupy/UmpBu/ABuUmpBase.py:187: FutureWarning: Method .as_matrix will be removed in a future version. Use .values instead.
  ump_np = ump_df.as_matrix()
AbuUmpEdgeDeg begin...
please wait! dump_pickle....: /root/abu/data/ump/ump_edge_hs_deg_edge
AbuUmpEdgePrice begin...
please wait! dump_pickle....: /root/abu/data/ump/ump_edge_hs_price_edge
AbuUmpEdgeMul begin...
please wait! dump_pickle....: /root/abu/data/ump/ump_edge_hs_mul_edge
AbuUmpEegeDegExtend begin...
please wait! dump_pickle....: /root/abu/data/ump/ump_edge_hs_extend_edge_deg
AbuUmpEdgeWave begin...
please wait! dump_pickle....: /root/abu/data/ump/ump_edge_hs_wave_edge
AbuUmpEdgeFull begin...
please wait! dump_pickle....: /root/abu/data/ump/ump_edge_hs_full_edge
fit edge complete!

应用到新的交易

未启用裁判的测试集 - 用于对比:

In [8]:
# 测试集回测时依然生成买入时刻特征
abupy.env.g_enable_ml_feature = True
# 回测时不重新切割训练集数据和测试集
abupy.env.g_enable_train_test_split = False
# 回测时使用切割好的测试数据
abupy.env.g_enable_last_split_test = True


# 测试集依然使用10,30,50,90,120日走势拟合角度特征AbuFeatureDegExtend,做为回测时的新的视角来录制比赛(记录回测特征)
feature.clear_user_feature()
feature.append_user_feature(AbuFeatureDegExtend)

read_cash = 5000000 #500w资金
o_pos_base =0.1 #abupy.beta.atr.g_atr_pos_base
print('o_pos_base:', o_pos_base)
abupy.beta.atr.g_atr_pos_base =  o_pos_base / 8
print('abupy.beta.atr.g_atr_pos_base:' , abupy.beta.atr.g_atr_pos_base)


abu_result_tuple_test = None
order_has_result = None

def run_loop_back_test():
    global abu_result_tuple_test, order_has_result
    abu_result_tuple_test, _ = abu.run_loop_back(read_cash,
                                                 buy_factors,
                                                 sell_factors,
                                                 choice_symbols=None,
                                                 start='2016-02-02', end='2019-09-12',
#                                                     n_process_kl = 6,
#                                                     n_process_pick= 6,
                                                )
    # 把运行的结果保存在本地,以便之后分析回测使用,保存回测结果数据代码如下所示
    abu.store_abu_result_tuple(abu_result_tuple_test, n_folds=3, store_type=EStoreAbu.E_STORE_CUSTOM_NAME, 
                               custom_name='test_cn')
    ABuProgress.clear_output()
    AbuMetricsBase.show_general(*abu_result_tuple_test, only_show_returns=True).plot_max_draw_down()
    # 验证A股主裁是否称职
    # 选取有交易结果的数据order_has_result
    order_has_result = abu_result_tuple_test.orders_pd[abu_result_tuple_test.orders_pd.result != 0]
    order_has_result.filter(regex='^buy(_deg_|_price_|_wave_|_jump)').head()

def run_load_test():
    global abu_result_tuple_test, order_has_result
    abu_result_tuple_test = abu.load_abu_result_tuple(n_folds=3, store_type=EStoreAbu.E_STORE_CUSTOM_NAME, 
                                                 custom_name='test_cn')
    AbuMetricsBase.show_general(*abu_result_tuple_test, only_show_returns=True).plot_max_draw_down()
    # 验证A股主裁是否称职
    # 选取有交易结果的数据order_has_result
    order_has_result = abu_result_tuple_test.orders_pd[abu_result_tuple_test.orders_pd.result != 0]
    order_has_result.filter(regex='^buy(_deg_|_price_|_wave_|_jump)').head()

def select_test(select):
    if select == 'run loop back':
        run_loop_back_test()
    else:
        run_load_test()

# _ = ipywidgets.interact_manual(select_test, select=['load test data', 'run loop back',])
run_load_test()
o_pos_base: 0.1
abupy.beta.atr.g_atr_pos_base: 0.0125
买入后卖出的交易数量:10834
买入后尚未卖出的交易数量:174
胜率:37.4285%
平均获利期望:6.6824%
平均亏损期望:-4.0840%
盈亏比:0.9930
策略收益: 1.7086%
基准收益: 8.8748%
策略年化收益: 0.4882%
基准年化收益: 2.5357%
策略买入成交比例:33.9299%
策略资金利用率比例:84.2858%
策略共执行882个交易日
最大回撤: 0.247707
最大回测启始时间:2018-01-24, 结束时间2019-01-31, 共回测1506094.184000

上面是没有启用机器人裁判的成绩。

以下启用机器人裁判,看看效果

In [9]:
# from warnings import simplefilter
# simplefilter(action='ignore', category=FutureWarning)
# simplefilter(action='ignore', category=ResourceWarning)

# abupy.env.g_data_cache_type = EDataCacheType.E_DATA_CACHE_CSV
# abupy.env.g_market_target = EMarketTargetType.E_MARKET_TARGET_CN
# abupy.env.g_data_fetch_mode = EMarketDataFetchMode.E_DATA_FETCH_FORCE_LOCAL

# 开启内置主裁
abupy.env.g_enable_ump_main_deg_block = True
# abupy.env.g_enable_ump_main_price_block = True

# 开启内置边裁
abupy.env.g_enable_ump_edge_deg_block = True
# abupy.env.g_enable_ump_edge_price_block = True

# 回测时需要开启特征生成,因为裁判开启需要生成特征做为输入
abupy.env.g_enable_ml_feature = True
# 回测时使用上一次切割好的测试集数据
abupy.env.g_enable_last_split_test = True


"""    """
feature.clear_user_feature()
# 10,30,50,90,120日走势拟合角度特征的AbuFeatureDegExtend,做为回测时的新的视角来录制比赛
feature.append_user_feature(AbuFeatureDegExtend)

# 打开使用用户自定义裁判开关
ump.manager.g_enable_user_ump = True
# 先clear一下
ump.manager.clear_user_ump()
# 把新的裁判AbuUmpMainDegExtend类名称使用append_user_ump添加到系统中
ump.manager.append_user_ump(AbuUmpEegeDegExtend)
# 把新的裁判AbuUmpMainDegExtend类名称使用append_user_ump添加到系统中
ump.manager.append_user_ump(AbuUmpMainDegExtend)


o_pos_base =0.1 #abupy.beta.atr.g_atr_pos_base
print('o_pos_base:', o_pos_base)
abupy.beta.atr.g_atr_pos_base =  o_pos_base / 8
print('abupy.beta.atr.g_atr_pos_base:' , abupy.beta.atr.g_atr_pos_base)


abu_result_tuple_test_ump = None
read_cash = 5000000 #500w资金

def run_loop_back_ump():
    global abu_result_tuple_test_ump, read_cash
    abu_result_tuple_test_ump, _ = abu.run_loop_back(read_cash,
                                            buy_factors,
                                            sell_factors,
#                                             choice_symbols = symbols,
                                            choice_symbols=None,
#                                             stock_picks= stock_pickers,
                                            start='2016-02-02', end='2019-09-12',
#                                             n_process_kl = 1,
#                                             n_process_pick= 1,
                                        )
    # 把运行的结果保存在本地,以便之后分析回测使用,保存回测结果数据代码如下所示
    abu.store_abu_result_tuple(abu_result_tuple_test_ump, n_folds=3, store_type=EStoreAbu.E_STORE_CUSTOM_NAME, 
                               custom_name='test_ump_cn')
    ABuProgress.clear_output()
    AbuMetricsBase.show_general(*abu_result_tuple_test_ump).plot_max_draw_down() #, returns_cmp=True

def run_load_ump():
    global abu_result_tuple_test_ump
    abu_result_tuple_test_ump = abu.load_abu_result_tuple(n_folds=3, store_type=EStoreAbu.E_STORE_CUSTOM_NAME, 
                                                 custom_name='test_ump_cn')
    AbuMetricsBase.show_general(*abu_result_tuple_test_ump).plot_max_draw_down() #, returns_cmp=True

def select_ump(select):
    if select == 'run loop back ump':
        run_loop_back_ump()
    else:
        run_load_ump()

# _ = ipywidgets.interact_manual(select_ump, select=['load test ump data','run loop back ump'])

# print("随便输出点什么表示已经执行过: ")
run_load_ump()
o_pos_base: 0.1
abupy.beta.atr.g_atr_pos_base: 0.0125
买入后卖出的交易数量:1027
买入后尚未卖出的交易数量:16
胜率:46.8354%
平均获利期望:7.2156%
平均亏损期望:-3.8613%
盈亏比:1.6230
策略收益: 26.7754%
基准收益: 8.8748%
策略年化收益: 7.6501%
基准年化收益: 2.5357%
策略买入成交比例:95.4938%
策略资金利用率比例:27.2689%
策略共执行882个交易日
alpha阿尔法:0.0607
beta贝塔:0.2493
Information信息比率:0.0144
策略Sharpe夏普比率: 0.9930
基准Sharpe夏普比率: 0.2286
策略波动率Volatility: 0.0709
基准波动率Volatility: 0.1689
最大回撤: 0.113420
最大回测启始时间:2017-11-13, 结束时间2018-10-23, 共回测666766.079000

盈亏比从 0.9930 提高到 1.6230,已经扭亏为盈了。

但是由于机器人裁判拦截了不少胜率不大的交易,交易机会少了,所以策略资金利用率比例:27.2689%, 下面强制提高单次买入的仓位试试,看能不能提高整体收益。

尝试强制提高仓位

abupy.beta.atr.g_atr_pos_base = o_pos_base /8 上面的单次买入仓位
abupy.beta.atr.g_atr_pos_base = o_pos_base /5 下面的单次买入仓位

In [10]:
# from warnings import simplefilter
# simplefilter(action='ignore', category=FutureWarning)
# simplefilter(action='ignore', category=ResourceWarning)

# 开启内置主裁
abupy.env.g_enable_ump_main_deg_block = True
# abupy.env.g_enable_ump_main_price_block = True

# 开启内置边裁
abupy.env.g_enable_ump_edge_deg_block = True
# abupy.env.g_enable_ump_edge_price_block = True

# 回测时需要开启特征生成,因为裁判开启需要生成特征做为输入
abupy.env.g_enable_ml_feature = True
# 回测时使用上一次切割好的测试集数据
abupy.env.g_enable_last_split_test = True


"""    """
feature.clear_user_feature()
# 10,30,50,90,120日走势拟合角度特征的AbuFeatureDegExtend,做为回测时的新的视角来录制比赛
feature.append_user_feature(AbuFeatureDegExtend)

# 打开使用用户自定义裁判开关
ump.manager.g_enable_user_ump = True
# 先clear一下
ump.manager.clear_user_ump()
# 把新的裁判AbuUmpMainDegExtend类名称使用append_user_ump添加到系统中
ump.manager.append_user_ump(AbuUmpEegeDegExtend)
# 把新的裁判AbuUmpMainDegExtend类名称使用append_user_ump添加到系统中
ump.manager.append_user_ump(AbuUmpMainDegExtend)

o_pos_base =0.1 #abupy.beta.atr.g_atr_pos_base
print('o_pos_base:', o_pos_base)
abupy.beta.atr.g_atr_pos_base =  o_pos_base /5
print('abupy.beta.atr.g_atr_pos_base:' , abupy.beta.atr.g_atr_pos_base)


abu_result_tuple_test_ump = None
read_cash = 5000000 #500w资金

def run_loop_back_ump():
    global abu_result_tuple_test_ump, read_cash
    abu_result_tuple_test_ump, _ = abu.run_loop_back(read_cash,
                                            buy_factors,
                                            sell_factors,
#                                             choice_symbols = symbols,
                                            choice_symbols=None,
#                                             stock_picks= stock_pickers,
                                            start='2016-02-02', end='2019-09-12',
                                             n_process_kl = 1,
                                            n_process_pick= 1,        
                                            )
    # 把运行的结果保存在本地,以便之后分析回测使用,保存回测结果数据代码如下所示
    abu.store_abu_result_tuple(abu_result_tuple_test_ump, n_folds=3, store_type=EStoreAbu.E_STORE_CUSTOM_NAME, 
                               custom_name='test_ump_cn_x25')
    ABuProgress.clear_output()
    AbuMetricsBase.show_general(*abu_result_tuple_test_ump).plot_max_draw_down() #, returns_cmp=True

def run_load_ump():
    global abu_result_tuple_test_ump
    abu_result_tuple_test_ump = abu.load_abu_result_tuple(n_folds=3, store_type=EStoreAbu.E_STORE_CUSTOM_NAME, 
                                                 custom_name='test_ump_cn_x25')
    AbuMetricsBase.show_general(*abu_result_tuple_test_ump).plot_max_draw_down() #, returns_cmp=True

def select_ump(select):
    if select == 'run loop back ump':
        run_loop_back_ump()
    else:
        run_load_ump()

# _ = ipywidgets.interact_manual(select_ump, select=['load test ump data','run loop back ump'])
# print("随便输出点什么表示已经执行过: ")

run_load_ump()
o_pos_base: 0.1
abupy.beta.atr.g_atr_pos_base: 0.02
买入后卖出的交易数量:1030
买入后尚未卖出的交易数量:16
胜率:46.7961%
平均获利期望:7.2137%
平均亏损期望:-3.8585%
盈亏比:1.6212
策略收益: 34.4394%
基准收益: 8.8748%
策略年化收益: 9.8398%
基准年化收益: 2.5357%
策略买入成交比例:85.6597%
策略资金利用率比例:39.1519%
策略共执行882个交易日
alpha阿尔法:0.0757
beta贝塔:0.3511
Information信息比率:0.0240
策略Sharpe夏普比率: 0.9292
基准Sharpe夏普比率: 0.2286
策略波动率Volatility: 0.0960
基准波动率Volatility: 0.1689
最大回撤: 0.170398
最大回测启始时间:2017-11-13, 结束时间2018-10-29, 共回测1041558.636000

额,资金利用率比例提高到了39.1519%, 年化收益也提高了不止2给点,但是最大回撤从0.11 升到 0.170398。。 可怕

分析裁判是否称职

就是分析裁判对交易的拦截是否正确。

根据阿布大师的原著《用Python做股票量化分析:量化交易之路》, 所有的信息都在一个 表中:

lcs lms lps lrs
分类簇中样本总数 分类簇中样本每笔交易平均获利 分类簇中样本交易获利总和 分类簇中样本失败率
x笔交易 平均每笔获利 获利总和 s失败率

主裁

In [ ]:
from warnings import simplefilter
simplefilter(action='ignore', category=FutureWarning)
simplefilter(action='ignore', category=ResourceWarning)

"""
通过一个一个迭代交易单,将交易单中的买入时刻特征传递给ump主裁决策器,让每一个主裁来决策是否进行拦截,
这样可以统计每一个主裁的拦截成功率,以及整体拦截率等
"""

order_has_result = abu_result_tuple_test.orders_pd[abu_result_tuple_test.orders_pd.result != 0]
#print(order_has_result)

# global ump_deg,  ump_mul, ump_price, ump_main_deg_extend,ump_jump, ump_wave
# ump_deg = AbuUmpMainDeg(predict=True)
# ump_jump = AbuUmpMainJump(predict=True)

def apply_ml_features_ump(order, predicter, progress, need_hit_cnt):
    if not isinstance(order.ml_features, dict):
        import ast
        # 低版本pandas dict对象取出来会成为str
        ml_features = ast.literal_eval(order.ml_features)
    else:
        ml_features = order.ml_features
    progress.show()
    # 将交易单中的买入时刻特征传递给ump主裁决策器,让每一个主裁来决策是否进行拦截
    return predicter.predict_kwargs(need_hit_cnt=need_hit_cnt, **ml_features)

def pararllel_func(ump_object, ump_name):
    with AbuMulPidProgress(len(order_has_result), '{} complete'.format(ump_name)) as progress:
        # 启动多进程进度条,对order_has_result进行apply
        ump_result = order_has_result.apply(apply_ml_features_ump, axis=1, args=(ump_object, progress, 2,))
    return ump_name, ump_result

# if sys.version_info > (3, 4, 0):
if False:
    # python3.4以上并行处理4个主裁,每一个主裁启动一个进程进行拦截决策
    parallel = Parallel(        n_jobs=6, verbose=0, pre_dispatch='2*n_jobs')
    
    out = parallel(delayed(pararllel_func)(ump_object, ump_name)
                                  for ump_object, ump_name in zip(
                                      [ump_deg, ump_mul, ump_price, ump_main_deg_extend, ump_jump, ump_wave], 
                                        ['ump_deg', 'ump_mul', 'ump_price', 'ump_main_deg_extend','ump_jump','ump_wave']))
else:
    # 3.4下由于子进程中pickle ump的内部类会找不到,所以暂时只使用一个进程一个一个的处理
    out = [pararllel_func(ump_object, ump_name) for ump_object, ump_name in zip(
                                    [ump_deg, ump_mul, ump_price, ump_main_deg_extend,ump_jump, ump_wave], 
                                    ['ump_deg', 'ump_mul', 'ump_price', 'ump_main_deg_extend','ump_jump','ump_wave'])]


# 将每一个进程中的裁判的拦截决策进行汇总
for sub_out in out:
    order_has_result[sub_out[0]] = sub_out[1]

print("随便输出点什么表示已经执行过: ")

""" 通过把所有主裁的决策进行相加, 如果有投票1的即会进行拦截,四个裁判整体拦截正确率统计 """
block_pd = order_has_result.filter(regex='^ump_*')
# 把所有主裁的决策进行相加
block_pd['sum_bk'] = block_pd.sum(axis=1)
block_pd['result'] = order_has_result['result']
# 有投票1的即会进行拦截
block_pd = block_pd[block_pd.sum_bk > 0]
print('6个裁判整体拦截正确率{:.2f}%'.format(block_pd[block_pd.result == -1].result.count() / block_pd.result.count() * 100))
block_pd.tail()


""" 下面统计每一个主裁的拦截正确率"""
display(HTML(' <b> 下面统计每一个主裁的拦截正确率 </b> '))

from sklearn import metrics
def sub_ump_show(block_name):
    sub_block_pd = block_pd[(block_pd[block_name] == 1)]
    # 如果失败就正确 -1->1 1->0
    sub_block_pd.result = np.where(sub_block_pd.result == -1, 1, 0)
    return metrics.accuracy_score(sub_block_pd[block_name], sub_block_pd.result) * 100, sub_block_pd.result.count()

print('角度裁判拦截正确率{:.2f}%, 拦截交易数量{}'.format(*sub_ump_show('ump_deg')))
print('角度扩展裁判拦拦截正确率{:.2f}%, 拦截交易数量{}'.format(*sub_ump_show('ump_main_deg_extend')))
print('价格裁判拦截正确率{:.2f}%, 拦截交易数量{}'.format(*sub_ump_show('ump_price')))
print('单混裁判拦截正确率{:.2f}%, 拦截交易数量{}'.format(*sub_ump_show('ump_mul')))
print('跳空缺口裁判拦截正确率{:.2f}%, 拦截交易数量{}'.format(*sub_ump_show('ump_jump')))
print('波动裁判拦截正确率{:.2f}%, 拦截交易数量{}'.format(*sub_ump_show('ump_wave')))

上面这个因为已经执行了超过12小时还没完成,就不那么好奇,不验证了。

但是下面边裁是真实的执行结果(边裁的称职验证要比主裁快很多)

边裁:

In [11]:
""" 验证边裁是否称职  """

# 选取有交易结果的数据order_has_result
# order_has_result = abu_result_tuple_test.orders_pd[abu_result_tuple_test.orders_pd.result != 0]

def apply_ml_features_edge(order, predicter, progress):
    if not isinstance(order.ml_features, dict):
        import ast
        # 低版本pandas dict对象取出来会成为str
        ml_features = ast.literal_eval(order.ml_features)
    else:
        ml_features = order.ml_features
    # 边裁进行裁决
    progress.show()
    # 将交易单中的买入时刻特征传递给ump边裁决策器,让每一个边裁来决策是否进行拦截
    edge = predicter.predict(**ml_features)
    return edge.value


def edge_pararllel_func(edge, edge_name):
    with AbuMulPidProgress(len(order_has_result), '{} complete'.format(edge_name)) as progress:
        # # 启动多进程进度条,对order_has_result进行apply
        edge_result = order_has_result.apply(apply_ml_features_edge, axis=1, args=(edge, progress,))
    return edge_name, edge_result

# if sys.version_info > (3, 4, 0): # 这里经常出问题,干脆单线程好了
if False:
    # python3.4以上并行处理4个边裁的决策,每一个边裁启动一个进程进行拦截决策
    parallel = Parallel( n_jobs=6, verbose=0, pre_dispatch='2*n_jobs')
        
    out = parallel(delayed(edge_pararllel_func)(edge, edge_name)
                                  for edge, edge_name in zip(
                                      [edge_deg, edge_price, edge_mul, edge_deg_extend, edge_wave, edge_full], 
                                        ['edge_deg', 'edge_price', 'edge_mul', 'edge_deg_extend','edge_wave','edge_full']))
else:
    # 3.4下由于子进程中pickle ump的内部类会找不到,所以暂时只使用一个进程一个一个的处理
    out = [edge_pararllel_func(edge, edge_name) for edge, edge_name in zip(
                                            [edge_deg, edge_price, edge_mul, edge_deg_extend, edge_wave, edge_full], 
                                            ['edge_deg', 'edge_price', 'edge_mul', 'edge_deg_extend','edge_wave','edge_full'])]
    
# 将每一个进程中的裁判的拦截决策进行汇总
for sub_out in out:
    order_has_result[sub_out[0]] = sub_out[1]
    
print("随便输出点什么表示已经执行过: ")

block_pd = order_has_result.filter(regex='^edge_*')
"""
    由于predict返回的结果中1代表win top
    但是我们只需要知道loss_top,所以只保留-1, 其他1转换为0。
"""
block_pd['edge_block'] = \
    np.where(np.min(block_pd, axis=1) == -1, -1, 0)

# 拿出真实的交易结果
block_pd['result'] = order_has_result['result']
# 拿出-1的结果,即判定loss_top的
block_pd = block_pd[block_pd.edge_block == -1]


print('x个裁判整体拦截正确率{:.2f}%'.format(block_pd[block_pd.result == -1].result.count() / 
                                  block_pd.result.count() * 100))

print('x个边裁拦截交易总数{}, 拦截率{:.2f}%'.format(
    block_pd.shape[0],
    block_pd.shape[0] / order_has_result.shape[0] * 100))
block_pd.head()


"""  单个 :"""

from sklearn import metrics
def sub_edge_show(edge_name):
    sub_edge_block_pd = order_has_result[(order_has_result[edge_name] == -1)]
    return metrics.accuracy_score(sub_edge_block_pd[edge_name], sub_edge_block_pd.result) * 100, sub_edge_block_pd.shape[0]

print('\r\n角度边裁拦截正确率{0:.2f}%, 拦截交易数量{1:}'.format(*sub_edge_show('edge_deg')))
print('角度扩展边裁拦截正确率{0:.2f}%, 拦截交易数量{1:}'.format(*sub_edge_show('edge_deg_extend')))
print('单混边裁拦截正确率{0:.2f}%, 拦截交易数量{1:}'.format(*sub_edge_show('edge_mul')))
print('价格边裁拦截正确率{0:.2f}%, 拦截交易数量{1:}'.format(*sub_edge_show('edge_price')))
print('Full边裁拦截正确率{0:.2f}%, 拦截交易数量{1:}'.format(*sub_edge_show('edge_full')))
print('波动边裁拦截正确率{0:.2f}%, 拦截交易数量{1:}'.format(*sub_edge_show('edge_wave')))
随便输出点什么表示已经执行过: 
x个裁判整体拦截正确率67.41%
x个边裁拦截交易总数6152, 拦截率56.78%

角度边裁拦截正确率68.22%, 拦截交易数量1485
角度扩展边裁拦截正确率72.58%, 拦截交易数量1882
单混边裁拦截正确率71.04%, 拦截交易数量1861
价格边裁拦截正确率66.48%, 拦截交易数量1599
Full边裁拦截正确率73.48%, 拦截交易数量973
波动边裁拦截正确率67.90%, 拦截交易数量2134

裁判称职与否总结

由于训练用的数据过少(2016-2019 3年行情 * 大概 1000只股票), 裁判还不算很厉害,有些正确率还不到60%。

In [ ]:
# 好奇 看看裁判从哪些角度分析交易的(有哪些特征)
orders_pd_train = orders_pd_train_cn
print(orders_pd_train.columns)

orders_pd_train[0:6]