多策略, 多品种回测示例


In [1]:
from collections import defaultdict

import OnePy as op
from OnePy.custom_module.cleaner_talib import Talib
from OnePy.custom_module.cleaner_sma import SMA

class SmaStrategy(op.StrategyBase):

    def __init__(self):

        super().__init__()
        self.sma1 = SMA(3, 40).calculate
        self.sma2 = SMA(5, 40).calculate

    def handle_bar(self):
        for ticker in self.env.tickers:

            if self.sma1(ticker) > self.sma2(ticker):

                self.buy(100, ticker, takeprofit=15,
                         stoploss=100)
            else:
                self.sell(20, ticker)

class BBANDS(op.StrategyBase):

    def __init__(self):
        super().__init__()
        self.sma = Talib(ind='sma', frequency='D',
                         params=dict(timeperiod=20)).calculate

        self.bbands = Talib(ind='BBANDS', frequency='D',
                            params=dict(timeperiod=20,
                                        nbdevup=2,
                                        nbdevdn=2,
                                        matype=0),
                            buffer_day=30).calculate

        self.switch_long = defaultdict(bool)
        self.switch_short = defaultdict(bool)

        self.params = dict(
            position=100,
            takeprofit_pct=0.01,
        )
        self.finished = defaultdict(list)

    def handle_bar(self):
        position = self.params['position']
        takeprofit_pct = self.params['takeprofit_pct']

        for ticker in self.env.tickers:
            upperband = self.bbands(ticker)['upperband']
            middleband = self.bbands(ticker)['middleband']
            lowerband = self.bbands(ticker)['lowerband']
            cur_price = self.cur_price(ticker)
            sma = self.sma(ticker)

            if cur_price > upperband > sma:
                if ticker not in self.finished['long']:
                    self.buy(position, ticker, price=cur_price -
                             0.01, trailingstop_pct=0.05)
                    self.finished['long'].append(ticker)

            elif cur_price < lowerband < sma:
                if ticker not in self.finished['short']:
                    self.short(position, ticker, price=cur_price +
                               0.01, trailingstop_pct=0.05)
                    self.finished['short'].append(ticker)

In [2]:
TICKER_LIST = ['000001', '000002'] # 多品种
INITIAL_CASH = 20000
FREQUENCY = 'D'
START, END = '2012-08-07', '2018-08-07'

go = op.backtest.stock(TICKER_LIST, FREQUENCY, INITIAL_CASH, START, END)

# 导入多个策略
SmaStrategy() 
BBANDS() 

go.output.show_setting() # 检查是否导入成功


+--------------------+
|readers_1  |  000001|
|readers_2  |  000002|
+--------------------+
+----------------------+
|cleaners_1  |    SMA_1|
|cleaners_2  |    SMA_2|
|cleaners_3  |  Talib_3|
|cleaners_4  |  Talib_4|
+----------------------+
+--------------------------+
|strategy_1  |  SmaStrategy|
|strategy_2  |       BBANDS|
+--------------------------+
+-------------------------+
|brokers_1  |  StockBroker|
+-------------------------+
+-----------------------------------------------+
|risk_managers_1  |  StockLimitFilterRiskManager|
+-----------------------------------------------+
+-----------------------------+
|recorders_1  |  StockRecorder|
+-----------------------------+

In [3]:
go.sunny()


正在初始化OnePy
Retry Talib_3, perfect buffer_day = 29
Retry Talib_3, perfect buffer_day = 27
Retry Talib_3, perfect buffer_day = 25
Retry Talib_3, perfect buffer_day = 23
Retry Talib_3, perfect buffer_day = 21
Retry Talib_3, perfect buffer_day = 19
Retry Talib_3, perfect buffer_day = 17
Retry Talib_3, perfect buffer_day = 15
Retry Talib_3, perfect buffer_day = 13
Retry Talib_3, perfect buffer_day = 11
Retry Talib_3, perfect buffer_day = 9
Retry Talib_3, perfect buffer_day = 7
=============== OnePy初始化成功! ===============
开始寻找OnePiece之旅~~~
Cash is not enough for trading!
Cash is not enough for trading!

+--------------------------------+
|Fromdate           |  2012-08-07|
|Todate             |  2018-08-07|
|Initial_Value      |   $20000.00|
|Final_Value        |   $18241.37|
|Total_Return       |     -8.793%|
|Max_Drawdown       |     12.887%|
|Max_Duration       |    916 days|
|Max_Drawdown_Date  |  2018-07-20|
|Sharpe_Ratio       |       -0.26|
+--------------------------------+

In [4]:
go.output.summary2()


+---------------------------------------+
|Start_date                |  2012-08-07|
|End_date                  |  2018-08-07|
|Initial_balance           |   $20000.00|
|End_balance               |   $18241.37|
|Total_return              |      -8.79%|
|Total_net_pnl             |   -$1758.63|
|Total_commission          |    $2527.56|
|Total_trading_days        |   1566 days|
|Max_drawdown              |      12.89%|
|Max_drawdown_date         |  2018-07-20|
|Max_duration_in_drawdown  |    916 days|
|Max_margin                |      $69.57|
|Max_win_holding_pnl       |     $104.54|
|Max_loss_holding_pnl      |    -$661.70|
|Sharpe_ratio              |       -0.26|
|Sortino_ratio             |       -0.33|
|Number_of_trades          |        2211|
|Number_of_daily_trades    |        1.41|
|Number_of_profit_days     |   1566 days|
|Number_of_loss_days       |      0 days|
|Avg_daily_pnl             |      -$1.12|
|Avg_daily_commission      |       $1.61|
|Avg_daily_return          |      -0.01%|
|Avg_daily_std             |      -0.01%|
|Annual_compound_return    |      -1.47%|
|Annual_average_return     |      -1.48%|
|Annual_std                |      -0.08%|
|Annual_pnl                |    -$283.00|
+---------------------------------------+
                                All Trades  Long Trades Short Trades
Total_number_of_trades                2211         2209            2
Total_net_pnl                    -$1758.63    -$1742.93      -$15.70
Ratio_avg_win_avg_loss                0.96         0.96         0.43
Profit_factor                         1.05         1.05         0.43
Percent_profitable                  52.01%       52.01%       50.00%
Number_of_winning_trades              1150         1149            1
Number_of_losing_trades               1057         1056            1
Max_holding_period             199.62 days  199.62 days   20.62 days
Max_consecutive_winning_trade           30           30            1
Max_consecutive_losing_trade            32           32            0
Largest_winning_trade               $15.00       $15.00       $10.51
Largest_losing_trade              -$100.00     -$100.00      -$24.35
Gross_profit                     $16623.41    $16612.90       $10.51
Gross_loss                      -$15854.48   -$15830.14      -$24.35
Gross_commission                  $2527.56     $2525.69        $1.87
Expectancy_adjusted_ratio             0.02         0.02        -0.28
Expectancy                           $0.32        $0.33       -$6.92
Avg_winning_trade                   $14.46       $14.46       $10.51
Avg_net_pnl_per_trade               -$0.80       -$0.79       -$7.85
Avg_losing_trade                   -$15.00      -$14.99      -$24.35
Avg_holding_period              13.08 days   13.08 days   11.12 days

In [ ]: