这个文章是接着【原创】【量化策略】海龟交易体系的小白构建(二)之交易实现所用的平台依然是我钟爱的ricequant 米筐科技的
海龟策略完全体系构建最后的最后,放上海龟体系的完全版,Code里面包含了上一节中提到的所有环节,注意本海龟策略是基于体系二的,感兴趣的朋友可以尝试构建体系一。
TurtleOriginalStrategy Code:
[url=]Clone[/url]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
); } double maxResult = forMax.getMax(); DescriptiveStatistics forMin = new DescriptiveStatistics(); for (int i = 0; i < arrayLowPriceResult.length-1; i++) { forMin.addValue(arrayLowPriceResult); } 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 = closePrice; } 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]; 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; }); }}回测结果:
opps吐血,虽然代码蛮长运行还是挺快哒,终于搞定,完整版的策略包括了按照海龟中的进场、追踪、止损、离场所有细节,然而并没有什么卵用,结果没有想象那么漂亮,不过继续在之前的基础上把最大回撤降低到22,我想这还是因为止损大法好的原因,宽慰一点点。
多少自己还是体会到一个交易系统雏形构建的方方面面,我这么对自己说,成功完成了一次心理按摩。
最后,欢迎小伙伴就代码进行深度交流。——> ________ ——>