声明:本文策略源码均来自掘金量化示例策略库,仅供参考!

一、股票策略

1.多因子选股

# 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')print(order_target_percent(symbol='SHSE.600000', percent=0.5, order_type=OrderType_Market,position_side=PositionSide_Long))# 数据滑窗context.date = 20# 设置开仓的最大资金量context.ratio = 0.8# 账面市值比的大/中/小分类context.BM_BIG = 3.0context.BM_MID = 2.0context.BM_SMA = 1.0# 市值大/小分类context.MV_BIG = 2.0context.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'].valuesmv_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[i] * stock_return[i])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']]fin = get_fundamentals(table='tq_sk_finindic', 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.symbolx_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'].valuesstock_return = close[-1] / close[0] - 1pb = 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 = labelelse:x_return = np.vstack([x_return, label])stocks = DataFrame(data=x_return, columns=['symbol', 'return', 'BM', 'NEGOTIABLEMV', 'mv'])stocks.index = stocks.symbolcolumns = ['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)) / 3smb = 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)) / 2hml = hml_b - hml_sclose = 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'].valuesmarket_return = close[-1] / close[0] - 1coff_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_poolstocks = 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_BACKTESTtoken绑定计算机的ID,可在系统设置-密钥管理中生成backtest_start_time回测开始时间backtest_end_time回测结束时间backtest_adjust股票复权方式不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POSTbacktest_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)

2.日内回转交易

# coding=utf-8
from __future__ import print_function, absolute_import, unicode_literals
try:import talib
except:print('请安装TA-Lib库')
from gm.api import *
'''
本策略首先买入SHSE.600000股票10000股
随后根据60s的数据来计算MACD(12,26,9)线,并在MACD>0的时候买入100股,MACD<0的时候卖出100股
但每日操作的股票数不超过原有仓位,并于收盘前把仓位调整至开盘前的仓位
回测数据为:SHSE.600000的60s数据
回测时间为:2017-09-01 08:00:00到2017-10-01 16:00:00
'''
def init(context):# 设置标的股票context.symbol = 'SHSE.600000'# 用于判定第一个仓位是否成功开仓context.first = 0# 订阅浦发银行, bar频率为1minsubscribe(symbols=context.symbol, frequency='60s', count=35)# 日内回转每次交易100股context.trade_n = 100# 获取昨今天的时间context.day = [0, 0]# 用于判断是否触发了回转逻辑的计时context.ending = 0
def on_bar(context, bars):bar = bars[0]if context.first == 0:# 最开始配置仓位# 需要保持的总仓位context.total = 10000# 购买10000股浦发银行股票order_volume(symbol=context.symbol, volume=context.total, side=PositionSide_Long,order_type=OrderType_Market, position_effect=PositionEffect_Open)print(context.symbol, '以市价单开多仓10000股')context.first = 1.day = bar.bob.strftime('%Y-%m-%d')context.day[-1] = day[-2:]# 每天的仓位操作context.turnaround = [0, 0]return# 更新最新的日期day = bar.bob.strftime('%Y-%m-%d %H:%M:%S')context.day[0] = bar.bob.day# 若为新的一天,获取可用于回转的昨仓if context.day[0] != context.day[-1]:context.ending = 0context.turnaround = [0, 0]if context.ending == 1:return# 若有可用的昨仓则操作if context.total >= 0:# 获取时间序列数据symbol = bar['symbol']recent_data = context.data(symbol=symbol, frequency='60s', count=35, fields='close')# 计算MACD线macd = talib.MACD(recent_data['close'].values)[0][-1]# 根据MACD>0则开仓,小于0则平仓if macd > 0:# 多空单向操作都不能超过昨仓位,否则最后无法调回原仓位if context.turnaround[0] + context.trade_n < context.total:# 计算累计仓位context.turnaround[0] += context.trade_norder_volume(symbol=context.symbol, volume=context.trade_n, side=PositionSide_Long,order_type=OrderType_Market, position_effect=PositionEffect_Open)print(symbol, '市价单开多仓', context.trade_n, '股')elif macd < 0:if context.turnaround[1] + context.trade_n < context.total:context.turnaround[1] += context.trade_norder_volume(symbol=context.symbol, volume=context.trade_n, side=PositionSide_Short,order_type=OrderType_Market, position_effect=PositionEffect_Close)print(symbol, '市价单平多仓', context.trade_n, '股')# 临近收盘时若仓位数不等于昨仓则回转所有仓位if day[11:16] == '14:55' or day[11:16] == '14:57':position = context.account().position(symbol=context.symbol, side=PositionSide_Long)if position['volume'] != context.total:order_target_volume(symbol=context.symbol, volume=context.total, order_type=OrderType_Market,position_side=PositionSide_Long)print('市价单回转仓位操作...')context.ending = 1# 更新过去的日期数据context.day[-1] = context.day[0]
if __name__ == '__main__':'''strategy_id策略ID,由系统生成filename文件名,请与本文件名保持一致mode实时模式:MODE_LIVE回测模式:MODE_BACKTESTtoken绑定计算机的ID,可在系统设置-密钥管理中生成backtest_start_time回测开始时间backtest_end_time回测结束时间backtest_adjust股票复权方式不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POSTbacktest_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=2000000,backtest_commission_ratio=0.0001,backtest_slippage_ratio=0.0001)

3.指数增强

# 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.0context.ratio = 0.8# 获取沪深300当时的成份股和相关数据stock300 = get_history_constituents(index='SHSE.000300', start_date='2017-06-30', end_date='2017-06-30')[0]['constituents']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']).Tprint('选择的成分股权重总和为: ', 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.ratioorder_target_percent(symbol=symbol, percent=buy_percent, order_type=OrderType_Market,position_side=PositionSide_Long)print(symbol, '以市价单开多仓至仓位:', buy_percent)else:# 获取过去5天的价格数据,若连续上涨则为强势股,权重+0.2;若连续下跌则为弱势股,权重-0.2recent_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_BACKTESTtoken绑定计算机的ID,可在系统设置-密钥管理中生成backtest_start_time回测开始时间backtest_end_time回测结束时间backtest_adjust股票复权方式不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POSTbacktest_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)

4.行业轮动

# 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'].valuesreturn_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_BACKTESTtoken绑定计算机的ID,可在系统设置-密钥管理中生成backtest_start_time回测开始时间backtest_end_time回测结束时间backtest_adjust股票复权方式不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POSTbacktest_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)

5.集合竞价选股

# coding=utf-8
from __future__ import print_function, absolute_import, unicode_literals
from gm.api import *
'''
本策略通过获取SHSE.000300沪深300的成份股数据并统计其30天内
开盘价大于前收盘价的天数,并在该天数大于阈值10的时候加入股票池
随后对不在股票池的股票平仓并等权配置股票池的标的,每次交易间隔1个月.
回测数据为:SHSE.000300在2015-01-15的成份股
回测时间为: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.count_bench累计天数阙值context.count_bench = 10# 用于对比的天数context.count = 30# 最大交易资金比例context.ratio = 0.8
def algo(context):# 获取当前时间now = context.now# 获取上一个交易日last_day = get_previous_trading_date(exchange='SHSE', date=now)# 获取沪深300成份股context.stock300 = get_history_constituents(index='SHSE.000300', start_date=last_day,end_date=last_day)[0]['constituents'].keys()# 获取当天有交易的股票not_suspended_info = get_history_instruments(symbols=context.stock300, start_date=now, end_date=now)not_suspended_symbols = [item['symbol'] for item in not_suspended_info if not item['is_suspended']]trade_symbols = []if not not_suspended_symbols:print('没有当日交易的待选股票')returnfor stock in not_suspended_symbols:recent_data = history_n(symbol=stock, frequency='1d', count=context.count, fields='pre_close,open',fill_missing='Last', adjust=ADJUST_PREV, end_time=now, df=True)diff = recent_data['open'] - recent_data['pre_close']# 获取累计天数超过阙值的标的池.并剔除当天没有交易的股票if len(diff[diff > 0]) >= context.count_bench:trade_symbols.append(stock)print('本次股票池有股票数目: ', len(trade_symbols))# 计算权重percent = 1.0 / len(trade_symbols) * context.ratio# 获取当前所有仓位positions = context.account().positions()# 如标的池有仓位,平不在标的池的仓位for position in positions:symbol = position['symbol']if symbol not in trade_symbols:order_target_percent(symbol=symbol, percent=0, order_type=OrderType_Market,position_side=PositionSide_Long)print('市价单平不在标的池的', symbol)# 对标的池进行操作for symbol in trade_symbols: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_BACKTESTtoken绑定计算机的ID,可在系统设置-密钥管理中生成backtest_start_time回测开始时间backtest_end_time回测结束时间backtest_adjust股票复权方式不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POSTbacktest_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)

6.机器学习

# coding=utf-8
from __future__ import print_function, absolute_import, unicode_literals
from datetime import datetime
import numpy as np
from gm.api import *
import sys
try:from sklearn import svm
except:print('请安装scikit-learn库和带mkl的numpy')sys.exit(-1)
'''
本策略选取了七个特征变量组成了滑动窗口长度为15天的训练集,随后训练了一个二分类(上涨/下跌)的支持向量机模型.
若没有仓位则在每个星期一的时候输入标的股票近15个交易日的特征变量进行预测,并在预测结果为上涨的时候购买标的.
若已经持有仓位则在盈利大于10%的时候止盈,在星期五损失大于2%的时候止损.
特征变量为:1.收盘价/均值2.现量/均量3.最高价/均价4.最低价/均价5.现量6.区间收益率7.区间标准差
训练数据为:SHSE.600000浦发银行,时间从2016-03-01到2017-06-30
回测时间为:2017-07-01 09:00:00到2017-10-01 09:00:00
'''
def init(context):# 订阅浦发银行的分钟bar行情context.symbol = 'SHSE.600000'subscribe(symbols=context.symbol, frequency='60s')start_date = '2016-03-01'  # SVM训练起始时间end_date = '2017-06-30'  # SVM训练终止时间# 用于记录工作日# 获取目标股票的daily历史行情recent_data = history(context.symbol, frequency='1d', start_time=start_date, end_time=end_date, fill_missing='last',df=True)days_value = recent_data['bob'].valuesdays_close = recent_data['close'].valuesdays = []# 获取行情日期列表print('准备数据训练SVM')for i in range(len(days_value)):days.append(str(days_value[i])[0:10])x_all = []y_all = []for index in range(15, (len(days) - 5)):# 计算三星期共15个交易日相关数据start_day = days[index - 15]end_day = days[index]data = history(context.symbol, frequency='1d', start_time=start_day, end_time=end_day, fill_missing='last',df=True)close = data['close'].valuesmax_x = data['high'].valuesmin_n = data['low'].valuesamount = data['amount'].valuesvolume = []for i in range(len(close)):volume_temp = amount[i] / close[i]volume.append(volume_temp)close_mean = close[-1] / np.mean(close)  # 收盘价/均值volume_mean = volume[-1] / np.mean(volume)  # 现量/均量max_mean = max_x[-1] / np.mean(max_x)  # 最高价/均价min_mean = min_n[-1] / np.mean(min_n)  # 最低价/均价vol = volume[-1]  # 现量return_now = close[-1] / close[0]  # 区间收益率std = np.std(np.array(close), axis=0)  # 区间标准差# 将计算出的指标添加到训练集X# features用于存放因子features = [close_mean, volume_mean, max_mean, min_mean, vol, return_now, std]x_all.append(features)# 准备算法需要用到的数据for i in range(len(days_close) - 20):if days_close[i + 20] > days_close[i + 15]:label = 1else:label = 0y_all.append(label)x_train = x_all[: -1]y_train = y_all[: -1]# 训练SVMcontext.clf = svm.SVC(C=1.0, kernel='rbf', degree=3, gamma='auto', coef0=0.0, shrinking=True, probability=False,tol=0.001, cache_size=200, verbose=False, max_iter=-1,decision_function_shape='ovr', random_state=None)context.clf.fit(x_train, y_train)print('训练完成!')
def on_bar(context, bars):bar = bars[0]# 获取当前年月日today = bar.bob.strftime('%Y-%m-%d')# 获取数据并计算相应的因子# 于星期一的09:31:00进行操作# 当前bar的工作日weekday = datetime.strptime(today, '%Y-%m-%d').isoweekday()# 获取模型相关的数据# 获取持仓position = context.account().position(symbol=context.symbol, side=PositionSide_Long)# 如果bar是新的星期一且没有仓位则开始预测if not position and weekday == 1:# 获取预测用的历史数据data = history_n(symbol=context.symbol, frequency='1d', end_time=today, count=15,fill_missing='last', df=True)close = data['close'].valuestrain_max_x = data['high'].valuestrain_min_n = data['low'].valuestrain_amount = data['amount'].valuesvolume = []for i in range(len(close)):volume_temp = train_amount[i] / close[i]volume.append(volume_temp)close_mean = close[-1] / np.mean(close)volume_mean = volume[-1] / np.mean(volume)max_mean = train_max_x[-1] / np.mean(train_max_x)min_mean = train_min_n[-1] / np.mean(train_min_n)vol = volume[-1]return_now = close[-1] / close[0]std = np.std(np.array(close), axis=0)# 得到本次输入模型的因子features = [close_mean, volume_mean, max_mean, min_mean, vol, return_now, std]features = np.array(features).reshape(1, -1)prediction = context.clf.predict(features)[0]# 若预测值为上涨则开仓if prediction == 1:# 获取昨收盘价context.price = close[-1]# 把浦发银行的仓位调至95%order_target_percent(symbol=context.symbol, percent=0.95, order_type=OrderType_Market,position_side=PositionSide_Long)print('SHSE.600000以市价单开多仓到仓位0.95')# 当涨幅大于10%,平掉所有仓位止盈elif position and bar.close / context.price >= 1.10:order_close_all()print('SHSE.600000以市价单全平多仓止盈')# 当时间为周五并且跌幅大于2%时,平掉所有仓位止损elif position and bar.close / context.price < 1.02 and weekday == 5:order_close_all()print('SHSE.600000以市价单全平多仓止损')
if __name__ == '__main__':'''strategy_id策略ID,由系统生成filename文件名,请与本文件名保持一致mode实时模式:MODE_LIVE回测模式:MODE_BACKTESTtoken绑定计算机的ID,可在系统设置-密钥管理中生成backtest_start_time回测开始时间backtest_end_time回测结束时间backtest_adjust股票复权方式不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POSTbacktest_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 09:00:00',backtest_end_time='2017-10-01 09:00:00',backtest_adjust=ADJUST_PREV,backtest_initial_cash=10000000,backtest_commission_ratio=0.0001,backtest_slippage_ratio=0.0001)

7.配对交易

# coding=utf-8
from __future__ import print_function, absolute_import, unicode_literals
from gm.api import *
import  numpy as npdef init(context):#获得N日股票交易数据context.N=5#选择一对股票context.stock=['SZSE.000651','SZSE.000333']# 每个交易日的09:40 定时执行algo任务schedule(schedule_func=algo, date_rule='1d', time_rule='09:40:00')def algo(context):# 获取上一个交易日的日期last_day = get_previous_trading_date(exchange='SHSE', date=context.now)# 获取当天有交易的股票,似乎无法同时获得两只股票的数据,所以只能麻烦一点not_suspended = get_history_instruments(symbols=context.stock[0], start_date=last_day, end_date=last_day)a = len([item['symbol'] for item in not_suspended if not item['is_suspended']])not_suspended = get_history_instruments(symbols=context.stock[1], start_date=last_day,end_date=last_day)b = len([item['symbol'] for item in not_suspended if not item['is_suspended']])#如果有一支停牌,就跳过if a+b<2:return#获得交易数据prices1 = history_n(symbol=context.stock[0], frequency='1d', count=context.N, end_time=last_day, fields='close',skip_suspended=True,fill_missing=None, adjust=ADJUST_PREV, adjust_end_time='', df=True)prices2=history_n(symbol=context.stock[1], frequency='1d', count=context.N, end_time=last_day, fields='close',skip_suspended=True,fill_missing=None, adjust=ADJUST_PREV, adjust_end_time='', df=True)p1=list(prices1['close'])p2=list(prices2['close'])spread = np.array(p1[:-1]) - np.array(p2[:-1])# 计算布林带的上下轨up = np.mean(spread) + 2 * np.std(spread)down = np.mean(spread) - 2 * np.std(spread)# 计算最新价差spread_now = p1[-1] - p2[-1]# 无交易时若价差上(下)穿布林带上(下)轨则做空(多)价差position_s1_long = context.account().position(symbol=context.stock[0], side=PositionSide_Long)position_s2_long = context.account().position(symbol=context.stock[1], side=PositionSide_Long)if not position_s1_long and not position_s2_long:if spread_now > up:order_target_percent(symbol=context.stock[1], percent=0.5, order_type=OrderType_Market,position_side=PositionSide_Long)if spread_now < down:order_target_percent(symbol=context.stock[0], percent=0.5, order_type=OrderType_Market,position_side=PositionSide_Long)# 价差回归时平仓elif position_s2_long:if spread_now <= up:order_close_all()elif position_s1_long:if spread_now >= down:order_close_all()if __name__ == '__main__':'''strategy_id策略ID,由系统生成filename文件名,请与本文件名保持一致mode实时模式:MODE_LIVE回测模式:MODE_BACKTESTtoken绑定计算机的ID,可在系统设置-密钥管理中生成backtest_start_time回测开始时间backtest_end_time回测结束时间backtest_adjust股票复权方式不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POSTbacktest_initial_cash回测初始资金backtest_commission_ratio回测佣金比例backtest_slippage_ratio回测滑点比例'''run(strategy_id='73bb5bf2-a536-11e8-bd52-9cd21ef04ea9',filename='配对交易.py',mode=MODE_BACKTEST,token='c395247a76e8a5caeee699d668d6f550213bc418',backtest_start_time='2014-01-01 08:00:00',backtest_end_time='2018-08-01 16:00:00',backtest_adjust=ADJUST_PREV,backtest_initial_cash=10000000,backtest_commission_ratio=0.0001,backtest_slippage_ratio=0.0001)

8.GARP策略

# coding=utf-8
from __future__ import print_function, absolute_import, unicode_literals
from gm.api import *
from sklearn import preprocessing'''
策略思路:
1、公司的资产负债率小于等于 25%
2、公司每股净现金大于 0
3、当前股价与每股自由现金流量比小于 10(市现率)
4、在所有股票中取市盈率排倒数30%的股票(首先PE必须大于0)
5、PEG=市盈率/净利润增长率<0.5
回测数据:SHSE.000906的成份股
回测时间:2016-01-01 08:00:00到2018-01-01 16:00:00
'''def init(context):# 每月第一个交易日的09:40 定时执行algo任务schedule(schedule_func=algo, date_rule='1m', time_rule='09:40:00')def algo(context):# 获取上一个交易日的日期last_day = get_previous_trading_date(exchange='SHSE', date=context.now)# 获取沪深300成份股stock800 = get_history_constituents(index='SHSE.000906', start_date=last_day,end_date=last_day)[0]['constituents'].keys()# 获取当天有交易的股票not_suspended = get_history_instruments(symbols=stock800, start_date=last_day, end_date=last_day)not_suspended = [item['symbol'] for item in not_suspended if not item['is_suspended']]df = get_fundamentals(table='deriv_finance_indicator', symbols=not_suspended, start_date=last_day, end_date=last_day,fields='ASSLIABRT,NCFPS,NPGRT', df=True)fin=get_fundamentals(table='trading_derivative_indicator', symbols=not_suspended, start_date=last_day, end_date=last_day,fields='PCLFY,PELFY', df=True)df['PCLFY']=fin['PCLFY']df['PELFY'] = fin['PELFY']# 除去空值df = df.dropna()df['PEG']=df['PELFY']/df['NPGRT']df.index=df.symboldel df['symbol'],df['pub_date'],df['end_date']print(df)# 选出PEG小于0.5的部分df = df[df['PEG'] < 0.5]# 选出债务总资产比小于0.25的部分df = df[df["ASSLIABRT"] < 25]# 选出每股净现金大于 0的部分df = df[df["NCFPS"] > 0]# 选出市盈率大于零的部分df = df[df['PELFY'] > 0]# 选出市现率小于10的部分df = df[df['PCLFY'] < 10]print(df)# 剔除市盈率较高的股票(即剔除3分位数以后的股票)if len(df)<4:symbols_pool = list(df.index)else:df = df[(df['PELFY'] < df['PELFY'].quantile(0.3))]symbols_pool = list(df.index)print(symbols_pool)order_close_all()long=len(symbols_pool)if long==0:return# 获取股票的权重percent = 1 / long# 买在标的池中的股票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_BACKTESTtoken绑定计算机的ID,可在系统设置-密钥管理中生成backtest_start_time回测开始时间backtest_end_time回测结束时间backtest_adjust股票复权方式不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POSTbacktest_initial_cash回测初始资金backtest_commission_ratio回测佣金比例backtest_slippage_ratio回测滑点比例'''run(strategy_id='73bb5bf2-a536-11e8-bd52-9cd21ef04ea9',filename='GARP.py',mode=MODE_BACKTEST,token='c395247a76e8a5caeee699d668d6f550213bc418',backtest_start_time='2016-01-01 08:00:00',backtest_end_time='2018-01-01 16:00:00',backtest_adjust=ADJUST_PREV,backtest_initial_cash=10000000,backtest_commission_ratio=0.0001,backtest_slippage_ratio=0.0001)

9.alpha对冲(股票+期货)

# coding=utf-8
from __future__ import print_function, absolute_import, unicode_literals
from gm.api import *
'''
本策略每隔1个月定时触发计算SHSE.000300成份股的过去的EV/EBITDA并选取EV/EBITDA大于0的股票
随后平掉排名EV/EBITDA不在最小的30的股票持仓并等权购买EV/EBITDA最小排名在前30的股票
并用相应的CFFEX.IF对应的真实合约等额对冲
回测数据为:SHSE.000300和他们的成份股和CFFEX.IF对应的真实合约
回测时间为:2017-07-01 08:00:00到2017-10-01 16:00:00
'''
def init(context):# 每月第一个交易日09:40:00的定时执行algo任务schedule(schedule_func=algo, date_rule='1m', time_rule='09:40:00')# 设置开仓在股票和期货的资金百分比(期货在后面自动进行杠杆相关的调整)context.percentage_stock = 0.4context.percentage_futures = 0.4
def algo(context):# 获取当前时刻now = context.now# 获取上一个交易日last_day = get_previous_trading_date(exchange='SHSE', date=now)# 获取沪深300成份股stock300 = get_history_constituents(index='SHSE.000300', start_date=last_day,end_date=last_day)[0]['constituents'].keys()# 获取上一个工作日的CFFEX.IF对应的合约index_futures = get_continuous_contracts(csymbol='CFFEX.IF', start_date=last_day, end_date=last_day)[-1]['symbol']# 获取当天有交易的股票not_suspended_info = get_history_instruments(symbols=stock300, start_date=now, end_date=now)not_suspended_symbols = [item['symbol'] for item in not_suspended_info if not item['is_suspended']]# 获取成份股EV/EBITDA大于0并为最小的30个fin = get_fundamentals(table='tq_sk_finindic', symbols=not_suspended_symbols,start_date=now, end_date=now, fields='EVEBITDA',filter='EVEBITDA>0', order_by='EVEBITDA', limit=30, df=True)fin.index = fin.symbol# 获取当前仓位positions = context.account().positions()# 平不在标的池或不为当前股指期货主力合约对应真实合约的标的for position in positions:symbol = position['symbol']sec_type = get_instrumentinfos(symbols=symbol)[0]['sec_type']# 若类型为期货且不在标的池则平仓if sec_type == SEC_TYPE_FUTURE and symbol != index_futures:order_target_percent(symbol=symbol, percent=0, order_type=OrderType_Market,position_side=PositionSide_Short)print('市价单平不在标的池的', symbol)elif symbol not in fin.index:order_target_percent(symbol=symbol, percent=0, order_type=OrderType_Market,position_side=PositionSide_Long)print('市价单平不在标的池的', symbol)# 获取股票的权重percent = context.percentage_stock / len(fin.index)# 买在标的池中的股票for symbol in fin.index:order_target_percent(symbol=symbol, percent=percent, order_type=OrderType_Market,position_side=PositionSide_Long)print(symbol, '以市价单调多仓到仓位', percent)# 获取股指期货的保证金比率ratio = get_history_instruments(symbols=index_futures, start_date=last_day, end_date=last_day)[0]['margin_ratio']# 更新股指期货的权重percent = context.percentage_futures * ratio# 买入股指期货对冲order_target_percent(symbol=index_futures, percent=percent, order_type=OrderType_Market,position_side=PositionSide_Short)print(index_futures, '以市价单调空仓到仓位', percent)
if __name__ == '__main__':'''strategy_id策略ID,由系统生成filename文件名,请与本文件名保持一致mode实时模式:MODE_LIVE回测模式:MODE_BACKTESTtoken绑定计算机的ID,可在系统设置-密钥管理中生成backtest_start_time回测开始时间backtest_end_time回测结束时间backtest_adjust股票复权方式不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POSTbacktest_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)

二、期货策略

1.双均线策略

# 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)# 获取数据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_BACKTESTtoken绑定计算机的ID,可在系统设置-密钥管理中生成backtest_start_time回测开始时间backtest_end_time回测结束时间backtest_adjust股票复权方式不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POSTbacktest_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)

2.网格交易

# coding=utf-8
from __future__ import print_function, absolute_import, unicode_literals
import numpy as np
import pandas as pd
from gm.api import *
'''
本策略首先计算了过去300个价格数据的均值和标准差
并根据均值加减1和2个标准差得到网格的区间分界线,
并分别配以0.3和0.5的仓位权重
然后根据价格所在的区间来配置仓位(+/-40为上下界,无实际意义):
(-40,-3],(-3,-2],(-2,2],(2,3],(3,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频率为1minsubscribe(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_Long)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_Short)print(context.symbol, '以市价单开空仓到仓位', context.weight[grid])# 持有多仓的处理elif position_long:if grid >= 3: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_Long)print(context.symbol, '以市价单全平多仓')# 小于1为在中间网格的下方,做空elif grid <= 1: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])# 持有空仓的处理elif position_short:# 小于1为在中间网格的下方,做空if grid <= 1: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_Short)print(context.symbol, '以市价单全平空仓')# 大于3为在中间网格的上方,做多elif grid >= 3: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])
if __name__ == '__main__':'''strategy_id策略ID,由系统生成filename文件名,请与本文件名保持一致mode实时模式:MODE_LIVE回测模式:MODE_BACKTESTtoken绑定计算机的ID,可在系统设置-密钥管理中生成backtest_start_time回测开始时间backtest_end_time回测结束时间backtest_adjust股票复权方式不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POSTbacktest_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)

 3.跨品种套利

# coding=utf-8
from __future__ import print_function, absolute_import, unicode_literals
from gm.api import *
import numpy as np
'''
本策略根据计算滚动的.过去的30个1min的bar的均值正负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=31, 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.valuesdata_hc = context.data(symbol=context.goods[1], frequency='60s', count=31, fields='close')close_hc = data_hc.values# 计算价差spread = close_rb[:-1] - close_hc[:-1]# 计算布林带的上下轨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_BACKTESTtoken绑定计算机的ID,可在系统设置-密钥管理中生成backtest_start_time回测开始时间backtest_end_time回测结束时间backtest_adjust股票复权方式不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POSTbacktest_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)

4.跨期套利

# 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))]).Tbeta, c = np.linalg.lstsq(matrix, series01)[0]resid = series01 - beta * series02 - cif ts.adfuller(np.array(resid), 1)[1] > 0.1:result = 0.0else:result = 1.0return beta, c, resid, resultelse:result = 0.0return 0.0, 0.0, 0.0, resultelse:result = 0.0return 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'].valuesclose_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_BACKTESTtoken绑定计算机的ID,可在系统设置-密钥管理中生成backtest_start_time回测开始时间backtest_end_time回测结束时间backtest_adjust股票复权方式不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POSTbacktest_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)

5.海龟交易法

# 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频率为1minsubscribe(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]# 计算ATRatr = talib.ATR(recent_data['high'].values, recent_data['low'].values, recent_data['close'].values,timeperiod=context.tar)[-1]# 计算唐奇安开仓和平仓通道context.don_open = context.parameter[0] + 1upper_band = talib.MAX(recent_data['close'].values[:-1], timeperiod=context.don_open)[-1]context.don_close = context.parameter[1] + 1lower_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线.DIFma_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]) * atrgrid_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]) * atrgrid_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_BACKTESTtoken绑定计算机的ID,可在系统设置-密钥管理中生成backtest_start_time回测开始时间backtest_end_time回测结束时间backtest_adjust股票复权方式不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POSTbacktest_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)

6.做市商交易

# coding=utf-8
from __future__ import print_function, absolute_import, unicode_literals
from gm.api import *
'''
本策略通过不断对CZCE.CF801进行:
买(卖)一价现价单开多(空)仓和卖(买)一价平多(空)仓来做市
并以此赚取差价
回测数据为:CZCE.CF801的tick数据
回测时间为:2017-09-29 11:25:00到2017-09-29 11:30:00
需要特别注意的是:本平台对于回测对限价单固定完全成交,本例子 仅供参考.
敬请通过适当调整回测参数
1.backtest_commission_ratio回测佣金比例
2.backtest_slippage_ratio回测滑点比例
3.backtest_transaction_ratio回测成交比例
以及优化策略逻辑来达到更贴近实际的回测效果
'''
def init(context):# 订阅CZCE.CF801的tick数据context.symbol = 'CZCE.CF801'subscribe(symbols=context.symbol, frequency='tick')
def on_tick(context, tick):quotes = tick['quotes'][0]# 获取持有的多仓positio_long = context.account().position(symbol=context.symbol, side=PositionSide_Long)# 获取持有的空仓position_short = context.account().position(symbol=context.symbol, side=PositionSide_Short)print(quotes['bid_p'])print(quotes['ask_p'])# 没有仓位则双向开限价单# 若有仓位则限价单平仓if not positio_long:# 获取买一价price = quotes['bid_p']print('买一价为: ', price)order_target_volume(symbol=context.symbol, volume=1, price=price, order_type=OrderType_Limit,position_side=PositionSide_Long)print('CZCE.CF801开限价单多仓1手')else:# 获取卖一价price = quotes['ask_p']print('卖一价为: ', price)order_target_volume(symbol=context.symbol, volume=0, price=price, order_type=OrderType_Limit,position_side=PositionSide_Long)print('CZCE.CF801平限价单多仓1手')if not position_short:# 获取卖一价price = quotes['ask_p']print('卖一价为: ', price)order_target_volume(symbol=context.symbol, volume=1, price=price, order_type=OrderType_Limit,position_side=PositionSide_Short)print('CZCE.CF801卖一价开限价单空仓')else:# 获取买一价price = quotes['bid_p']print('买一价为: ', price)order_target_volume(symbol=context.symbol, volume=0, price=price, order_type=OrderType_Limit,position_side=PositionSide_Short)print('CZCE.CF801买一价平限价单空仓')
if __name__ == '__main__':'''strategy_id策略ID,由系统生成filename文件名,请与本文件名保持一致mode实时模式:MODE_LIVE回测模式:MODE_BACKTESTtoken绑定计算机的ID,可在系统设置-密钥管理中生成backtest_start_time回测开始时间backtest_end_time回测结束时间backtest_adjust股票复权方式不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POSTbacktest_initial_cash回测初始资金backtest_commission_ratio回测佣金比例backtest_slippage_ratio回测滑点比例backtest_transaction_ratio回测成交比例'''run(strategy_id='strategy_id',filename='main.py',mode=MODE_BACKTEST,token='token_id',backtest_start_time='2017-09-29 11:25:00',backtest_end_time='2017-09-29 11:30:00',backtest_adjust=ADJUST_PREV,backtest_initial_cash=500000,backtest_commission_ratio=0.00006,backtest_slippage_ratio=0.0001,backtest_transaction_ratio=0.5)

三、其他

1.MACD策略

# -*- coding: utf-8 -*-# 简便起见,可以直接用 from gm.api import *
from gm.api import run
from gm.api import ADJUST_PREV
from gm.api import MODE_BACKTEST
from gm.api import subscribe
from gm.api import history_n
from gm.api import order_percent
from gm.api import order_volume
from gm.api import (OrderSide_Buy, OrderSide_Sell)
from gm.api import (PositionEffect_Open, PositionEffect_Close)
from gm.api import OrderType_Market
from datetime import datetime
from datetime import timedelta
import talib
import numpy as np
from collections import deque# 常用参量设置
DATE_STR = "%Y-%m-%d"
TIME_STR = "%Y-%m-%d %H:%M:%S"HIST_WINDOW = 40
SHORT_PERIOD = 5
LONG_PERIOD = 20def init(context):# 全局变量设置context.dict_stock_price = dict()# 以 50 EFT作为交易标的context.stock_pool = ['SZSE.000001']# 订阅日线行情subscribe(symbols=context.stock_pool, frequency='1d', wait_group=True)# 日期设定,避免出现未来函数,将起始日往前取一日start_date = datetime.strptime(context.backtest_start_time, TIME_STR)context.start_date = datetime.strftime(start_date - timedelta(days=1),TIME_STR)# 获取起始日之前行情,便于计算指标deque_high = deque(maxlen=HIST_WINDOW)deque_low = deque(maxlen=HIST_WINDOW)deque_close = deque(maxlen=HIST_WINDOW)for stock in context.stock_pool:history_info = history_n(symbol=stock, frequency='1d', count=HIST_WINDOW,adjust=ADJUST_PREV,adjust_end_time=context.backtest_end_time,end_time=context.start_date,fields='high, low, close')for bar in history_info:deque_high.append(bar['high'])deque_low.append(bar['low'])deque_close.append(bar['close'])context.dict_stock_price.setdefault(stock, [deque_high, deque_low, deque_close])print('finish initialization')def on_bar(context, bars):for bar in bars:if bar.symbol not in context.dict_stock_price.keys():print('Warning: cannot obtain price of stock {} at date {}'.format(bar.symbol, context.now))# 数据填充context.dict_stock_price[bar.symbol][0].append(bar.high)context.dict_stock_price[bar.symbol][1].append(bar.low)context.dict_stock_price[bar.symbol][2].append(bar.close)# 计算指标,这里以双均线为例# highs = np.array(context.dict_stock_price[bar.symbol][0])# lows = np.array(context.dict_stock_price[bar.symbol][1])closes = np.array(context.dict_stock_price[bar.symbol][2])macd, macd_signal, macd_hist = talib.MACD(closes, fastperiod=12, slowperiod=26, signalperiod=9)# 金叉,满仓买入if macd_hist[-2] <= 0 and macd_hist[-1] > 0:order_percent(symbol=bar.symbol,percent=1.0,side=OrderSide_Buy,order_type=OrderType_Market,position_effect=PositionEffect_Open,price=0)print(context.now)# 死叉,全部卖出pos = context.account().position(symbol=bar.symbol, side=OrderSide_Buy)if (macd_hist[-2] >= 0 and macd_hist[-1] < 0):if pos is None:continueorder_volume(symbol=bar.symbol,volume=pos.volume,side=OrderSide_Sell,order_type=OrderType_Market,position_effect=PositionEffect_Close,price=0)if __name__ == "__main__":run(strategy_id='569b4ffc-6d44-11e8-bd88-80ce62334e41',filename='demo_04.py',mode=MODE_BACKTEST,backtest_adjust=ADJUST_PREV,token='64c33fc82f334e11e1138eefea8ffc241db4a2a0',backtest_start_time='2017-01-17 09:00:00',backtest_end_time='2018-06-21 15:00:00')

2.KD策略

# -*- coding: utf-8 -*-#本策略基于掘金量化交易平台 网址:www.myquant.cn# 简便起见,可以直接用 from gm.api import *
from gm.api import run
from gm.api import ADJUST_PREV
from gm.api import MODE_BACKTEST
from gm.api import subscribe
from gm.api import history_n
from gm.api import order_percent
from gm.api import order_volume
from gm.api import (OrderSide_Buy, OrderSide_Sell)
from gm.api import (PositionEffect_Open, PositionEffect_Close)
from gm.api import OrderType_Market
from datetime import datetime
from datetime import timedelta
import talib
import numpy as np
from collections import deque# 常用参量设置
DATE_STR = "%Y-%m-%d"
TIME_STR = "%Y-%m-%d %H:%M:%S"HIST_WINDOW = 30
SHORT_PERIOD = 5
LONG_PERIOD = 20def init(context):# 全局变量设置context.dict_stock_price = dict()# 以 50 EFT作为交易标的context.stock_pool = ['SZSE.000001']# 订阅日线行情subscribe(symbols=context.stock_pool, frequency='1d', wait_group=True)# 日期设定,避免出现未来函数,将起始日往前取一日start_date = datetime.strptime(context.backtest_start_time, TIME_STR)context.start_date = datetime.strftime(start_date - timedelta(days=1),TIME_STR)# 获取起始日之前行情,便于计算指标deque_high = deque(maxlen=HIST_WINDOW)deque_low = deque(maxlen=HIST_WINDOW)deque_close = deque(maxlen=HIST_WINDOW)for stock in context.stock_pool:history_info = history_n(symbol=stock, frequency='1d', count=HIST_WINDOW,adjust=ADJUST_PREV,adjust_end_time=context.backtest_end_time,end_time=context.start_date,fields='high, low, close')for bar in history_info:deque_high.append(bar['high'])deque_low.append(bar['low'])deque_close.append(bar['close'])context.dict_stock_price.setdefault(stock, [deque_high, deque_low, deque_close])print('finish initialization')def on_bar(context, bars):for bar in bars:if bar.symbol not in context.dict_stock_price.keys():print('Warning: cannot obtain price of stock {} at date {}'.format(bar.symbol, context.now))# 数据填充context.dict_stock_price[bar.symbol][0].append(bar.high)context.dict_stock_price[bar.symbol][1].append(bar.low)context.dict_stock_price[bar.symbol][2].append(bar.close)# 计算指标,这里以双均线为例highs = np.array(context.dict_stock_price[bar.symbol][0])lows = np.array(context.dict_stock_price[bar.symbol][1])closes = np.array(context.dict_stock_price[bar.symbol][2])k_value, d_value = talib.STOCH(highs,lows,closes,fastk_period=9,slowk_period=3,slowk_matype=0,slowd_period=3,slowd_matype=0)# 金叉,满仓买入if k_value[-2] <= d_value[-2] and k_value[-1] > d_value[-1]:order_percent(symbol=bar.symbol,percent=1.0,side=OrderSide_Buy,order_type=OrderType_Market,position_effect=PositionEffect_Open,price=0)print(context.now)# 死叉,全部卖出pos = context.account().position(symbol=bar.symbol, side=OrderSide_Buy)if k_value[-2] >= d_value[-2] and k_value[-1] < d_value[-1]:if pos is None:continueorder_volume(symbol=bar.symbol,volume=pos.volume,side=OrderSide_Sell,order_type=OrderType_Market,position_effect=PositionEffect_Close,price=0)if __name__ == "__main__":run(strategy_id='569b4ffc-6d44-11e8-bd88-80ce62334e41',filename='demo_02.py',mode=MODE_BACKTEST,backtest_adjust=ADJUST_PREV,token='64c33fc82f334e11e1138eefea8ffc241db4a2a0',backtest_start_time='2017-01-17 09:00:00',backtest_end_time='2018-06-21 15:00:00')

3.双均线加上MACD过滤

# -*- coding: utf-8 -*-# 简便起见,可以直接用 from gm.api import *
from gm.api import run
from gm.api import ADJUST_PREV
from gm.api import MODE_BACKTEST
from gm.api import subscribe
from gm.api import history_n
from gm.api import order_percent
from gm.api import order_volume
from gm.api import (OrderSide_Buy, OrderSide_Sell)
from gm.api import (PositionEffect_Open, PositionEffect_Close)
from gm.api import OrderType_Market
from datetime import datetime
from datetime import timedelta
import talib
import numpy as np
from collections import deque# 常用参量设置
DATE_STR = "%Y-%m-%d"
TIME_STR = "%Y-%m-%d %H:%M:%S"HIST_WINDOW = 40
SHORT_PERIOD = 5
LONG_PERIOD = 20def init(context):# 全局变量设置context.dict_stock_price = dict()# 以 50 EFT作为交易标的context.stock_pool = ['SHSE.600000']# 订阅日线行情subscribe(symbols=context.stock_pool, frequency='1d', wait_group=True)# 日期设定,避免出现未来函数,将起始日往前取一日start_date = datetime.strptime(context.backtest_start_time, TIME_STR)context.start_date = datetime.strftime(start_date - timedelta(days=1),TIME_STR)# 获取起始日之前行情,便于计算指标deque_close = deque(maxlen=HIST_WINDOW)for stock in context.stock_pool:history_info = history_n(symbol=stock, frequency='1d', count=HIST_WINDOW,adjust=ADJUST_PREV,adjust_end_time=context.backtest_end_time,end_time=context.start_date,fields='close')for bar in history_info:deque_close.append(bar['close'])context.dict_stock_price.setdefault(stock, deque_close)print('finish initialization')def on_bar(context, bars):for bar in bars:if bar.symbol not in context.dict_stock_price.keys():print('Warning: cannot obtain price of stock {} at date {}'.format(bar.symbol, context.now))# 数据填充context.dict_stock_price[bar.symbol].append(bar.close)# 计算指标,这里以双均线为例closes = np.array(context.dict_stock_price[bar.symbol])short_ma = talib.SMA(closes, SHORT_PERIOD)long_ma = talib.SMA(closes, LONG_PERIOD)macd, macd_signal, macd_hist = talib.MACD(closes, fastperiod=12, slowperiod=26, signalperiod=9)# 金叉,满仓买入if short_ma[-2] <= long_ma[-2] and short_ma[-1] > long_ma[-1]:order_percent(symbol=bar.symbol,percent=1.0,side=OrderSide_Buy,order_type=OrderType_Market,position_effect=PositionEffect_Open,price=0)print(context.now)# 死叉或者 MACD 绿柱,全部卖出pos = context.account().position(symbol=bar.symbol, side=OrderSide_Buy)if (short_ma[-2] >= long_ma[-2] and short_ma[-1] < long_ma[-1]) or \macd_hist[-1] < 0:if pos is None:continueorder_volume(symbol=bar.symbol,volume=pos.volume,side=OrderSide_Sell,order_type=OrderType_Market,position_effect=PositionEffect_Close,price=0)
if __name__ == "__main__":run(strategy_id='569b4ffc-6d44-11e8-bd88-80ce62334e41',filename='demo_05.py',mode=MODE_BACKTEST,backtest_adjust=ADJUST_PREV,token='64c33fc82f334e11e1138eefea8ffc241db4a2a0',backtest_start_time='2017-01-17 09:00:00',backtest_end_time='2018-06-21 15:00:00')

4.KDJ中J值策略

# -*- coding: utf-8 -*-#本策略基于掘金量化交易平台 网址:www.myquant.cn# 简便起见,可以直接用 from gm.api import *
from gm.api import run
from gm.api import ADJUST_PREV
from gm.api import MODE_BACKTEST
from gm.api import subscribe
from gm.api import history_n
from gm.api import order_percent
from gm.api import order_volume
from gm.api import (OrderSide_Buy, OrderSide_Sell)
from gm.api import (PositionEffect_Open, PositionEffect_Close)
from gm.api import OrderType_Market
from datetime import datetime
from datetime import timedelta
import talib
import numpy as np
from collections import deque# 常用参量设置
DATE_STR = "%Y-%m-%d"
TIME_STR = "%Y-%m-%d %H:%M:%S"HIST_WINDOW = 30
SHORT_PERIOD = 5
LONG_PERIOD = 20def init(context):# 全局变量设置context.dict_stock_price = dict()# 以 50 EFT作为交易标的context.stock_pool = ['SZSE.00001']# 订阅日线行情subscribe(symbols=context.stock_pool, frequency='1d', wait_group=True)# 日期设定,避免出现未来函数,将起始日往前取一日start_date = datetime.strptime(context.backtest_start_time, TIME_STR)context.start_date = datetime.strftime(start_date - timedelta(days=1),TIME_STR)# 获取起始日之前行情,便于计算指标deque_high = deque(maxlen=HIST_WINDOW)deque_low = deque(maxlen=HIST_WINDOW)deque_close = deque(maxlen=HIST_WINDOW)for stock in context.stock_pool:history_info = history_n(symbol=stock, frequency='1d', count=HIST_WINDOW,adjust=ADJUST_PREV,adjust_end_time=context.backtest_end_time,end_time=context.start_date,fields='high, low, close')for bar in history_info:deque_high.append(bar['high'])deque_low.append(bar['low'])deque_close.append(bar['close'])context.dict_stock_price.setdefault(stock, [deque_high, deque_low, deque_close])print('finish initialization')def on_bar(context, bars):for bar in bars:if bar.symbol not in context.dict_stock_price.keys():print('Warning: cannot obtain price of stock {} at date {}'.format(bar.symbol, context.now))# 数据填充context.dict_stock_price[bar.symbol][0].append(bar.high)context.dict_stock_price[bar.symbol][1].append(bar.low)context.dict_stock_price[bar.symbol][2].append(bar.close)# 计算指标,这里以双均线为例highs = np.array(context.dict_stock_price[bar.symbol][0])lows = np.array(context.dict_stock_price[bar.symbol][1])closes = np.array(context.dict_stock_price[bar.symbol][2])k_value, d_value = talib.STOCH(highs,lows,closes,fastk_period=9,slowk_period=3,slowk_matype=0,slowd_period=3,slowd_matype=0)j_value = 3*k_value - 2*d_value# 金叉,满仓买入if j_value[-1] >= 80 or j_value[-1] <= 20:order_percent(symbol=bar.symbol,percent=1.0,side=OrderSide_Buy,order_type=OrderType_Market,position_effect=PositionEffect_Open,price=0)print(context.now)# 死叉,全部卖出pos = context.account().position(symbol=bar.symbol, side=OrderSide_Buy)if (j_value[-1] < 80 and j_value[-1] > 20):if pos is None:continueorder_volume(symbol=bar.symbol,volume=pos.volume,side=OrderSide_Sell,order_type=OrderType_Market,position_effect=PositionEffect_Close,price=0)if __name__ == "__main__":run(strategy_id='569b4ffc-6d44-11e8-bd88-80ce62334e41',filename='demo_03.py',mode=MODE_BACKTEST,backtest_adjust=ADJUST_PREV,token='64c33fc82f334e11e1138eefea8ffc241db4a2a0',backtest_start_time='2017-01-17 09:00:00',backtest_end_time='2018-06-21 15:00:00')

5.RSRS标准分

from __future__ import print_function, absolute_import
from gm.api import *
import statsmodels.api as  sm
import numpy as npdef init(context):# 设置参数context.N=18context.M=600context.ans=[]context.buy=0.7context.sell=-0.7#获取历史数据及历史斜率prices = history_n(symbol='SHSE.000300', frequency='1d', count=context.M, end_time='2014-01-01', fields='high,low',skip_suspended=True,fill_missing=None,adjust=ADJUST_PREV,df=True)highs = prices.highlows = prices.lowcontext.ans = []for i in range(len(highs))[context.N:]:data_high = highs.iloc[i - context.N + 1:i + 1]data_low = lows.iloc[i - context.N + 1:i + 1]X = sm.add_constant(data_low)model = sm.OLS(data_high, X)results = model.fit()context.ans.append(results.params[1])schedule(schedule_func=algo, date_rule='1d', time_rule='09:40:00')def algo(context):# 获取上一个交易日的日期last_day = get_previous_trading_date(exchange='SHSE', date=context.now)# 计算前一日的RSRS斜率prices = history_n(symbol='SHSE.000300', frequency='1d', count=context.N, end_time=last_day, fields='', skip_suspended=True,fill_missing=None, adjust=ADJUST_PREV, adjust_end_time='', df=True)#做回归计算highs = prices.highlows = prices.lowX = sm.add_constant(lows)model = sm.OLS(highs, X)results = model.fit()context.ans.append(results.params[1])# 计算标准化的RSRS指标# 计算均值序列section = context.ans[-context.M:]# 计算均值序列mu = np.mean(section)# 计算标准化RSRS指标序列sigma = np.std(section)zscore = (section[-1] - mu) / sigmaif zscore > context.buy:order_target_percent(symbol='SHSE.000300', percent=1, order_type=OrderType_Market,position_side=PositionSide_Long)if zscore < context.sell:order_close_all()if __name__ == '__main__':run(strategy_id='73bb5bf2-a536-11e8-bd52-9cd21ef04ea9',filename='RSRS.py',mode=MODE_BACKTEST,token='c395247a76e8a5caeee699d668d6f550213bc418',backtest_start_time='2014-01-01 08:00:00',backtest_end_time='2018-01-01 16:00:00',backtest_adjust=ADJUST_PREV,backtest_initial_cash=10000000,backtest_commission_ratio=0,backtest_slippage_ratio=0)

6.RSRS斜率

from __future__ import print_function, absolute_import
from gm.api import *
import statsmodels.api as  sm
import numpy as npdef init(context):#设置参数context.N=18context.M=3600context.ans=[]#获取历史数据及历史斜率prices = history_n(symbol='SHSE.000300', frequency='1d', count=context.M, end_time='2014-01-01', fields='high,low',skip_suspended=True,fill_missing=None,adjust=ADJUST_PREV,df=True)highs = prices.highlows = prices.lowcontext.ans = []for i in range(len(highs))[context.N:]:data_high = highs.iloc[i - context.N + 1:i + 1]data_low = lows.iloc[i - context.N + 1:i + 1]X = sm.add_constant(data_low)model = sm.OLS(data_high, X)results = model.fit()context.ans.append(results.params[1])mu=np.mean(context.ans)sigama=np.std(context.ans)#求阈值context.buy=mu+sigamacontext.sell=mu-sigamaschedule(schedule_func=algo, date_rule='1d', time_rule='09:40:00')def algo(context):# 获取上一个交易日的日期last_day = get_previous_trading_date(exchange='SHSE', date=context.now)#计算前一日的RSRS斜率prices = history_n(symbol='SHSE.000300', frequency='1d', count=context.N, end_time=last_day, fields='', skip_suspended=True,fill_missing=None, adjust=ADJUST_PREV, adjust_end_time='', df=True)#做回归计算highs = prices.highlows = prices.lowX = sm.add_constant(lows)model = sm.OLS(highs, X)results = model.fit().params[1]if results > context.buy:order_target_percent(symbol='SHSE.000300', percent=1, order_type=OrderType_Market,position_side=PositionSide_Long)if results < context.sell:order_close_all()if __name__ == '__main__':run(strategy_id='73bb5bf2-a536-11e8-bd52-9cd21ef04ea9',filename='789.py',mode=MODE_BACKTEST,token='c395247a76e8a5caeee699d668d6f550213bc418',backtest_start_time='2014-01-01 08:00:00',backtest_end_time='2018-01-01 16:00:00',backtest_adjust=ADJUST_PREV,backtest_initial_cash=10000000,backtest_commission_ratio=0,backtest_slippage_ratio=0)

7.有效因子 

# coding=utf-8
from __future__ import print_function, absolute_import, unicode_literals
import multiprocessing
import numpy as np
import pandas as pd
from gm.api import *
import matplotlib.pyplot as plt#本策略基于掘金量化交易平台 网址:www.myquant.cndef init(context):# 每月第一个交易日09:40:00的定时执行algo任务schedule(schedule_func=algo, date_rule='1m', time_rule='09:40:00')def algo(context):# 获取当前时刻now = context.now# 获取上一个交易日last_day = get_previous_trading_date(exchange='SHSE', date=now)# 获取IT指数成份股stock300 = get_history_constituents(index='SZSE.399239', start_date=last_day,end_date=last_day)[0]['constituents'].keys()# 获取当天有交易的股票not_suspended_info = get_history_instruments(symbols=stock300, start_date=now, end_date=now)not_suspended_symbols = [item['symbol'] for item in not_suspended_info if not item['is_suspended']]fin = get_fundamentals(table='trading_derivative_indicator', symbols=not_suspended_symbols,start_date=now, end_date=now, fields='PELFYNPAAEI',filter='PELFYNPAAEI >0 or PELFYNPAAEI <0', order_by='PELFYNPAAEI', df=True)long=len(fin)if context.stockrange==0.1:stockpool = list(fin.symbol)[0:int(long * context.stockrange)-1]else:stockpool = list(fin.symbol)[int(long*(context.stockrange-0.1))-1:int(long*context.stockrange)-1]#清仓order_close_all()# 获取股票的权重percent = 1.0 / len(stockpool)# 买在标的池中的股票for symbol in stockpool:order_target_percent(symbol=symbol, percent=percent, order_type=OrderType_Market,position_side=PositionSide_Long)# 获取每次回测的报告数据
def on_backtest_finished(context, indicator):data = [indicator['pnl_ratio'],indicator['pnl_ratio']+0.189, indicator['pnl_ratio_annual'], indicator['sharp_ratio'], indicator['max_drawdown'],context.stockrange]# 将回测报告加入全局list,以便记录context.list.append(data)def run_strategy(stockrange, a_list):from gm.model.storage import context# 用context传入参数context.stockrange = stockrange# a_list一定要传入context.list = a_listrun(strategy_id='3e6dc538-947a-11e8-89c4-9cd21ef04ea9',filename='有效因子.py',mode=MODE_BACKTEST,token='c395247a76e8a5caeee699d668d6f550213bc418',backtest_start_time='2017-01-01 08:00:00',backtest_end_time='2018-01-01 16:00:00',backtest_adjust=ADJUST_PREV,backtest_initial_cash=50000,backtest_commission_ratio=0,backtest_slippage_ratio=0)if __name__ == '__main__':# 生成全局listmanager = multiprocessing.Manager()a_list = manager.list()# 循环输入参数数值回测for stockrange in np.arange(0.1, 1.1, 0.1):print(stockrange)process = multiprocessing.Process(target=run_strategy, args=(stockrange, a_list))process.start()process.join()# 回测报告转化成DataFrame格式a_list = np.array(a_list)final = pd.DataFrame(a_list,columns=['pnl_ratio', 'Alpha','pnl_ratio_annual', 'sharp_ratio', 'max_drawdown', 'stockrange'])fig = plt.figure(figsize=(12, 6))fig.set_facecolor('white')plt.bar(final.loc[final.Alpha>0].index, final.loc[final.Alpha>0].Alpha, align='center',color='r', width=0.3)plt.bar(final.loc[final.Alpha < 0].index, final.loc[final.Alpha < 0].Alpha, align='center',color='g', width=0.3)plt.title('PELFYNPAAEI')plt.show()print(final)

8.冗余因子去除

from __future__ import print_function, absolute_import, unicode_literals
import seaborn as sns
import pandas as pd
from gm.api import *
import matplotlib.pyplot as plt
set_token('c395247a76e8a5caeee699d668d6f550213bc418')#本策略基于掘金量化交易平台 网址:www.myquant.cn#相关性矩阵热力图
def cor(df):dfData = df.corr()plt.subplots(figsize=(9, 9)) # 设置画面大小sns.heatmap(dfData, annot=True, vmax=1, square=True, cmap="Blues")plt.savefig('./BluesStateRelation.png')plt.show()#获取每月第一个交易日
time=get_trading_dates(exchange='SHSE', start_date='2016-01-01', end_date='2018-01-01')
date=[]
for i in time:n=time.index(i)if i[5:7]!=time[n-1][5:7]:date.append(i)#测试因子间相关性
for tradedate in date:data=pd.DataFrame()fin=pd.DataFrame()a=0for factor in ['PB','ROEANNUAL','TAGRT','SHTLIABTOTLIABRT']:n=date.index(tradedate)if n ==23:break# 获取上一个交易日last_day = get_previous_trading_date(exchange='SHSE', date=tradedate)nextmoth=date[n+1]# 获取上证50成份股stock300 = get_history_constituents(index='SHSE.000016', start_date=last_day,end_date=last_day)[0]['constituents'].keys()# 获取当天有交易的股票not_suspended_info = get_history_instruments(symbols=stock300, start_date=tradedate, end_date=tradedate)not_suspended_symbols = [item['symbol'] for item in not_suspended_info if not item['is_suspended']]#获取因子数据if factor=='PB':fin = get_fundamentals(table='trading_derivative_indicator', symbols=not_suspended_symbols,start_date=tradedate, end_date=tradedate, fields=factor,filter='', order_by='-' + factor, df=True)else:fin = get_fundamentals(table='deriv_finance_indicator', symbols=not_suspended_symbols,start_date=tradedate, end_date=tradedate, fields=factor,filter='', order_by='-'+factor, df=True)long=len(fin)fin=fin.fillna(0)portfolio=[]#获取股票收益率for i in fin.symbol:try :last=history(symbol=i, frequency='1d', start_time=nextmoth, end_time=nextmoth, fields='close', skip_suspended=True,fill_missing=None, adjust=ADJUST_NONE, adjust_end_time='', df=False)[0]['close']except:portfolio.append(0)continuepre=history(symbol=i, frequency='1d', start_time=tradedate, end_time=tradedate, fields='close', skip_suspended=True,fill_missing=None, adjust=ADJUST_NONE, adjust_end_time='', df=False)[0]['close']portfolio.append((last - pre) / pre)#根据收益率对股票进行打分portfolio_2=[(sum(portfolio[0:4]))/5]*5+[(sum(portfolio[5:9]))/5]*5+[(sum(portfolio[10:14]))/5]*5+[(sum(portfolio[15:19]))/5]*5+[(sum(portfolio[20:24]))/5]*5+[(sum(portfolio[25:29]))/5]*5+[(sum(portfolio[30:34]))/5]*5+[(sum(portfolio[35:39]))/5]*5+[(sum(portfolio[40:44]))/5]*5+[(sum(portfolio[45-long:0]))/5]*(long-45)fin['portfolio_2'] = portfolio_2fin=fin.sort_values(by = 'portfolio_2',axis = 0,ascending = False)score=[10]*5+[9]*5+[8]*5+[7]*5+[6]*5+[5]*5+[4]*5+[3]*5+[2]*5+[1]*(long-45)fin[factor + 'score'] =scoredel fin['pub_date'],fin['end_date'],fin['portfolio_2'],fin[factor]a=a+1#获取关于四个因子下,每个股票所获得的分数值if a==1:data=finelse:data = pd.merge(data, fin, how='right', on='symbol')#统计分析del data['symbol']cor(data)print(data.corr())

经典的股票/期货量化交易策略,拿来即用的Python策略源码相关推荐

  1. 量化交易中VWAP/TWAP算法的基本原理和简单源码实现(C++和python)(转)

    量化交易中VWAP/TWAP算法的基本原理和简单源码实现(C++和python) 原文地址:http://blog.csdn.net/u012234115/article/details/728300 ...

  2. 量化交易中VWAP/TWAP算法的基本原理和简单源码实现(C++和python)

    参考文献: https://en.wikipedia.org/wiki/Time-weighted_average_price https://en.wikipedia.org/wiki/Volume ...

  3. python期货量化交易实战_Python期货量化交易实战

    ·了解交易的规则与数据指标,学习正确的金融算法·基于真实的数据进行回测和分析,了解期货交易的内涵·循序渐进的案例式教学,按部就班地操作就能上手·基于Python 3.7进行分析,提供示例代码,可在异步 ...

  4. python版期货量化交易(AlgoPlus)案例(多进程处理子任务)

    python版期货量化交易(AlgoPlus)案例(多进程处理子任务) python因为简单.易上手,所以深受大家的喜爱,并且随着人工智能的不断发展与进步,python也一跃成为了最受欢迎的编程语言之 ...

  5. Python期货量化交易中常用的数据类型有哪些?

    1 常用内置常量 Python解释器在启动时会创建None.True.False三个常量,None表示"无",True表示"真",False表示"假& ...

  6. 股票实盘量化交易之所以受普通投资者欢迎有哪两大原因?

    股票实盘量化交易之所以如此受普通投资者欢迎,还有以下2个原因: 1.零成本试错,全市场捕捉赚钱机会 一般来说,大家都是拿真金白银去股票市场冒险的,风险极高,但如果你会量化交易,大可不必拿自己的血汗钱去 ...

  7. 浅析股票网格量化交易的不同优势以及具备什么条件限制

    在股市的长期走势中,震荡市场占比超过70%,真正连续涨跌的股票很少,而网格量化交易方法是一种专门针对震荡的交易策略,它利用市场在一定范围内的波动来赚取差价收入. 网格交易最初诞生于外汇交易市场,因为有 ...

  8. 股票数据量化交易接口是什么?

    股票数据量化交易接口是什么?量化交易接口是一款股票交易接口货交易接口全自动智能量化接口,兼容全球主流平台,全自动交易,无需人工干涉,即可自动炒交易接口赚钱,核心智能量化技术+核心算法,云大数据计算补仓 ...

  9. 【Python】基金/股票 最大回撤率计算与绘图详解(附源码和数据)

    如果你想找的是求最大回撤的算法,请跳转:[Python] 使用动态规划求解最大回撤详解 [Python]基金/股票 最大回撤率计算与绘图详解(附源码和数据) 0. 起因 1. 大成沪深300指数A 5 ...

  10. 经典的期货量化交易策略大全

    1.双均线策略(期货) 双均线策略是简单移动平均线策略的加强版.移动平均线目的是过滤掉时间序列中的高频扰动,保留有用的低频趋势.它以滞后性的代价获得了平滑性,比如,在一轮牛市行情后,只有当价格出现大幅 ...

最新文章

  1. Eclipse下修改工程名
  2. 哈工程计算机学院领导门志国,电气学院“钥匙工程”第二季:赵洪教授为2018级新生打开专业之门...
  3. 常见排序算法(C实现)
  4. OTNM2000 Server端安装
  5. java解析excel文件处理数字成像_Java处理Excel工具,POI解析,使用InputStream读取文件...
  6. 广度搜索 -- 9.1 Word Ladder -- 求是否有解 -- 图解
  7. python读取xps文件_Python操做PDF-文本和图片提取(使用PyPDF2和PyMuPDF)
  8. Java实体对象为null时set方法空指针异常
  9. 记录AK7739-TDM调试
  10. 20v转5v_12v转5v_5v转3.3v 5A用AH8316
  11. 人脸识别准确概率计算——超详细
  12. 多分类TPR, FPR, ROC计算与画图
  13. 万字长文科普:什么是低代码?
  14. python 储蓄计划_储蓄--投资恒式为什么不意味着计划的储蓄恒等于计划的投资?...
  15. 基于STM8S003f3的单键触摸开关制作
  16. 【Android】问题总结:Aroute There`s no route matched
  17. matlab绝对均值,在K-Means算法中使用绝对皮尔逊相关作为距离(MATLAB)
  18. 如何用XMind绘制鱼骨图
  19. python控制机械臂6轴_在ROS环境下,怎么使用moveit!来驱动真实的六轴机械臂?
  20. 字符串核对之Boyer-Moore算法

热门文章

  1. 计算几何05_B样条曲线
  2. 基于用户的协同过滤推荐算法(整合)
  3. Hinduja Global Solutions借助OpManager一年节省300万美元
  4. 使用jemeter进行接口压力测试
  5. qnap安装Linux程序,播酷云J3455-itx 安装 黑威联通Qnap 4.4.0(实机安装)
  6. python移动文件,将某一文件夹下的文件移至另一个文件夹下
  7. Python实现图片美化,醉后不知天在水?(附上代码) | 机器学习
  8. 嵩天《Python数据分析与展示》实例3:Matplotlib基础图表绘制
  9. rollup函数(分组后对每组数据分别合计)
  10. STorM32三轴云台控制器PID参数调节(1)