对冲基金与量化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月全国开班
https://pmu.h5.xeknow.com/s/48Y8oy