海龟的Python版出炉。
为方便对比,这里把java、python两种语言代码同时贴出,回测时间及初始资金均使用页面默认的20140104-20150104,100000.0人民币。
turtle_java
public class TurtleOriginalStrategy implements IHStrategy { Core talibCore; //定义全局变量 static int tradedayNum = 0; static double unit = 0; static double atr = 0; static String tradingSignal = "start"; static String preTradingSignal = ""; static int units_hold_max = 4; static int units_hold = 0; static double quantity = 0; static double max_add = 0; static double firstOpenPrice = 0; //计算最大最小值 public double[] getExtremem(double[] arrayHighPriceResult, double[] arrayLowPriceResult) { DescriptiveStatistics forMax = new DescriptiveStatistics(); for (int i = 0; i < arrayHighPriceResult.length-1; i++) { forMax.addValue(arrayHighPriceResult[i]); } double maxResult = forMax.getMax(); DescriptiveStatistics forMin = new DescriptiveStatistics(); for (int i = 0; i < arrayLowPriceResult.length-1; i++) { forMin.addValue(arrayLowPriceResult[i]); } double minResult = forMin.getMin(); double[] forExtremum = new double[2]; forExtremum[0] = maxResult; forExtremum[1] = minResult; return forExtremum; } //计算Atr以及单位 public double[] getAtrAndUnit(double[] atrArrayResult, MInteger atrLengthResult, double portfolioValueResult) { double atr = atrArrayResult[atrLengthResult.value-1]; double unit = Math.floor(portfolioValueResult * .01 / atr); double[] atrAndUnit = new double[2]; atrAndUnit[0] = atr; atrAndUnit[1] = unit; return atrAndUnit; } //计算止损线价位 public double getStopPrice(double firstOpenPriceResult, int units_hold_result, double atrResult) { double stopPrice = firstOpenPriceResult - 2*atrResult + (units_hold_result-1)*0.5*atrResult; return stopPrice; } @Override public void init(IHInformer informer, IHInitializers initializers) { talibCore = new Core(); int openObserveTime = 55; int closeObserveTime = 20; int atrTime = 20; MInteger atrBegin = new MInteger(); MInteger atrLength = new MInteger(); String stockId = "CSI300.INDX"; initializers.instruments((universe) -> universe.add(stockId)); initializers.events().statistics((stats, info, trans) -> { //获取组合总价值,包含市场价值与剩余资金 double portfolioValue = info.portfolio().getPortfolioValue(); double[] highPrice = stats.get(stockId).history(openObserveTime+1, HPeriod.Day).getHighPrice(); double[] lowPriceForAtr = stats.get(stockId).history(openObserveTime+1, HPeriod.Day).getLowPrice(); double[] lowPriceForExtremem = stats.get(stockId).history(closeObserveTime+1, HPeriod.Day).getLowPrice(); double[] closePrice = stats.get(stockId).history(openObserveTime+2, HPeriod.Day).getClosingPrice(); double closePriceForAtr[] = new double[closePrice.length-1]; for (int i = 0; i < closePrice.length-1; i++) { closePriceForAtr[i] = closePrice[i]; } double[] atrArray = new double[openObserveTime]; //Talib计算N即ATR RetCode retCode = talibCore.atr(0, openObserveTime-1, highPrice, lowPriceForAtr, closePriceForAtr, atrTime, atrBegin, atrLength, atrArray); double max = getExtremem(highPrice, lowPriceForExtremem)[0]; double min = getExtremem(highPrice, lowPriceForExtremem)[1]; double atr = atrArray[atrLength.value-1]; informer.info(lowPriceForExtremem[lowPriceForExtremem.length - 1]); informer.info("#######"); informer.info(max); informer.info(min); informer.info(atr); informer.info("#######"); if (tradingSignal != "start") { if (units_hold != 0) { max_add += 0.5 * getAtrAndUnit(atrArray, atrLength, portfolioValue)[0]; } } else { max_add = stats.get(stockId).getLastPrice(); } informer.info(units_hold); double curPosition = info.position(stockId).getNonClosedTradeQuantity(); double availableCash = info.portfolio().getAvailableCash(); double marketValue = info.portfolio().getMarketValue(); if (curPosition > 0 & stats.get(stockId).getLastPrice() < getStopPrice(firstOpenPrice, units_hold, atr)) { tradingSignal = "stop"; } else { if (curPosition > 0 & stats.get(stockId).getLastPrice() < min) { tradingSignal = "exit"; } else { if (stats.get(stockId).getLastPrice() > max_add & units_hold != 0 & units_hold < units_hold_max & availableCash > stats.get(stockId).getLastPrice()*unit) { tradingSignal = "entry_add"; } else { if (stats.get(stockId).getLastPrice() > max & units_hold == 0) { max_add = stats.get(stockId).getLastPrice(); tradingSignal = "entry"; } } } } //informer.info(tradingSignal); atr = getAtrAndUnit(atrArray, atrLength, portfolioValue)[0]; if (tradedayNum % 5 == 0) { unit = getAtrAndUnit(atrArray, atrLength, portfolioValue)[1]; } tradedayNum += 1; double quantity = unit; if (tradingSignal != preTradingSignal | (units_hold < units_hold_max & units_hold > 1) | tradingSignal == "stop") { if (tradingSignal == "entry") { quantity = unit; if (availableCash > stats.get(stockId).getLastPrice()*quantity) { trans.buy(stockId).shares(quantity).commit(); firstOpenPrice = stats.get(stockId).getLastPrice(); units_hold = 1; informer.info("entrybuy" + quantity); } } if (tradingSignal == "entry_add") { quantity = unit; trans.buy(stockId).shares(quantity).commit(); units_hold += 1; informer.info("entry_addbuy" + quantity); } if (tradingSignal == "stop") { if (/*curPosition marketValue*/ units_hold > 0) { trans.sell(stockId).shares(quantity).commit(); units_hold -= 1; informer.info("stop" + quantity); } } if (tradingSignal == "exit") { if (curPosition > 0) { trans.sell(stockId).shares(curPosition).commit(); units_hold = 0; informer.info("exitsell" + curPosition); } } } preTradingSignal = tradingSignal; }); } }
收益图:
风险指标:
turtle_python
import numpy as np import talib import math def getExtremem(arrayHighPriceResult, arrayLowPriceResult): np_arrayHighPriceResult = np.array(arrayHighPriceResult[:-1]) np_arrayLowPriceResult = np.array(arrayLowPriceResult[:-1]) maxResult = np_arrayHighPriceResult.max() minResult = np_arrayLowPriceResult.min() return [maxResult, minResult] def getAtrAndUnit(atrArrayResult, atrLengthResult, portfolioValueResult): atr = atrArrayResult[atrLengthResult-1] unit = math.floor(portfolioValueResult * .01 / atr) return [atr, unit] def getStopPrice(firstOpenPriceResult, units_hold_result, atrResult): stopPrice = firstOpenPriceResult - 2*atrResult + (units_hold_result-1)*0.5*atrResult return stopPrice def init(context): context.tradedayNum = 0 context.unit = 0 context.atr = 0 context.tradingSignal = 'start' context.preTradingSignal = '' context.units_hold_max = 4 context.units_hold = 0 context.quantity = 0 context.max_add = 0 context.firstOpenPrice = 0 context.s = 'CSI300.INDX' update_universe([context.s]) context.openObserveTime = 55; context.closeObserveTime = 20; context.atrTime = 20; def handle_bar(context, bar_dict): portfolioValue = context.portfolio.portfolio_value highPrice = history(context.openObserveTime+1, '1d', 'high')[context.s] lowPriceForAtr = history(context.openObserveTime+1, '1d', 'low')[context.s] lowPriceForExtremem = history(context.closeObserveTime+1, '1d', 'low')[context.s] closePrice = history(context.openObserveTime+2, '1d', 'close')[context.s] closePriceForAtr = closePrice[:-1] atrArray = talib.ATR(highPrice.values, lowPriceForAtr.values, closePriceForAtr.values, timeperiod=context.atrTime) maxx = getExtremem(highPrice.values, lowPriceForExtremem.values)[0] minn = getExtremem(highPrice.values, lowPriceForExtremem.values)[1] atr = atrArray[-2] if (context.tradingSignal != 'start'): if (context.units_hold != 0): context.max_add += 0.5 * getAtrAndUnit(atrArray, atrArray.size, portfolioValue)[0] else: context.max_add = bar_dict[context.s].last curPosition = context.portfolio.positions[context.s].quantity availableCash = context.portfolio.cash marketValue = context.portfolio.market_value if (curPosition > 0 and bar_dict[context.s].last < minn): context.tradingSignal = 'exit' else: if (curPosition > 0 and bar_dict[context.s].last < getStopPrice(context.firstOpenPrice, context.units_hold, atr)): context.tradingSignal = 'stop' else: if (bar_dict[context.s].last > context.max_add and context.units_hold != 0 and context.units_hold < context.units_hold_max and availableCash > bar_dict[context.s].last*context.unit): context.tradingSignal = 'entry_add' else: if (bar_dict[context.s].last > maxx and context.units_hold == 0): context.max_add = bar_dict[context.s].last context.tradingSignal = 'entry' atr = getAtrAndUnit(atrArray, atrArray.size, portfolioValue)[0] if context.tradedayNum % 5 == 0: context.unit = getAtrAndUnit(atrArray, atrArray.size, portfolioValue)[1] context.tradedayNum += 1 context.quantity = context.unit if (context.tradingSignal != context.preTradingSignal or (context.units_hold < context.units_hold_max and context.units_hold > 1) or context.tradingSignal == 'stop'): if context.tradingSignal == 'entry': context.quantity = context.unit if availableCash > bar_dict[context.s].last*context.quantity: order_shares(context.s, context.quantity) context.firstOpenPrice = bar_dict[context.s].last context.units_hold = 1 if context.tradingSignal == 'entry_add': context.quantity = context.unit order_shares(context.s, context.quantity) context.units_hold += 1 if context.tradingSignal == 'stop': if (context.units_hold > 0): order_shares(context.s, -context.quantity) context.units_hold -= 1 if context.tradingSignal == 'exit': if curPosition > 0: order_shares(context.s, -curPosition) context.units_hold = 0 context.preTradingSignal = context.tradingSignal
Python策略范例系列目录:
1. Python策略范例1-一步一步找Alpha
2. Python策略范例2-一个简单的技术指标策略
3. Python策略范例3-了解米筐撮合机制
4. Python策略范例4-策略怎么样,米筐来分析
5. Python策略范例5-股息率策略
当前阅读> 6. Python策略范例6-海龟交易的Python完全版
7. Python策略范例7-Dual Thrust 交易策略
8. Python策略范例8-止损/止盈的七种方法
9. Python策略范例9-我有一个策略想法,如何一步步转化成策略代码?
10. Python策略范例10-参数优化框架