【干货分享】从零开始学量化:16二八轮动策略

  1. 策略原理:
    (1)获取指数000300、000905前一日收盘价以及前20日数据;
    (2)计算前20日变动;
    (3)获取ETF300(510300)及ETF500(510500)的持仓数据;
    (4)
    a. 如果000300趋势下降且有持仓,则卖出ETF300;
    b. 如果000905趋势下降且有持仓,则卖出ETF500;
    c. 如果300指数增幅大于500指数增幅,且300指数增幅大于0,且ETF300及ETF500无持仓,则买入ETF300;
    d. 如果300指数增幅小于500指数增幅,且500指数增幅大于0,且ETF300及ETF500无持仓,则买入ETF500;

  2. 代码解读:
    2.1 strategy.ini`

[strategy]
username=
password=
mode=4
td_addr=localhost:8001
strategy_id=
subscribe_symbols=SHSE.000300.bar.daily,SHSE.000905.bar.daily
[backtest]
start_time = 2015-05-01 09:00:00
end_time = 2015-5-31 16:00:00
;策略初始资金
initial_cash=1000000

;委托量成交比率,默认=1(每个委托100%成交)
transaction_ratio=1

;手续费率,默认=0(不计算手续费)
commission_ratio=0

;滑点比率,默认=0(无滑点)
slippage_ratio=0

[para]
#bar_type=60
window_size=20

market_exchange_a=SHSE
market_secid_a=000300

market_exchange_b=SHSE
market_secid_b=000905


trade_exchange_a=SHSE
trade_secid_a=510300
trade_unit_a=100

trade_exchange_b=SHSE
trade_secid_b=510500
trade_unit_b=100

#hour=14
#minute=53

#sigma=2.34

##############################################################
# logger settings
##############################################################
[loggers]
keys=root

[logger_root]
level=DEBUG
handlers=console,file

[handlers]
keys=console,file

[handler_file]
class=handlers.RotatingFileHandler
;args=('strategy_sa.log','a','maxBytes=10000','backupCount=5')
args=('strategy_sa.log','a',10000,5)
formatter=simple

[handler_console]
class=StreamHandler
args = (sys.stdout,)
formatter=simple

[formatters]
keys = simple

[formatter_simple]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
datefmt=

2.2 strategy.py

# -*- coding: utf-8 -*-
"""
Created on Tue Jan 24 13:32:56 2017

@author: Lenovo
"""

#!/usr/bin/env python
# encoding: utf-8

from gmsdk.api import StrategyBase
import numpy as np
from collections import deque
#from gmsdk import *
#import arrow
#from math import log

eps = 1e-6

class StatArb(StrategyBase):
    '''
        statistics arbitrage demo
    '''
    def __init__(self, *args, **kwargs):
        #import pdb; pdb.set_trace()
        super( StatArb, self).__init__(*args, **kwargs)
        # 策略初始化工作在这里写,从外部读取静态数据,读取策略配置参数等工作,只在策略启动初始化时执行一次。

        # 从配置文件中读取配置参数
        self.market_exchange_a = self.config.get('para', 'market_exchange_a') or 'SHSE'
        self.market_secid_a = self.config.get('para', 'market_secid_a') or '000300'
        self.market_symbol_a = ".".join([self.market_exchange_a, self.market_secid_a])
      

        self.market_exchange_b = self.config.get('para', 'market_exchange_b') or 'SHSE'
        self.market_secid_b = self.config.get('para', 'market_secid_b') or '000905'
        self.market_symbol_b = ".".join([self.market_exchange_b, self.market_secid_b])
         
        
        self.trade_exchange_a = self.config.get('para', 'trade_exchange_a') or 'SHSE'
        self.trade_secid_a = self.config.get('para', 'trade_secid_a') or '510300'
        self.trade_symbol_a = ".".join([self.trade_exchange_a, self.trade_secid_a])
      

        self.trade_exchange_b = self.config.get('para', 'trade_exchange_b') or 'SHSE'
        self.trade_secid_b = self.config.get('para', 'trade_secid_b') or '510500'
        self.trade_symbol_b = ".".join([self.trade_exchange_b, self.trade_secid_b])
     

       # self.hour = self.config.get('para','hour') or '14'
       # self.minute = self.config.get('para','minute') or '53'

        self.window_size = self.config.getint('para','window_size') or 20

        self.trade_unit_a = self.config.getint('para','trade_unit_a') or 100
        self.trade_unit_b = self.config.getint('para','trade_unit_b') or 100
    
                
        self.closes_a_buffer = deque(maxlen=self.window_size)
        self.closes_b_buffer = deque(maxlen=self.window_size)
        
        last_closes_a = [bar.close for bar in self.get_last_n_dailybars(self.market_symbol_a,self.window_size,end_time=self.start_time)]
        last_closes_a.reverse()
       
        last_closes_b = [bar.close for bar in self.get_last_n_dailybars(self.market_symbol_b,self.window_size,end_time=self.start_time)]
        last_closes_b.reverse()
      
        self.closes_a_buffer.extend(last_closes_a)
        self.closes_b_buffer.extend(last_closes_b)

    def on_bar(self, bar):
        if bar.sec_id == self.market_secid_a:
            self.closes_a_buffer.append(bar.close)
            self.last_price_a = bar.close
        elif bar.sec_id == self.market_secid_b:
            self.closes_b_buffer.append(bar.close)
            self.last_price_b = bar.close
       # t=arrow.get(bar.utc_time)
       # if t.hour == self.hour and t.minute == self.minute:
        self.algo_action()
    def open_side_a(self):
        self.open_long(self.trade_exchange_a, self.trade_secid_a, self.last_price_a, self.trade_unit_a)
        #self.open_long(self.trade_exchange_a, self.trade_secid_a, 0, self.trade_unit_a)
     
    def open_side_b(self):     
        self.open_long(self.trade_exchange_b, self.trade_secid_b, self.last_price_b, self.trade_unit_b)
       # self.open_long(self.trade_exchange_b, self.trade_secid_b, 0, self.trade_unit_b)

    def close_side_a(self):
        Position_a = self.get_position(self.trade_exchange_a,self.trade_secid_a,1)
        self.close_long(self.trade_exchange_a, self.trade_secid_a, self.last_price_a, Position_a.volume)
       # self.close_long(self.trade_exchange_a, self.trade_secid_a, 0, Position_a.volume)
        
    def close_side_b(self):
        Position_b = self.get_position(self.trade_exchange_b,self.trade_secid_b,1)
        self.close_long(self.trade_exchange_b, self.trade_secid_b, self.last_price_b, Position_b.volume)
        #self.close_long(self.trade_exchange_b, self.trade_secid_b, 0, Position_b.volume)

    def algo_action(self):
        close_a = np.asarray(self.closes_a_buffer)
        close_b = np.asarray(self.closes_b_buffer)
        Change_a = (close_a[self.window_size-1]-close_a[0])/close_a[0]
        Change_b = (close_b[self.window_size-1]-close_b[0])/close_b[0]
        Position_a = self.get_position(self.trade_exchange_a,self.trade_secid_a,1)
        Position_b = self.get_position(self.trade_exchange_b,self.trade_secid_b,1)
        av = Position_a.volume if Position_a else 0
        bv = Position_b.volume if Position_b else 0
        diff = Change_a - Change_b    
        if diff > eps and Change_a > 0 and av == 0 and bv == 0:
            self.open_side_a()
        elif diff < eps and Change_b > 0 and av == 0 and bv == 0:
            self.open_side_b()
        elif Change_a < 0 and av > 0:
            self.close_side_a()
        elif Change_b < 0 and bv > 0:
            self.close_side_b()
    
if __name__ == '__main__':
    #import pdb; pdb.set_trace()
    dm = StatArb(config_file='strategy.ini')
    ret = dm.run()
    print ("Statistics Arbitrage: ", ret, dm.get_strerror(ret))
1赞

顶顶顶~好贴莫沉

有什么问题一起探讨研究呀

666666666666666666666666666666
有一个小问题,第一天的收盘价会被压入deque两次