楼主: jinlu310
7705 21

[交易策略] 对冲基金与量化Alpha策略 [推广有奖]

回帖奖励 258 个论坛币 回复本帖可获得 3 个论坛币奖励! 每人限 1 次

版务助理

学术权威

27%

还不是VIP/贵宾

-

威望
1
论坛币
38678 个
通用积分
1788.1129
学术水平
130 点
热心指数
144 点
信用等级
117 点
经验
98153 点
帖子
2118
精华
5
在线时间
6869 小时
注册时间
2017-10-31
最后登录
2024-4-23

相似文件 换一批

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币

对冲基金与量化Alpha策略



正好给大家整理了一批策略代码


量化投资策略是利用量化的方法,进行金融市场的分析、判断和交易的策略、算法的总称。著名的量化投资策略有以下10种(注:策略源码模板不能直接用于实盘交易,仅供探讨交流)


01

海龟交易策略


海龟交易策略是一套非常完整的趋势跟随型的自动化交易策略。这个复杂的策略在入场条件、仓位控制、资金管理、止损止盈等各个环节,都进行了详细的设计,这基本上可以作为复杂交易策略设计和开发的模板。


策略源码模板

向上滑动阅览

# coding=utf-8

from __future__ import print_function, absolute_import, unicode_literals

import numpy as np

import pandas as pd

try:

   import talib

except:

   print('请安装TA-Lib库')

from gm.api import *

'''

本策略通过计算CZCE.FG801和SHFE.rb1801的ATR.唐奇安通道和MA线,并:

上穿唐奇安通道且短MA在长MA上方则开多仓,下穿唐奇安通道且短MA在长MA下方则开空仓

若有 多/空 仓位则分别:

价格 跌/涨 破唐奇安平仓通道 上/下 轨则全平仓位,否则

根据 跌/涨 破持仓均价 -/+ x(x=0.5,1,1.5,2)倍ATR把仓位

回测数据为:CZCE.FG801和SHFE.rb1801的1min数据

回测时间为:2017-09-15 09:15:00到2017-10-01 15:00:00

'''

def init(context):

   # context.parameter分别为唐奇安开仓通道.唐奇安平仓通道.短ma.长ma.ATR的参数

   context.parameter = [55, 20, 10, 60, 20]

   context.tar = context.parameter[4]

   # context.goods交易的品种

   context.goods = ['CZCE.FG801', 'SHFE.rb1801']

   # context.ratio交易最大资金比率

   context.ratio = 0.8

   # 订阅context.goods里面的品种, bar频率为1min

   subscribe(symbols=context.goods, frequency='60s', count=101)

   # 止损的比例区间

def on_bar(context, bars):

   bar = bars[0]

   symbol = bar['symbol']

   recent_data = context.data(symbol=symbol, frequency='60s', count=101, fields='close,high,low')

   close = recent_data['close'].values[-1]

   # 计算ATR

   atr = talib.ATR(recent_data['high'].values, recent_data['low'].values, recent_data['close'].values,

                   timeperiod=context.tar)[-1]

   # 计算唐奇安开仓和平仓通道

   context.don_open = context.parameter[0] + 1

   upper_band = talib.MAX(recent_data['close'].values[:-1], timeperiod=context.don_open)[-1]

   context.don_close = context.parameter[1] + 1

   lower_band = talib.MIN(recent_data['close'].values[:-1], timeperiod=context.don_close)[-1]

   # 计算开仓的资金比例

   percent = context.ratio / float(len(context.goods))

   # 若没有仓位则开仓

   position_long = context.account().position(symbol=symbol, side=PositionSide_Long)

   position_short = context.account().position(symbol=symbol, side=PositionSide_Short)

   if not position_long and not position_short:

       # 计算长短ma线.DIF

       ma_short = talib.MA(recent_data['close'].values, timeperiod=(context.parameter[2] + 1))[-1]

       ma_long = talib.MA(recent_data['close'].values, timeperiod=(context.parameter[3] + 1))[-1]

       dif = ma_short - ma_long

       # 获取当前价格

       # 上穿唐奇安通道且短ma在长ma上方则开多仓

       if close > upper_band and (dif > 0):

           order_target_percent(symbol=symbol, percent=percent, order_type=OrderType_Market,

                                position_side=PositionSide_Long)

           print(symbol, '市价单开多仓到比例: ', percent)

       # 下穿唐奇安通道且短ma在长ma下方则开空仓

       if close < lower_band and (dif < 0):

           order_target_percent(symbol=symbol, percent=percent, order_type=OrderType_Market,

                                position_side=PositionSide_Short)

           print(symbol, '市价单开空仓到比例: ', percent)

   elif position_long:

       # 价格跌破唐奇安平仓通道全平仓位止损

       if close < lower_band:

           order_close_all()

           print(symbol, '市价单全平仓位')

       else:

           # 获取持仓均价

           vwap = position_long['vwap']

           # 获取持仓的资金

           money = position_long['cost']

           # 获取平仓的区间

           band = vwap - np.array([200, 2, 1.5, 1, 0.5, -100]) * atr

           grid_percent = float(pd.cut([close], band, labels=[0, 0.25, 0.5, 0.75, 1])[0]) * percent

           # 选择现有百分比和区间百分比中较小的值(避免开仓)

           target_percent = np.minimum(money / context.account().cash['nav'], grid_percent)

           if target_percent != 1.0:

               print(symbol, '市价单平多仓到比例: ', target_percent)

               order_target_percent(symbol=symbol, percent=target_percent, order_type=OrderType_Market,

                                    position_side=PositionSide_Long)

   elif position_short:

       # 价格涨破唐奇安平仓通道或价格涨破持仓均价加两倍ATR平空仓

       if close > upper_band:

           order_close_all()

           print(symbol, '市价单全平仓位')

       else:

           # 获取持仓均价

           vwap = position_short['vwap']

           # 获取持仓的资金

           money = position_short['cost']

           # 获取平仓的区间

           band = vwap + np.array([-100, 0.5, 1, 1.5, 2, 200]) * atr

           grid_percent = float(pd.cut([close], band, labels=[1, 0.75, 0.5, 0.25, 0])[0]) * percent

           # 选择现有百分比和区间百分比中较小的值(避免开仓)

           target_percent = np.minimum(money / context.account().cash['nav'], grid_percent)

           if target_percent != 1.0:

               order_target_percent(symbol=symbol, percent=target_percent, order_type=OrderType_Market,

                                    position_side=PositionSide_Short)

               print(symbol, '市价单平空仓到比例: ', target_percent)

if __name__ == '__main__':

   '''

   strategy_id策略ID,由系统生成

   filename文件名,请与本文件名保持一致

   mode实时模式:MODE_LIVE回测模式:MODE_BACKTEST

   token绑定计算机的ID,可在系统设置-密钥管理中生成

   backtest_start_time回测开始时间

   backtest_end_time回测结束时间

   backtest_adjust股票复权方式不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POST

   backtest_initial_cash回测初始资金

   backtest_commission_ratio回测佣金比例

   backtest_slippage_ratio回测滑点比例

   '''

   run(strategy_id='strategy_id',

       filename='main.py',

       mode=MODE_BACKTEST,

       token='token_id',

       backtest_start_time='2017-09-15 09:15:00',

       backtest_end_time='2017-10-01 15:00:00',

       backtest_adjust=ADJUST_PREV,

       backtest_initial_cash=10000000,

       backtest_commission_ratio=0.0001,

       backtest_slippage_ratio=0.0001)



02

阿尔法策略


阿尔法的概念来自于二十世纪中叶,经过学者的统计,当时约75%的股票型基金经理构建的投资组合无法跑赢根据市值大小构建的简单组合或是指数,属于传统的基本面分析策略。


在期指市场上做空,在股票市场上构建拟合300指数的成份股,赚取其中的价差,这种被动型的套利就是贝塔套利。



策略源码模板

向上滑动阅览

# coding=utf-8

from __future__ import print_function, absolute_import, unicode_literals

import numpy as np

from gm.api import *

from pandas import DataFrame

'''

本策略每隔1个月定时触发,根据Fama-French三因子模型对每只股票进行回归,得到其alpha值。

假设Fama-French三因子模型可以完全解释市场,则alpha为负表明市场低估该股,因此应该买入。

策略思路:

计算市场收益率、个股的账面市值比和市值,并对后两个进行了分类,

根据分类得到的组合分别计算其市值加权收益率、SMB和HML.

对各个股票进行回归(假设无风险收益率等于0)得到alpha值.

选取alpha值小于0并为最小的10只股票进入标的池

平掉不在标的池的股票并等权买入在标的池的股票

回测数据:SHSE.000300的成份股

回测时间:2017-07-01 08:00:00到2017-10-01 16:00:00

'''

def init(context):

   # 每月第一个交易日的09:40 定时执行algo任务

   schedule(schedule_func=algo, date_rule='1m', time_rule='09:40:00')

   # 数据滑窗

   context.date = 20

   # 设置开仓的最大资金量

   context.ratio = 0.8

   # 账面市值比的大/中/小分类

   context.BM_BIG = 3.0

   context.BM_MID = 2.0

   context.BM_SMA = 1.0

   # 市值大/小分类

   context.MV_BIG = 2.0

   context.MV_SMA = 1.0

# 计算市值加权的收益率,MV为市值的分类,BM为账目市值比的分类

def market_value_weighted(stocks, MV, BM):

   select = stocks[(stocks.NEGOTIABLEMV == MV) & (stocks.BM == BM)]

   market_value = select['mv'].values

   mv_total = np.sum(market_value)

   mv_weighted = [mv / mv_total for mv in market_value]

   stock_return = select['return'].values

   # 返回市值加权的收益率的和

   return_total = []

   for i in range(len(mv_weighted)):

       return_total.append(mv_weighted * stock_return)

   return_total = np.sum(return_total)

   return return_total

def algo(context):

   # 获取上一个交易日的日期

   last_day = get_previous_trading_date(exchange='SHSE', date=context.now)

   # 获取沪深300成份股

   context.stock300 = get_history_constituents(index='SHSE.000300', start_date=last_day,

                                               end_date=last_day)[0]['constituents'].keys()

   # 获取当天有交易的股票

   not_suspended = get_history_instruments(symbols=context.stock300, start_date=last_day, end_date=last_day)

   not_suspended = [item['symbol'] for item in not_suspended

                    if not item['is_suspended'] and item['symbol']!= 'SHSE.601313']  # 601313 为退市股票

   fin = get_fundamentals(table='trading_derivative_indicator', symbols=not_suspended,

                          start_date=last_day, end_date=last_day,fields='PB,NEGOTIABLEMV', df=True)

   # 计算账面市值比,为P/B的倒数

   fin['PB'] = (fin['PB'] ** -1)

   # 计算市值的50%的分位点,用于后面的分类

   size_gate = fin['NEGOTIABLEMV'].quantile(0.50)

   # 计算账面市值比的30%和70%分位点,用于后面的分类

   bm_gate = [fin['PB'].quantile(0.30), fin['PB'].quantile(0.70)]

   fin.index = fin.symbol

   x_return = []

   # 对未停牌的股票进行处理

   for symbol in not_suspended:

       # 计算收益率

       close = history_n(symbol=symbol, frequency='1d', count=context.date + 1, end_time=last_day, fields='close',

                         skip_suspended=True, fill_missing='Last', adjust=ADJUST_PREV, df=True)['close'].values

       stock_return = close[-1] / close[0] - 1

       pb = fin['PB'][symbol]

       market_value = fin['NEGOTIABLEMV'][symbol]

       # 获取[股票代码. 股票收益率, 账面市值比的分类, 市值的分类, 流通市值]

       if pb < bm_gate[0]:

           if market_value < size_gate:

               label = [symbol, stock_return, context.BM_SMA, context.MV_SMA, market_value]

           else:

               label = [symbol, stock_return, context.BM_SMA, context.MV_BIG, market_value]

       elif pb < bm_gate[1]:

           if market_value < size_gate:

               label = [symbol, stock_return, context.BM_MID, context.MV_SMA, market_value]

           else:

               label = [symbol, stock_return, context.BM_MID, context.MV_BIG, market_value]

       elif market_value < size_gate:

           label = [symbol, stock_return, context.BM_BIG, context.MV_SMA, market_value]

       else:

           label = [symbol, stock_return, context.BM_BIG, context.MV_BIG, market_value]

       if len(x_return) == 0:

           x_return = label

       else:

           x_return = np.vstack([x_return, label])

   stocks = DataFrame(data=x_return, columns=['symbol', 'return', 'BM', 'NEGOTIABLEMV', 'mv'])

   stocks.index = stocks.symbol

   columns = ['return', 'BM', 'NEGOTIABLEMV', 'mv']

   for column in columns:

       stocks[column] = stocks[column].astype(np.float64)

   # 计算SMB.HML和市场收益率

   # 获取小市值组合的市值加权组合收益率

   smb_s = (market_value_weighted(stocks, context.MV_SMA, context.BM_SMA) +

            market_value_weighted(stocks, context.MV_SMA, context.BM_MID) +

            market_value_weighted(stocks, context.MV_SMA, context.BM_BIG)) / 3

   # 获取大市值组合的市值加权组合收益率

   smb_b = (market_value_weighted(stocks, context.MV_BIG, context.BM_SMA) +

            market_value_weighted(stocks, context.MV_BIG, context.BM_MID) +

            market_value_weighted(stocks, context.MV_BIG, context.BM_BIG)) / 3

   smb = smb_s - smb_b

   # 获取大账面市值比组合的市值加权组合收益率

   hml_b = (market_value_weighted(stocks, context.MV_SMA, 3) +

            market_value_weighted(stocks, context.MV_BIG, context.BM_BIG)) / 2

   # 获取小账面市值比组合的市值加权组合收益率

   hml_s = (market_value_weighted(stocks, context.MV_SMA, context.BM_SMA) +

            market_value_weighted(stocks, context.MV_BIG, context.BM_SMA)) / 2

   hml = hml_b - hml_s

   close = history_n(symbol='SHSE.000300', frequency='1d', count=context.date + 1,

                     end_time=last_day, fields='close', skip_suspended=True,

                     fill_missing='Last', adjust=ADJUST_PREV, df=True)['close'].values

   market_return = close[-1] / close[0] - 1

   coff_pool = []

   # 对每只股票进行回归获取其alpha值

   for stock in stocks.index:

       x_value = np.array([[market_return], [smb], [hml], [1.0]])

       y_value = np.array([stocks['return'][stock]])

       # OLS估计系数

       coff = np.linalg.lstsq(x_value.T, y_value)[0][3]

       coff_pool.append(coff)

   # 获取alpha最小并且小于0的10只的股票进行操作(若少于10只则全部买入)

   stocks['alpha'] = coff_pool

   stocks = stocks[stocks.alpha < 0].sort_values(by='alpha').head(10)

   symbols_pool = stocks.index.tolist()

   positions = context.account().positions()

   # 平不在标的池的股票

   for position in positions:

       symbol = position['symbol']

       if symbol not in symbols_pool:

           order_target_percent(symbol=symbol, percent=0, order_type=OrderType_Market,

                                position_side=PositionSide_Long)

           print('市价单平不在标的池的', symbol)

   # 获取股票的权重

   percent = context.ratio / len(symbols_pool)

   # 买在标的池中的股票

   for symbol in symbols_pool:

       order_target_percent(symbol=symbol, percent=percent, order_type=OrderType_Market,

                            position_side=PositionSide_Long)

       print(symbol, '以市价单调多仓到仓位', percent)

if __name__ == '__main__':

   '''

   strategy_id策略ID,由系统生成

   filename文件名,请与本文件名保持一致

   mode实时模式:MODE_LIVE回测模式:MODE_BACKTEST

   token绑定计算机的ID,可在系统设置-密钥管理中生成

   backtest_start_time回测开始时间

   backtest_end_time回测结束时间

   backtest_adjust股票复权方式不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POST

   backtest_initial_cash回测初始资金

   backtest_commission_ratio回测佣金比例

   backtest_slippage_ratio回测滑点比例

   '''

   run(strategy_id='strategy_id',

       filename='main.py',

       mode=MODE_BACKTEST,

       token='token_id',

       backtest_start_time='2017-07-01 08:00:00',

       backtest_end_time='2017-10-01 16:00:00',

       backtest_adjust=ADJUST_PREV,

       backtest_initial_cash=10000000,

       backtest_commission_ratio=0.0001,

       backtest_slippage_ratio=0.0001)



03

多因子选股


多因子模型是量化选股中最重要的一类模型,基本思想是找到某些和收益率最相关的指标,并根据该指标,构建一个股票组合,期望该组合在未来的一段时间跑赢或跑输指数。如果跑赢,则可以做多该组合,同时做空期指,赚取正向阿尔法收益;如果是跑输,则可以组多期指,融券做空该组合,赚取反向阿尔法收益。多因子模型的关键是找到因子与收益率之间的关联性。


策略源码模板

向上滑动阅览

# coding=utf-8

from __future__ import print_function, absolute_import, unicode_literals

import numpy as np

from gm.api import *

from pandas import DataFrame

'''

本策略每隔1个月定时触发,根据Fama-French三因子模型对每只股票进行回归,得到其alpha值。

假设Fama-French三因子模型可以完全解释市场,则alpha为负表明市场低估该股,因此应该买入。

策略思路:

计算市场收益率、个股的账面市值比和市值,并对后两个进行了分类,

根据分类得到的组合分别计算其市值加权收益率、SMB和HML.

对各个股票进行回归(假设无风险收益率等于0)得到alpha值.

选取alpha值小于0并为最小的10只股票进入标的池

平掉不在标的池的股票并等权买入在标的池的股票

回测数据:SHSE.000300的成份股

回测时间:2017-07-01 08:00:00到2017-10-01 16:00:00

'''

def init(context):

   # 每月第一个交易日的09:40 定时执行algo任务

   schedule(schedule_func=algo, date_rule='1m', time_rule='09:40:00')

   # 数据滑窗

   context.date = 20

   # 设置开仓的最大资金量

   context.ratio = 0.8

   # 账面市值比的大/中/小分类

   context.BM_BIG = 3.0

   context.BM_MID = 2.0

   context.BM_SMA = 1.0

   # 市值大/小分类

   context.MV_BIG = 2.0

   context.MV_SMA = 1.0

# 计算市值加权的收益率,MV为市值的分类,BM为账目市值比的分类

def market_value_weighted(stocks, MV, BM):

   select = stocks[(stocks.NEGOTIABLEMV == MV) & (stocks.BM == BM)]

   market_value = select['mv'].values

   mv_total = np.sum(market_value)

   mv_weighted = [mv / mv_total for mv in market_value]

   stock_return = select['return'].values

   # 返回市值加权的收益率的和

   return_total = []

   for i in range(len(mv_weighted)):

       return_total.append(mv_weighted * stock_return)

   return_total = np.sum(return_total)

   return return_total

def algo(context):

   # 获取上一个交易日的日期

   last_day = get_previous_trading_date(exchange='SHSE', date=context.now)

   # 获取沪深300成份股

   context.stock300 = get_history_constituents(index='SHSE.000300', start_date=last_day,

                                               end_date=last_day)[0]['constituents'].keys()

   # 获取当天有交易的股票

   not_suspended = get_history_instruments(symbols=context.stock300, start_date=last_day, end_date=last_day)

   not_suspended = [item['symbol'] for item in not_suspended

                    if not item['is_suspended'] and item['symbol']!= 'SHSE.601313']  # 601313 为退市股票

   fin = get_fundamentals(table='trading_derivative_indicator', symbols=not_suspended,

                          start_date=last_day, end_date=last_day,fields='PB,NEGOTIABLEMV', df=True)

   # 计算账面市值比,为P/B的倒数

   fin['PB'] = (fin['PB'] ** -1)

   # 计算市值的50%的分位点,用于后面的分类

   size_gate = fin['NEGOTIABLEMV'].quantile(0.50)

   # 计算账面市值比的30%和70%分位点,用于后面的分类

   bm_gate = [fin['PB'].quantile(0.30), fin['PB'].quantile(0.70)]

   fin.index = fin.symbol

   x_return = []

   # 对未停牌的股票进行处理

   for symbol in not_suspended:

       # 计算收益率

       close = history_n(symbol=symbol, frequency='1d', count=context.date + 1, end_time=last_day, fields='close',

                         skip_suspended=True, fill_missing='Last', adjust=ADJUST_PREV, df=True)['close'].values

       stock_return = close[-1] / close[0] - 1

       pb = fin['PB'][symbol]

       market_value = fin['NEGOTIABLEMV'][symbol]

       # 获取[股票代码. 股票收益率, 账面市值比的分类, 市值的分类, 流通市值]

       if pb < bm_gate[0]:

           if market_value < size_gate:

               label = [symbol, stock_return, context.BM_SMA, context.MV_SMA, market_value]

           else:

               label = [symbol, stock_return, context.BM_SMA, context.MV_BIG, market_value]

       elif pb < bm_gate[1]:

           if market_value < size_gate:

               label = [symbol, stock_return, context.BM_MID, context.MV_SMA, market_value]

           else:

               label = [symbol, stock_return, context.BM_MID, context.MV_BIG, market_value]

       elif market_value < size_gate:

           label = [symbol, stock_return, context.BM_BIG, context.MV_SMA, market_value]

       else:

           label = [symbol, stock_return, context.BM_BIG, context.MV_BIG, market_value]

       if len(x_return) == 0:

           x_return = label

       else:

           x_return = np.vstack([x_return, label])

   stocks = DataFrame(data=x_return, columns=['symbol', 'return', 'BM', 'NEGOTIABLEMV', 'mv'])

   stocks.index = stocks.symbol

   columns = ['return', 'BM', 'NEGOTIABLEMV', 'mv']

   for column in columns:

       stocks[column] = stocks[column].astype(np.float64)

   # 计算SMB.HML和市场收益率

   # 获取小市值组合的市值加权组合收益率

   smb_s = (market_value_weighted(stocks, context.MV_SMA, context.BM_SMA) +

            market_value_weighted(stocks, context.MV_SMA, context.BM_MID) +

            market_value_weighted(stocks, context.MV_SMA, context.BM_BIG)) / 3

   # 获取大市值组合的市值加权组合收益率

   smb_b = (market_value_weighted(stocks, context.MV_BIG, context.BM_SMA) +

            market_value_weighted(stocks, context.MV_BIG, context.BM_MID) +

            market_value_weighted(stocks, context.MV_BIG, context.BM_BIG)) / 3

   smb = smb_s - smb_b

   # 获取大账面市值比组合的市值加权组合收益率

   hml_b = (market_value_weighted(stocks, context.MV_SMA, 3) +

            market_value_weighted(stocks, context.MV_BIG, context.BM_BIG)) / 2

   # 获取小账面市值比组合的市值加权组合收益率

   hml_s = (market_value_weighted(stocks, context.MV_SMA, context.BM_SMA) +

            market_value_weighted(stocks, context.MV_BIG, context.BM_SMA)) / 2

   hml = hml_b - hml_s

   close = history_n(symbol='SHSE.000300', frequency='1d', count=context.date + 1,

                     end_time=last_day, fields='close', skip_suspended=True,

                     fill_missing='Last', adjust=ADJUST_PREV, df=True)['close'].values

   market_return = close[-1] / close[0] - 1

   coff_pool = []

   # 对每只股票进行回归获取其alpha值

   for stock in stocks.index:

       x_value = np.array([[market_return], [smb], [hml], [1.0]])

       y_value = np.array([stocks['return'][stock]])

       # OLS估计系数

       coff = np.linalg.lstsq(x_value.T, y_value)[0][3]

       coff_pool.append(coff)

   # 获取alpha最小并且小于0的10只的股票进行操作(若少于10只则全部买入)

   stocks['alpha'] = coff_pool

   stocks = stocks[stocks.alpha < 0].sort_values(by='alpha').head(10)

   symbols_pool = stocks.index.tolist()

   positions = context.account().positions()

   # 平不在标的池的股票

   for position in positions:

       symbol = position['symbol']

       if symbol not in symbols_pool:

           order_target_percent(symbol=symbol, percent=0, order_type=OrderType_Market,

                                position_side=PositionSide_Long)

           print('市价单平不在标的池的', symbol)

   # 获取股票的权重

   percent = context.ratio / len(symbols_pool)

   # 买在标的池中的股票

   for symbol in symbols_pool:

       order_target_percent(symbol=symbol, percent=percent, order_type=OrderType_Market,

                            position_side=PositionSide_Long)

       print(symbol, '以市价单调多仓到仓位', percent)

if __name__ == '__main__':

   '''

   strategy_id策略ID,由系统生成

   filename文件名,请与本文件名保持一致

   mode实时模式:MODE_LIVE回测模式:MODE_BACKTEST

   token绑定计算机的ID,可在系统设置-密钥管理中生成

   backtest_start_time回测开始时间

   backtest_end_time回测结束时间

   backtest_adjust股票复权方式不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POST

   backtest_initial_cash回测初始资金

   backtest_commission_ratio回测佣金比例

   backtest_slippage_ratio回测滑点比例

   '''

   run(strategy_id='strategy_id',

       filename='main.py',

       mode=MODE_BACKTEST,

       token='token_id',

       backtest_start_time='2017-07-01 08:00:00',

       backtest_end_time='2017-10-01 16:00:00',

       backtest_adjust=ADJUST_PREV,

       backtest_initial_cash=10000000,

       backtest_commission_ratio=0.0001,

       backtest_slippage_ratio=0.0001)



04

双均线策略


双均线策略,通过建立m天移动平均线,n天移动平均线,则两条均线必有交点。若m>n,n天平均线“上穿越”m天均线则为买入点,反之为卖出点。该策略基于不同天数均线的交叉点,抓住股票的强势和弱势时刻,进行交易。


双均线策略中,如果两根均线的周期接近,比如5日线,10日线,这种非常容易缠绕,不停的产生买点卖点,会有大量的无效交易,交易费用很高。如果两根均线的周期差距较大,比如5日线,60日线,这种交易周期很长,趋势性已经不明显了,趋势转变以后很长时间才会出现买卖点。也就是说可能会造成很大的亏损。所以两个参数选择的很重要,趋势性越强的品种,均线策略越有效。


策略源码模板

向上滑动阅览

# coding=utf-8

from __future__ import print_function, absolute_import

from gm.api import *

import talib

import time

'''

本策略以DCE.i1801为交易标的,根据其一分钟(即60s频度)bar数据建立双均线模型,

短周期为30,长周期为60,当短期均线由上向下穿越长期均线时做空,

当短期均线由下向上穿越长期均线时做多,每次开仓前先平掉所持仓位,再开仓。

回测数据为:DCE.i1801的60s频度bar数据

回测时间为:2017-09-01 09:00:00到2017-09-30 15:00:00

'''

def init(context):

   context.FAST = 30                                              # 短周期

   context.SLOW = 60                                              # 长周期

   context.symbol = 'DCE.i1801'                                   # 订阅&交易标的

   context.period = context.SLOW + 1                              # 订阅数据滑窗长度

   subscribe(context.symbol, '60s', count=context.period)         # 订阅行情

def on_bar(context, bars):

   print (bars[0].bob)

   # 获取通过subscribe订阅的数据

   prices = context.data('DCE.i1801', '60s', context.period, fields='close')

   # 计算长短周期均线

   fast_avg = talib.SMA(prices.values.reshape(context.period), context.FAST)

   slow_avg = talib.SMA(prices.values.reshape(context.period), context.SLOW)

   # 均线下穿,做空

   if slow_avg[-2] < fast_avg[-2] and slow_avg[-1] >= fast_avg[-1]:

     # 平多仓

       order_target_percent(symbol=context.symbol, percent=0, position_side=1, order_type=2)

     # 开空仓

       order_target_percent(symbol=context.symbol, percent=0.1, position_side=2, order_type=2)

   # 均线上穿,做多

   if fast_avg[-2] < slow_avg[-2] and fast_avg[-1] >= slow_avg[-1]:

     # 平空仓

       order_target_percent(symbol=context.symbol, percent=0, position_side=2,order_type=2)

     # 开多仓

       order_target_percent(symbol=context.symbol, percent=0.1, position_side=1,order_type=2)

def on_execution_report(context, execrpt):

   # 打印委托执行回报

   print(execrpt)  

if __name__ == '__main__':

   '''

   strategy_id策略ID,由系统生成

   filename文件名,请与本文件名保持一致

   mode实时模式:MODE_LIVE回测模式:MODE_BACKTEST

   token绑定计算机的ID,可在系统设置-密钥管理中生成

   backtest_start_time回测开始时间

   backtest_end_time回测结束时间

   backtest_adjust股票复权方式不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POST

   backtest_initial_cash回测初始资金

   backtest_commission_ratio回测佣金比例

   backtest_slippage_ratio回测滑点比例

   '''

   run(strategy_id='strategy_id',

       filename='main.py',

       mode=MODE_BACKTEST,

       token='token_id',

       backtest_start_time='2017-09-01 09:00:00',

       backtest_end_time='2017-09-30 15:00:00',

       backtest_adjust=ADJUST_NONE,

       backtest_initial_cash=10000000,

       backtest_commission_ratio=0.0001,

       backtest_slippage_ratio=0.0001)



05

行业轮动


行业轮动是利用市场趋势获利的一种主动交易策略其本质是利用不同投资品种强势时间的错位对行业品种进行切换以达到投资收益最大化的目的。


策略源码模板

向上滑动阅览

# coding=utf-8

from __future__ import print_function, absolute_import, unicode_literals

import numpy as np

from gm.api import *

'''

本策略每隔1个月定时触发计算SHSE.000910.SHSE.000909.SHSE.000911.SHSE.000912.SHSE.000913.SHSE.000914

(300工业.300材料.300可选.300消费.300医药.300金融)这几个行业指数过去

20个交易日的收益率并选取了收益率最高的指数的成份股获取并获取了他们的市值数据

随后把仓位调整至市值最大的5只股票上

回测数据为:SHSE.000910.SHSE.000909.SHSE.000911.SHSE.000912.SHSE.000913.SHSE.000914和他们的成份股

回测时间为:2017-07-01 08:00:00到2017-10-01 16:00:00

'''

def init(context):

   # 每月第一个交易日的09:40 定时执行algo任务

   schedule(schedule_func=algo, date_rule='1m', time_rule='09:40:00')

   # 用于筛选的行业指数

   context.index = ['SHSE.000910', 'SHSE.000909', 'SHSE.000911', 'SHSE.000912', 'SHSE.000913', 'SHSE.000914']

   # 用于统计数据的天数

   context.date = 20

   # 最大下单资金比例

   context.ratio = 0.8

def algo(context):

   # 获取当天的日期

   today = context.now

   # 获取上一个交易日

   last_day = get_previous_trading_date(exchange='SHSE', date=today)

   return_index = []

   # 获取并计算行业指数收益率

   for i in context.index:

       return_index_his = history_n(symbol=i, frequency='1d', count=context.date, fields='close,bob',

                                    fill_missing='Last', adjust=ADJUST_PREV, end_time=last_day, df=True)

       return_index_his = return_index_his['close'].values

       return_index.append(return_index_his[-1] / return_index_his[0] - 1)

   # 获取指定数内收益率表现最好的行业

   sector = context.index[np.argmax(return_index)]

   print('最佳行业指数是: ', sector)

   # 获取最佳行业指数成份股

   symbols = get_history_constituents(index=sector, start_date=last_day, end_date=last_day)[0]['constituents'].keys()

   # 获取当天有交易的股票

   not_suspended_info = get_history_instruments(symbols=symbols, start_date=today, end_date=today)

   not_suspended_symbols = [item['symbol'] for item in not_suspended_info if not item['is_suspended']]

   # 获取最佳行业指数成份股的市值,从大到小排序并选取市值最大的5只股票

   fin = get_fundamentals(table='tq_sk_finindic', symbols=not_suspended_symbols, start_date=last_day,

                          end_date=last_day, limit=5, fields='NEGOTIABLEMV', order_by='-NEGOTIABLEMV', df=True)

   fin.index = fin['symbol']

   # 计算权重

   percent = 1.0 / len(fin.index) * context.ratio

   # 获取当前所有仓位

   positions = context.account().positions()

   # 如标的池有仓位,平不在标的池的仓位

   for position in positions:

       symbol = position['symbol']

       if symbol not in fin.index:

           order_target_percent(symbol=symbol, percent=0, order_type=OrderType_Market,

                                position_side=PositionSide_Long)

           print('市价单平不在标的池的', symbol)

   # 对标的池进行操作

   for symbol in fin.index:

       order_target_percent(symbol=symbol, percent=percent, order_type=OrderType_Market,

                            position_side=PositionSide_Long)

       print(symbol, '以市价单调整至仓位', percent)

if __name__ == '__main__':

   '''

   strategy_id策略ID,由系统生成

   filename文件名,请与本文件名保持一致

   mode实时模式:MODE_LIVE回测模式:MODE_BACKTEST

   token绑定计算机的ID,可在系统设置-密钥管理中生成

   backtest_start_time回测开始时间

   backtest_end_time回测结束时间

   backtest_adjust股票复权方式不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POST

   backtest_initial_cash回测初始资金

   backtest_commission_ratio回测佣金比例

   backtest_slippage_ratio回测滑点比例

   '''

   run(strategy_id='strategy_id',

       filename='main.py',

       mode=MODE_BACKTEST,

       token='token_id',

       backtest_start_time='2017-07-01 08:00:00',

       backtest_end_time='2017-10-01 16:00:00',

       backtest_adjust=ADJUST_PREV,

       backtest_initial_cash=10000000,

       backtest_commission_ratio=0.0001,

       backtest_slippage_ratio=0.0001)



06

跨品种套利


跨品种套利指的是利用两种不同的、但相关联的指数期货产品之间的价差进行交易。这两种指数之间具有相互替代性或受同一供求因素制约。跨品种套利的交易形式是同时买进和卖出相同交割月份但不同种类的股指期货合约。主要有相关商品间套利和原料与成品之间套利。


跨品种套利的主要作用一是帮助扭曲的市场价格回复到正常水平;二是增强市场的流动性。


策略源码模板

向上滑动阅览

# coding=utf-8

from __future__ import print_function, absolute_import, unicode_literals

from gm.api import *

import numpy as np

'''

本策略首先滚动计算过去30个1min收盘价的均值,然后用均值加减2个标准差得到布林线.

若无仓位,在最新价差上穿上轨时做空价差;下穿下轨时做多价差

若有仓位则在最新价差回归至上下轨水平内时平仓

回测数据为:SHFE.rb1801和SHFE.hc1801的1min数据

回测时间为:2017-09-01 08:00:00到2017-10-01 16:00:00

'''

def init(context):

   # 进行套利的品种

   context.goods = ['SHFE.rb1801', 'SHFE.hc1801']

   # 订阅行情

   subscribe(symbols=context.goods, frequency='60s', count=30, wait_group=True)

def on_bar(context, bars):

   # 获取两个品种的时间序列

   data_rb = context.data(symbol=context.goods[0], frequency='60s', count=31, fields='close')

   close_rb = data_rb.values

   data_hc = context.data(symbol=context.goods[1], frequency='60s', count=31, fields='close')

   close_hc = data_hc.values

   # 计算价差

   spread = close_rb - close_hc

   # 计算布林带的上下轨

   up = np.mean(spread) + 2 * np.std(spread)

   down = np.mean(spread) - 2 * np.std(spread)

   # 计算最新价差

   spread_now = close_rb[-1] - close_hc[-1]

   # 无交易时若价差上(下)穿布林带上(下)轨则做空(多)价差

   position_rb_long = context.account().position(symbol=context.goods[0], side=PositionSide_Long)

   position_rb_short = context.account().position(symbol=context.goods[0], side=PositionSide_Short)

   if not position_rb_long and not position_rb_short:

       if spread_now > up:

           order_target_volume(symbol=context.goods[0], volume=1, order_type=OrderType_Market,

                               position_side=PositionSide_Short)

           print(context.goods[0], '以市价单开空仓一手')

           order_target_volume(symbol=context.goods[1], volume=1, order_type=OrderType_Market,

                               position_side=PositionSide_Long)

           print(context.goods[1], '以市价单开多仓一手')

       if spread_now < down:

           order_target_volume(symbol=context.goods[0], volume=1, order_type=OrderType_Market,

                               position_side=PositionSide_Long)

           print(context.goods[0], '以市价单开多仓一手')

           order_target_volume(symbol=context.goods[1], volume=1, order_type=OrderType_Market,

                               position_side=PositionSide_Short)

           print(context.goods[1], '以市价单开空仓一手')

   # 价差回归时平仓

   elif position_rb_short:

       if spread_now <= up:

           order_close_all()

           print('价格回归,平所有仓位')

           # 跌破下轨反向开仓

       if spread_now < down:

           order_target_volume(symbol=context.goods[0], volume=1, order_type=OrderType_Market,

                               position_side=PositionSide_Long)

           print(context.goods[0], '以市价单开多仓一手')

           order_target_volume(symbol=context.goods[1], volume=1, order_type=OrderType_Market,

                               position_side=PositionSide_Short)

           print(context.goods[1], '以市价单开空仓一手')

   elif position_rb_long:

       if spread_now >= down:

           order_close_all()

           print('价格回归,平所有仓位')

           # 涨破上轨反向开仓

       if spread_now > up:

           order_target_volume(symbol=context.goods[0], volume=1, order_type=OrderType_Market,

                               position_side=PositionSide_Short)

           print(context.goods[0], '以市价单开空仓一手')

           order_target_volume(symbol=context.goods[1], volume=1, order_type=OrderType_Market,

                               position_side=PositionSide_Long)

           print(context.goods[1], '以市价单开多仓一手')

if __name__ == '__main__':

   '''

   strategy_id策略ID,由系统生成

   filename文件名,请与本文件名保持一致

   mode实时模式:MODE_LIVE回测模式:MODE_BACKTEST

   token绑定计算机的ID,可在系统设置-密钥管理中生成

   backtest_start_time回测开始时间

   backtest_end_time回测结束时间

   backtest_adjust股票复权方式不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POST

   backtest_initial_cash回测初始资金

   backtest_commission_ratio回测佣金比例

   backtest_slippage_ratio回测滑点比例

   '''

   run(strategy_id='strategy_id',

       filename='main.py',

       mode=MODE_BACKTEST,

       token='token_id',

       backtest_start_time='2017-09-01 08:00:00',

       backtest_end_time='2017-10-01 16:00:00',

       backtest_adjust=ADJUST_PREV,

       backtest_initial_cash=500000,

       backtest_commission_ratio=0.0001,

       backtest_slippage_ratio=0.0001)



07

指数增强


增强型指数投资由于不同基金管理人描述其指数增强型产品的投资目的不尽相同,增强型指数投资并无统一模式,唯一共同点在于他们都希望能够提供高于标的指数回报水平的投资业绩。为使指数化投资名副其实,基金经理试图尽可能保持标的指数的各种特征。


策略源码模板

向上滑动阅览

# coding=utf-8

from __future__ import print_function, absolute_import, unicode_literals

import numpy as np

from gm.api import *

from pandas import DataFrame

'''

本策略以0.8为初始权重跟踪指数标的沪深300中权重大于0.35%的成份股.

个股所占的百分比为(0.8*成份股权重)*100%.然后根据个股是否:

1.连续上涨5天 2.连续下跌5天

来判定个股是否为强势股/弱势股,并对其把权重由0.8调至1.0或0.6

回测时间为:2017-07-01 08:50:00到2017-10-01 17:00:00

'''

def init(context):

   # 资产配置的初始权重,配比为0.6-0.8-1.0

   context.ratio = 0.8

   # 获取沪深300当时的成份股和相关数据

   stock300 = get_history_constituents(index='SHSE.000300', start_date='2017-06-30', end_date='2017-06-30')[0][

   stock300_symbol = []

   stock300_weight = []

   for key in stock300:

       # 保留权重大于0.35%的成份股

       if (stock300[key] / 100) > 0.0035:

           stock300_symbol.append(key)

           stock300_weight.append(stock300[key] / 100)

   context.stock300 = DataFrame([stock300_weight], columns=stock300_symbol, index=['weight']).T

   print('选择的成分股权重总和为: ', np.sum(stock300_weight))

   subscribe(symbols=stock300_symbol, frequency='1d', count=5, wait_group=True)

def on_bar(context, bars):

   # 若没有仓位则按照初始权重开仓

   for bar in bars:

       symbol = bar['symbol']

       position = context.account().position(symbol=symbol, side=PositionSide_Long)

       if not position:

           buy_percent = context.stock300['weight'][symbol] * context.ratio

           order_target_percent(symbol=symbol, percent=buy_percent, order_type=OrderType_Market,

                                position_side=PositionSide_Long)

           print(symbol, '以市价单开多仓至仓位:', buy_percent)

       else:

           # 获取过去5天的价格数据,若连续上涨则为强势股,权重+0.2;若连续下跌则为弱势股,权重-0.2

           recent_data = context.data(symbol=symbol, frequency='1d', count=5, fields='close')['close'].tolist()

           if all(np.diff(recent_data) > 0):

               buy_percent = context.stock300['weight'][symbol] * (context.ratio + 0.2)

               order_target_percent(symbol=symbol, percent=buy_percent, order_type=OrderType_Market,

                                    position_side=PositionSide_Long)

               print('强势股', symbol, '以市价单调多仓至仓位:', buy_percent)

           elif all(np.diff(recent_data) < 0):

               buy_percent = context.stock300['weight'][symbol] * (context.ratio - 0.2)

               order_target_percent(symbol=symbol, percent=buy_percent, order_type=OrderType_Market,

                                    position_side=PositionSide_Long)

               print('弱势股', symbol, '以市价单调多仓至仓位:', buy_percent)

if __name__ == '__main__':

   '''

   strategy_id策略ID,由系统生成

   filename文件名,请与本文件名保持一致

   mode实时模式:MODE_LIVE回测模式:MODE_BACKTEST

   token绑定计算机的ID,可在系统设置-密钥管理中生成

   backtest_start_time回测开始时间

   backtest_end_time回测结束时间

   backtest_adjust股票复权方式不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POST

   backtest_initial_cash回测初始资金

   backtest_commission_ratio回测佣金比例

   backtest_slippage_ratio回测滑点比例

   '''

   run(strategy_id='strategy_id',

       filename='main.py',

       mode=MODE_BACKTEST,

       token='token_id',

       backtest_start_time='2017-07-01 08:50:00',

       backtest_end_time='2017-10-01 17:00:00',

       backtest_adjust=ADJUST_PREV,

       backtest_initial_cash=10000000,

       backtest_commission_ratio=0.0001,

       backtest_slippage_ratio=0.0001)



08

网格交易


网格交易是利用市场震荡行情获利的一种主动交易策略,其本质是利用投资标的在一段震荡行情中价格在网格区间内的反复运动以进行加仓减仓的操作以达到投资收益最大化的目的。通俗点讲就是根据建立不同数量.不同大小的网格,在突破网格的时候建仓,回归网格的时候减仓,力求能够捕捉到价格的震荡变化趋势,达到盈利的目的。


策略源码模板

向上滑动阅览

# coding=utf-8

from __future__ import print_function, absolute_import, unicode_literals

import numpy as np

import pandas as pd

from gm.api import *

'''

本策略首先计算了SHFE.rb1801过去300个1min收盘价的均值和标准差

并用均值加减2和3个标准差得到网格的区间分界线,分别配以0.3和0.5的仓位权重

然后根据价格所在的区间来配置仓位:

(n为收盘价的均值,std为收盘价的标准差,k1-k6分别为[-40, -3, -2, 2, 3, 40],其中-40和40为上下界,无实际意义)

[0.5, 0.3, 0.0, -0.3, -0.5](资金比例,此处负号表示开空仓)

回测数据为:SHFE.rb1801的1min数据

回测时间为:2017-07-01 08:00:00到2017-10-01 16:00:00

'''

def init(context):

   context.symbol = 'SHFE.rb1801'

   # 订阅SHFE.rb1801, bar频率为1min

   subscribe(symbols=context.symbol, frequency='60s')

   # 获取过去300个价格数据

   timeseries = history_n(symbol=context.symbol, frequency='60s', count=300, fields='close', fill_missing='Last',

                          end_time='2017-07-01 08:00:00', df=True)['close'].values

   # 获取网格区间分界线

   context.band = np.mean(timeseries) + np.array([-40, -3, -2, 2, 3, 40]) * np.std(timeseries)

   # 设置网格的仓位

   context.weight = [0.5, 0.3, 0.0, 0.3, 0.5]

def on_bar(context, bars):

   bar = bars[0]

   # 根据价格落在(-40,-3],(-3,-2],(-2,2],(2,3],(3,40]的区间范围来获取最新收盘价所在的价格区间

   grid = pd.cut([bar.close], context.band, labels=[0, 1, 2, 3, 4])[0]

   # 获取多仓仓位

   position_long = context.account().position(symbol=context.symbol, side=PositionSide_Long)

   # 获取空仓仓位

   position_short = context.account().position(symbol=context.symbol, side=PositionSide_Short)

   # 若无仓位且价格突破则按照设置好的区间开仓

   if not position_long and not position_short and grid != 2:

       # 大于3为在中间网格的上方,做空

       if grid >= 3:

           order_target_percent(symbol=context.symbol, percent=context.weight[grid], order_type=OrderType_Market,

                                position_side=PositionSide_Short)

           print(context.symbol, '以市价单开空仓到仓位', context.weight[grid])

       if grid <= 1:

           order_target_percent(symbol=context.symbol, percent=context.weight[grid], order_type=OrderType_Market,

                                position_side=PositionSide_Long)

           print(context.symbol, '以市价单开多仓到仓位', context.weight[grid])

   # 持有多仓的处理

   elif position_long:

       # 大于3为在中间网格的上方,做空

       if grid >= 3:

           order_target_percent(symbol=context.symbol, percent=0, order_type=OrderType_Market,

                                position_side=PositionSide_Long)

           print(context.symbol, '以市价单全平多仓')

           order_target_percent(symbol=context.symbol, percent=context.weight[grid], order_type=OrderType_Market,

                                position_side=PositionSide_Short)

           print(context.symbol, '以市价单调开空仓到仓位', context.weight[grid])

       # 等于2为在中间网格,平仓

       elif grid == 2:

           order_target_percent(symbol=context.symbol, percent=0, order_type=OrderType_Market,

                                position_side=PositionSide_Long)

           print(context.symbol, '以市价单全平多仓')

       # 小于1为在中间网格的下方,做多

       elif grid <= 1:

           order_target_percent(symbol=context.symbol, percent=context.weight[grid], order_type=OrderType_Market,

                                position_side=PositionSide_Long)

           print(context.symbol, '以市价单开多仓到仓位', context.weight[grid])

   # 持有空仓的处理

   elif position_short:

       # 小于1为在中间网格的下方,做多

       if grid <= 1:

           order_target_percent(symbol=context.symbol, percent=0, order_type=OrderType_Market,

                                position_side=PositionSide_Short)

           print(context.symbol, '以市价单全平空仓')

           order_target_percent(symbol=context.symbol, percent=context.weight[grid], order_type=OrderType_Market,

                                position_side=PositionSide_Long)

           print(context.symbol, '以市价单调多仓到仓位', context.weight[grid])

       # 等于2为在中间网格,平仓

       elif grid == 2:

           order_target_percent(symbol=context.symbol, percent=0, order_type=OrderType_Market,

                                position_side=PositionSide_Short)

           print(context.symbol, '以市价单全平空仓')

       # 大于3为在中间网格的上方,做空

       elif grid >= 3:

           order_target_percent(symbol=context.symbol, percent=context.weight[grid], order_type=OrderType_Market,

                                position_side=PositionSide_Short)

           print(context.symbol, '以市价单开空仓到仓位', context.weight[grid])

if __name__ == '__main__':

   '''

   strategy_id策略ID,由系统生成

   filename文件名,请与本文件名保持一致

   mode实时模式:MODE_LIVE回测模式:MODE_BACKTEST

   token绑定计算机的ID,可在系统设置-密钥管理中生成

   backtest_start_time回测开始时间

   backtest_end_time回测结束时间

   backtest_adjust股票复权方式不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POST

   backtest_initial_cash回测初始资金

   backtest_commission_ratio回测佣金比例

   backtest_slippage_ratio回测滑点比例

   '''

   run(strategy_id='strategy_id',

       filename='main.py',

       mode=MODE_BACKTEST,

       token='token_id',

       backtest_start_time='2017-07-01 08:00:00',

       backtest_end_time='2017-10-01 16:00:00',

       backtest_adjust=ADJUST_PREV,

       backtest_initial_cash=10000000,

       backtest_commission_ratio=0.0001,

       backtest_slippage_ratio=0.0001)



09

跨期套利


跨期套利是套利交易中最普遍的一种,是股指期货的跨期套利(Calendar Spread Arbitrage)即为在同一交易所进行同一指数、但不同交割月份的套利活动。


策略源码模板

向上滑动阅览

# coding=utf-8

from __future__ import print_function, absolute_import, unicode_literals

import numpy as np

from gm.api import *

try:

   import statsmodels.tsa.stattools as ts

except:

   print('请安装statsmodels库')

'''

本策略根据EG两步法(1.序列同阶单整2.OLS残差平稳)判断序列具有协整关系之后(若无协整关系则全平仓位不进行操作)

通过计算两个真实价格序列回归残差的0.9个标准差上下轨,并在价差突破上轨的时候做空价差,价差突破下轨的时候做多价差

并在回归至标准差水平内的时候平仓

回测数据为:SHFE.rb1801和SHFE.rb1805的1min数据

回测时间为:2017-09-25 08:00:00到2017-10-01 15:00:00

'''

# 协整检验的函数

def cointegration_test(series01, series02):

   urt_rb1801 = ts.adfuller(np.array(series01), 1)[1]

   urt_rb1805 = ts.adfuller(np.array(series01), 1)[1]

   # 同时平稳或不平稳则差分再次检验

   if (urt_rb1801 > 0.1 and urt_rb1805 > 0.1) or (urt_rb1801 < 0.1 and urt_rb1805 < 0.1):

       urt_diff_rb1801 = ts.adfuller(np.diff(np.array(series01)), 1)[1]

       urt_diff_rb1805 = ts.adfuller(np.diff(np.array(series01), 1))[1]

       # 同时差分平稳进行OLS回归的残差平稳检验

       if urt_diff_rb1801 < 0.1 and urt_diff_rb1805 < 0.1:

           matrix = np.vstack([series02, np.ones(len(series02))]).T

           beta, c = np.linalg.lstsq(matrix, series01)[0]

           resid = series01 - beta * series02 - c

           if ts.adfuller(np.array(resid), 1)[1] > 0.1:

               result = 0.0

           else:

               result = 1.0

           return beta, c, resid, result

       else:

           result = 0.0

           return 0.0, 0.0, 0.0, result

   else:

       result = 0.0

       return 0.0, 0.0, 0.0, result

def init(context):

   context.goods = ['SHFE.rb1801', 'SHFE.rb1805']

   # 订阅品种

   subscribe(symbols=context.goods, frequency='60s', count=801, wait_group=True)

def on_bar(context, bars):

   # 获取过去800个60s的收盘价数据

   close_01 = context.data(symbol=context.goods[0], frequency='60s', count=801, fields='close')['close'].values

   close_02 = context.data(symbol=context.goods[1], frequency='60s', count=801, fields='close')['close'].values

   # 展示两个价格序列的协整检验的结果

   beta, c, resid, result = cointegration_test(close_01, close_02)

   # 如果返回协整检验不通过的结果则全平仓位等待

   if not result:

       print('协整检验不通过,全平所有仓位')

       order_close_all()

       return

   # 计算残差的标准差上下轨

   mean = np.mean(resid)

   up = mean + 0.9 * np.std(resid)

   down = mean - 0.9 * np.std(resid)

   # 计算新残差

   resid_new = close_01[-1] - beta * close_02[-1] - c

   # 获取rb1801的多空仓位

   position_01_long = context.account().position(symbol=context.goods[0], side=PositionSide_Long)

   position_01_short = context.account().position(symbol=context.goods[0], side=PositionSide_Short)

   if not position_01_long and not position_01_short:

       # 上穿上轨时做空新残差

       if resid_new > up:

           order_target_volume(symbol=context.goods[0], volume=1, order_type=OrderType_Market,

                               position_side=PositionSide_Short)

           print(context.goods[0] + '以市价单开空仓1手')

           order_target_volume(symbol=context.goods[1], volume=1, order_type=OrderType_Market,

                               position_side=PositionSide_Long)

           print(context.goods[1] + '以市价单开多仓1手')

       # 下穿下轨时做多新残差

       if resid_new < down:

           order_target_volume(symbol=context.goods[0], volume=1, order_type=OrderType_Market,

                               position_side=PositionSide_Long)

           print(context.goods[0], '以市价单开多仓1手')

           order_target_volume(symbol=context.goods[1], volume=1, order_type=OrderType_Market,

                               position_side=PositionSide_Short)

           print(context.goods[1], '以市价单开空仓1手')

   # 新残差回归时平仓

   elif position_01_short:

       if resid_new <= up:

           order_close_all()

           print('价格回归,平掉所有仓位')

       # 突破下轨反向开仓

       if resid_new < down:

           order_target_volume(symbol=context.goods[0], volume=1, order_type=OrderType_Market,

                               position_side=PositionSide_Long)

           print(context.goods[0], '以市价单开多仓1手')

           order_target_volume(symbol=context.goods[1], volume=1, order_type=OrderType_Market,

                               position_side=PositionSide_Short)

           print(context.goods[1], '以市价单开空仓1手')

   elif position_01_long:

       if resid_new >= down:

           order_close_all()

           print('价格回归,平所有仓位')

       # 突破上轨反向开仓

       if resid_new > up:

           order_target_volume(symbol=context.goods[0], volume=1, order_type=OrderType_Market,

                               position_side=PositionSide_Short)

           print(context.goods[0], '以市价单开空仓1手')

           order_target_volume(symbol=context.goods[1], volume=1, order_type=OrderType_Market,

                               position_side=PositionSide_Long)

           print(context.goods[1], '以市价单开多仓1手')

if __name__ == '__main__':

   '''

   strategy_id策略ID,由系统生成

   filename文件名,请与本文件名保持一致

   mode实时模式:MODE_LIVE回测模式:MODE_BACKTEST

   token绑定计算机的ID,可在系统设置-密钥管理中生成

   backtest_start_time回测开始时间

   backtest_end_time回测结束时间

   backtest_adjust股票复权方式不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POST

   backtest_initial_cash回测初始资金

   backtest_commission_ratio回测佣金比例

   backtest_slippage_ratio回测滑点比例

   '''

   run(strategy_id='strategy_id',

       filename='main.py',

       mode=MODE_BACKTEST,

       token='token_id',

       backtest_start_time='2017-09-25 08:00:00',

       backtest_end_time='2017-10-01 16:00:00',

       backtest_adjust=ADJUST_PREV,

       backtest_initial_cash=500000,

       backtest_commission_ratio=0.0001,

       backtest_slippage_ratio=0.0001)



10

高频交易策略


高频交易是指从那些人们无法利用的极为短暂的市场变化中寻求获利的计算机化交易,比如,某种证券买入价和卖出价差价的微小变化,或者某只股票在不同交易所之间的微小价差。这种交易的速度如此之快,以至于有些交易机构将自己的“服务器群组”安置到了离交易所的计算机很近的地方,以缩短交易指令通过光缆以光速旅行的距离。(该策略源码模板暂无)




在量化江湖里,投资策略就像是各门各派的内功心法,只有合适的内功心法配合适合的武术招式,刻苦修炼,才能在江湖中闯出一片天地。


在投资界,正好有这么一个平台,陪你喂招切磋—— 传授秘诀高招。



“金融量化”交流群,微信扫码加入

量化投资/策略分析/金融数据/在线疑问/技术交流,欢迎进群



对冲基金与量化Alpha策略

4月全国开班

量化投资二维码.png

https://pmu.h5.xeknow.com/s/48Y8oy


二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:Alpha 对冲基金 Pha Fundamentals Fundamental

https://bbs.pinggu.org/thread-7300925-1-1.html

经管之家-黄金广告位商务合作15692935359
沙发
jinlu310 在职认证  发表于 2022-3-14 13:33:42 |只看作者 |坛友微信交流群
量化投资策略是利用量化的方法,进行金融市场的分析、判断和交易的策略、算法的总称。著名的量化投资策略有以下10种(注:策略源码模板不能直接用于实盘交易,仅供探讨交流)

使用道具

藤椅
jinlu310 在职认证  发表于 2022-3-14 13:34:29 |只看作者 |坛友微信交流群
对冲基金与量化Alpha策略

4月全国开班

量化投资二维码.png

https://pmu.h5.xeknow.com/s/48Y8oy

使用道具

板凳
xjg 发表于 2022-3-16 10:27:41 |只看作者 |坛友微信交流群

回帖奖励 +3 个论坛币

使用道具

报纸
ahc123 发表于 2022-4-10 15:27:11 |只看作者 |坛友微信交流群

回帖奖励 +3 个论坛币

使用道具

地板
jgzj2345 发表于 2022-4-10 17:27:22 |只看作者 |坛友微信交流群

回帖奖励 +3 个论坛币

代码非常详尽全面

使用道具

7
三江鸿 发表于 2022-5-15 00:40:34 来自手机 |只看作者 |坛友微信交流群

回帖奖励 +3 个论坛币

感谢分享

使用道具

8
ahc123 发表于 2022-5-17 13:22:03 |只看作者 |坛友微信交流群
,LP与GP

使用道具

9
stevensym 在职认证  发表于 2022-5-24 23:21:05 |只看作者 |坛友微信交流群
等到出来开班教课了,也就是这招不管用,赚不到钱的时候了。
能赚到钱,真会分享吗?

使用道具

10
八荒丶六合 发表于 2022-5-30 13:34:52 |只看作者 |坛友微信交流群

回帖奖励 +3 个论坛币

使用道具

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
加好友,备注jr
拉您进交流群

京ICP备16021002-2号 京B2-20170662号 京公网安备 11010802022788号 论坛法律顾问:王进律师 知识产权保护声明   免责及隐私声明

GMT+8, 2024-4-23 19:55