Back to Abu

import warnings;

ipython/第八章-量化系统——开发.ipynb

1.1012.7 KB
Original Source
python
from __future__ import print_function
from __future__ import division

import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline
sns.set_context(rc={'figure.figsize': (14, 7) } )
figzize_me = figsize =(14, 7)
# import warnings; 
# warnings.filterwarnings('ignore')

import os
import sys
# 使用insert 0即只使用github,避免交叉使用了pip安装的abupy,导致的版本不一致问题
sys.path.insert(0, os.path.abspath('../'))
import abupy
# 使用沙盒数据,目的是和书中一样的数据环境
abupy.env.enable_example_env_ipython()

第8章 量化系统-开发

abu量化系统github地址 (您的star是我的动力!)

abu量化文档教程ipython notebook

8.1 abu量化系统择时

8.1.1 买入因子的实现

python
from abupy import AbuFactorBuyBreak
from abupy import AbuBenchmark
# buy_factors 60日向上突破,42日向上突破两个因子
buy_factors = [{'xd': 60, 'class': AbuFactorBuyBreak}, 
               {'xd': 42, 'class': AbuFactorBuyBreak}]
benchmark = AbuBenchmark()
python
from abupy import AbuPickTimeWorker 
from abupy import AbuCapital
from abupy import AbuKLManager

capital = AbuCapital(1000000, benchmark)
kl_pd_manager = AbuKLManager(benchmark, capital)
# 获取TSLA的交易数据
kl_pd = kl_pd_manager.get_pick_time_kl_pd('usTSLA')
abu_worker = AbuPickTimeWorker(capital, kl_pd, benchmark, buy_factors, None)
%time abu_worker.fit()
python
from abupy import ABuTradeProxy
orders_pd, action_pd, _ = ABuTradeProxy.trade_summary(abu_worker.orders, kl_pd, draw=True)
python
from abupy import ABuTradeExecute
ABuTradeExecute.apply_action_to_capital(capital, action_pd, kl_pd_manager)
capital.capital_pd.capital_blance.plot()

8.1.2 卖出因子的实现

python
from abupy import AbuFactorSellBreak
# 使用120天向下突破为卖出信号
sell_factor1 = {'xd': 120, 'class': AbuFactorSellBreak}
python
from abupy import ABuPickTimeExecute
# 只使用120天向下突破为卖出因子
sell_factors = [sell_factor1]
capital = AbuCapital(1000000, benchmark)
orders_pd, action_pd, _ = ABuPickTimeExecute.do_symbols_with_same_factors(
                          ['usTSLA'], benchmark, buy_factors, sell_factors, capital, show=True)
python
from abupy import AbuFactorAtrNStop
# 趋势跟踪策略止盈要大于止损设置值,这里0.5,3.0
sell_factor2 = {'stop_loss_n':0.5, 'stop_win_n':3.0, 'class': AbuFactorAtrNStop}
# 两个卖出因子策略并行同时生效
sell_factors = [sell_factor1, sell_factor2]
capital = AbuCapital(1000000, benchmark)
orders_pd, action_pd, _ = ABuPickTimeExecute.do_symbols_with_same_factors(
                          ['usTSLA'], benchmark, buy_factors, sell_factors, capital, show=True)
python
from abupy import AbuFactorPreAtrNStop
# 暴跌止损卖出因子形成dict
sell_factor3 =  {'class': AbuFactorPreAtrNStop, 'pre_atr_n':1.0}
# 三个卖出因子同时生效,组成sell_factors
sell_factors = [sell_factor1, sell_factor2, sell_factor3]
capital = AbuCapital(1000000, benchmark)
orders_pd, action_pd, _ = ABuPickTimeExecute.do_symbols_with_same_factors(
                          ['usTSLA'], benchmark, buy_factors, sell_factors, capital, show=True)
python
from abupy import AbuFactorCloseAtrNStop
# 保护止盈卖出因子组成dict
sell_factor4 = {'class': AbuFactorCloseAtrNStop, 'close_atr_n':1.5}
# 四个卖出因子同时并行生效
sell_factors = [sell_factor1, sell_factor2, sell_factor3, sell_factor4]
capital = AbuCapital(1000000, benchmark)
orders_pd, action_pd, _ = ABuPickTimeExecute.do_symbols_with_same_factors(
                          ['usTSLA'], benchmark, buy_factors, sell_factors, capital, show=True)

8.1.3 滑点买入卖出价格确定及策略实现

python
from abupy import AbuSlippageBuyBase

# 修改g_open_down_rate的值为0.02
g_open_down_rate = 0.02

class AbuSlippageBuyMean2(AbuSlippageBuyBase):
    def fit_price(self):
        if (self.kl_pd_buy.open / self.kl_pd_buy.pre_close) < (
            1 - g_open_down_rate):
            # 开盘下跌K_OPEN_DOWN_RATE以上,单子失效
            print(self.factor_name + 'open down threshold')
            return np.inf
        # 买入价格为当天均价
        self.buy_price = np.mean(
            [self.kl_pd_buy['high'], self.kl_pd_buy['low']])
        return self.buy_price
python
# 只针对60使用AbuSlippageBuyMean2
buy_factors2 = [{'slippage': AbuSlippageBuyMean2, 'xd': 60,
                 'class': AbuFactorBuyBreak},
                {'xd': 42, 'class': AbuFactorBuyBreak}]

sell_factors = [sell_factor1, sell_factor2, sell_factor3,
                sell_factor4]
capital = AbuCapital(1000000, benchmark)
orders_pd, action_pd, _ = \
    ABuPickTimeExecute.do_symbols_with_same_factors(['usTSLA'],
                                                    benchmark,
                                                    buy_factors2,
                                                    sell_factors,
                                                    capital,
                                                    show=True)

8.1.4 对多支股票进行择时

python
# 我们假定choice_symbols是我们选股模块的结果,
choice_symbols = ['usTSLA', 'usNOAH', 'usSFUN', 'usBIDU', 'usAAPL', 'usGOOG', 'usWUBA', 'usVIPS']
capital = AbuCapital(1000000, benchmark)
orders_pd, action_pd, all_fit_symbols_cnt = ABuPickTimeExecute.do_symbols_with_same_factors(choice_symbols, benchmark, buy_factors, sell_factors, capital, show=False)
python
orders_pd[:10].filter(['symbol', 'buy_price', 'buy_cnt', 'buy_factor', 'buy_pos', 
                       'sell_date', 'sell_type_extra', 'sell_type', 'profit'])
python
action_pd[:10]
python
from abupy import AbuMetricsBase 
metrics = AbuMetricsBase(orders_pd, action_pd, capital, benchmark)
metrics.fit_metrics()
metrics.plot_returns_cmp(only_show_returns=True)

8.1.5 自定义仓位管理策略的实现

python
metrics.gains_mean, -metrics.losses_mean
python
from abupy import AbuKellyPosition
# 42d使用AbuKellyPosition,60d仍然使用默认仓位管理类
buy_factors2 = [{'xd': 60, 'class': AbuFactorBuyBreak},
                {'xd': 42, 'position': {'class': AbuKellyPosition, 'win_rate': metrics.win_rate, 
                                        'gains_mean': metrics.gains_mean, 'losses_mean': -metrics.losses_mean},
                 'class': AbuFactorBuyBreak}]
capital = AbuCapital(1000000, benchmark)
orders_pd, action_pd, all_fit_symbols_cnt = ABuPickTimeExecute.do_symbols_with_same_factors(choice_symbols, benchmark, buy_factors2, sell_factors, capital, show=False)
python
orders_pd[:10].filter(['symbol', 'buy_cnt', 'buy_factor', 'buy_pos'])

8.1.6 多支股票使用不同的因子进行择时

python
# 选定noah和sfun
target_symbols = ['usSFUN', 'usNOAH']
# 针对sfun只使用42d向上突破作为买入因子
buy_factors_sfun = [{'xd': 42, 'class': AbuFactorBuyBreak}]
# 针对sfun只使用60d向下突破作为卖出因子
sell_factors_sfun = [{'xd': 60, 'class': AbuFactorSellBreak}]

# 针对noah只使用21d向上突破作为买入因子
buy_factors_noah = [{'xd': 21, 'class': AbuFactorBuyBreak}]
# 针对noah只使用42d向下突破作为卖出因子
sell_factors_noah = [{'xd': 42, 'class': AbuFactorSellBreak}]

factor_dict = dict()
# 构建SFUN独立的buy_factors,sell_factors的dict
factor_dict['usSFUN'] = {'buy_factors':buy_factors_sfun, 'sell_factors':sell_factors_sfun}
# 构建NOAH独立的buy_factors,sell_factors的dict
factor_dict['usNOAH'] = {'buy_factors':buy_factors_noah, 'sell_factors':sell_factors_noah}
# 初始化资金
capital = AbuCapital(1000000, benchmark)
# 使用do_symbols_with_diff_factors执行
orders_pd, action_pd, all_fit_symbols = ABuPickTimeExecute.do_symbols_with_diff_factors(
                                        target_symbols, benchmark, factor_dict, capital)
python
pd.crosstab(orders_pd.buy_factor, orders_pd.symbol)

8.1.7 使用并行来提升择时运行效率

python
# 要关闭沙盒数据环境,因为沙盒里就那几个股票的历史数据, 下面要随机做300个股票
abupy.env.disable_example_env_ipython()

# 关闭沙盒后,首先基准要从非沙盒环境换取,否则数据对不齐,无法正常运行
benchmark = AbuBenchmark()
capital = AbuCapital(1000000, benchmark)
python
from abupy import ABuMarket
# 当传入choice_symbols为None时代表对整个市场的所有股票进行回测
choice_symbols = None
# 顺序获取市场后50支股票
choice_symbols = ABuMarket.all_symbol()[-50:]
# 随机获取50支股票
choice_symbols = ABuMarket.choice_symbols(50)
python
from abupy import AbuPickTimeMaster
capital = AbuCapital(1000000, benchmark)
orders_pd, action_pd, _ = AbuPickTimeMaster.do_symbols_with_same_factors_process(
                          choice_symbols, benchmark, buy_factors, sell_factors, 
                          capital)
python
metrics = AbuMetricsBase(orders_pd, action_pd, capital, benchmark)
metrics.fit_metrics()
metrics.plot_returns_cmp(only_show_returns=True)

8.2 abu量化系统选股

8.2.1 选股因子的实现

python
# 继续使用沙盒数据环境
abupy.env.enable_example_env_ipython()

# 开启沙盒后,基准也要从沙盒环境取,否则数据对不齐,无法正常运行
benchmark = AbuBenchmark()
capital = AbuCapital(1000000, benchmark)
kl_pd_manager = AbuKLManager(benchmark, capital)
python
from abupy import AbuPickRegressAngMinMax
from abupy import AbuPickStockWorker
# 选股条件threshold_ang_min=0.0, 即要求股票走势为向上上升趋势
stock_pickers = [{'class': AbuPickRegressAngMinMax, 
                'threshold_ang_min':0.0, 'reversed':False}]

# 从这几个股票里进行选股,只是为了演示方便,一般的选股都会是数量比较多的情况比如全市场股票
choice_symbols = ['usNOAH', 'usSFUN', 'usBIDU', 'usAAPL', 'usGOOG', 'usTSLA', 'usWUBA', 'usVIPS']

capital = AbuCapital(1000000, benchmark)
kl_pd_manager = AbuKLManager(benchmark, capital)
stock_pick = AbuPickStockWorker(capital, benchmark, kl_pd_manager, choice_symbols=choice_symbols, stock_pickers=stock_pickers)
stock_pick.fit()
stock_pick.choice_symbols

注意选股结果会与书中的结果不一致,因为要控制沙盒数据体积小于50mb, 所以沙盒数据有些symbol只有两年多一点,与原始环境不一致。

python
from abupy import ABuRegUtil
# 从kl_pd_manager缓存中获取选股走势数据,注意get_pick_stock_kl_pd为选股数据,get_pick_time_kl_pd为择时
kl_pd_noah = kl_pd_manager.get_pick_stock_kl_pd('usNOAH')
# 绘制并计算角度
deg = ABuRegUtil.calc_regress_deg(kl_pd_noah.close)
print('noah 选股周期内角度={}'.format(round(deg, 3)))

ABuPickStockExecute

python
from abupy import ABuPickStockExecute
stock_pickers = [{'class': AbuPickRegressAngMinMax, 
                 'threshold_ang_min':0.0, 'threshold_ang_max':10.0, 'reversed':False}]

ABuPickStockExecute.do_pick_stock_work(choice_symbols, benchmark, capital, stock_pickers)
python
kl_pd_sfun = kl_pd_manager.get_pick_stock_kl_pd('usSFUN')
print('sfun 选股周期内角度={}'.format(round(ABuRegUtil.calc_regress_deg(kl_pd_sfun.close), 3)))

reversed

python
# 和上面的代码唯一的区别就是reversed=True
stock_pickers = [{'class': AbuPickRegressAngMinMax, 
                 'threshold_ang_min':0.0, 'threshold_ang_max':10.0, 'reversed':True}]
ABuPickStockExecute.do_pick_stock_work(choice_symbols, benchmark, capital, stock_pickers)

8.2.2 多个选股因子并行执行

python
from abupy import AbuPickStockPriceMinMax

stock_pickers = [{'class': AbuPickRegressAngMinMax, 
                 'threshold_ang_min':0.0, 'reversed':False}, 
                 {'class': AbuPickStockPriceMinMax, 'threshold_price_min':50.0,
                 'reversed':False}]
ABuPickStockExecute.do_pick_stock_work(choice_symbols, benchmark, capital, stock_pickers)

8.2.3 使用并行来提升回测运行效率

python
# 继续关闭沙盒环境,因为下面要choice_symbols
abupy.env.disable_example_env_ipython()

# 关闭沙盒后,首先基准要从非沙盒环境换取,否则数据对不齐,无法正常运行
benchmark = AbuBenchmark()
capital = AbuCapital(1000000, benchmark)
kl_pd_manager = AbuKLManager(benchmark, capital)

from abupy import ABuMarket, AbuPickStockMaster
# 首先随抽取50支股票
choice_symbols = ABuMarket.choice_symbols(50)
python
# 股价在15-50之间
stock_pickers = [{'class': AbuPickStockPriceMinMax, 'threshold_price_min':15.0,
                'threshold_price_max':50.0, 'reversed':False}]
%time cs = AbuPickStockMaster.do_pick_stock_with_process(capital, benchmark, stock_pickers, choice_symbols)
python
cs