/* This file is part of jTotus. jTotus is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. jTotus is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with jTotus. If not, see <http://www.gnu.org/licenses/>. */ /* * https://www.nordnet.fi/mux/page/hjalp/ordHjalp.html?ord=diagram%20rsi * MACD */ package org.jtotus.methods; import org.jlucrum.realtime.eventtypes.MarketData; import org.jtotus.common.MethodResults; import com.tictactec.ta.lib.Core; import com.tictactec.ta.lib.MInteger; import com.tictactec.ta.lib.RetCode; import java.io.File; import java.util.Date; import org.jtotus.common.DateIterator; import org.jtotus.gui.graph.GraphSender; import org.jtotus.config.ConfTaLibMACD; import org.jtotus.common.StateIterator; import org.jtotus.config.ConfigLoader; import org.jtotus.methods.evaluators.EvaluateMethodSignals; /** * * @author Evgeni Kappinen */ public class TaLibMACD extends TaLibAbstract implements MethodEntry { /*Stock list */ protected ConfTaLibMACD config = null; public ConfigLoader<ConfTaLibMACD> configFile = null; public void loadInputs(String configStock) { configFile = new ConfigLoader<ConfTaLibMACD>(super.portfolioConfig.portfolioName + File.separator + configStock + File.separator + this.getMethName()); if (configFile.getConfig() == null) { //Load default values config = new ConfTaLibMACD(); configFile.storeConfig(config); } else { config = (ConfTaLibMACD) configFile.getConfig(); } super.child_config = config; configFile.applyInputsToObject(this); } /************* DECISION TEST ************* * @param evaluator Evaluation object * @param stockName ReviewTarget of the method * @param input closing price for period * * @return void */ public void performDecisionTest(EvaluateMethodSignals evaluator, String stockName, double[] input, int fastPeriod, int slowPeriod, int signalPeriod) { boolean change=false; MInteger outBegIdx = new MInteger(); MInteger outNbElement = new MInteger(); double []macd = new double [input.length - 1]; double []macdSignal = new double [input.length - 1]; double []macdHis = new double [input.length - 1]; double[] output = this.actionMACD(input, outBegIdx, outNbElement, macd, macdSignal,macdHis, fastPeriod, slowPeriod, signalPeriod); } public double[] actionMACD(double[] input, MInteger outBegIdxDec, MInteger outNbElementDec, double []macd, double []macdSignal, double []macdHis, int fastPeriod, int slowPeriod, int signalPeriod) { int intput_size = input.length - 1; final Core core = new Core(); final int allocationSizeDecision = intput_size - core.macdLookback(fastPeriod, slowPeriod, signalPeriod); if (allocationSizeDecision <= 0) { System.err.printf("No data for period (%d)\n", allocationSizeDecision); return null; } RetCode decCode = core.macd(0, intput_size - 1, input, fastPeriod, slowPeriod, signalPeriod, outBegIdxDec, outNbElementDec, macd, macdSignal, macdHis); if (decCode.compareTo(RetCode.Success) != 0) { //Error return empty method results throw new java.lang.IllegalStateException("MACD failed:" + " Fast: " +fastPeriod+" Slow: "+slowPeriod+" Signal: "+signalPeriod + " Begin:" + outBegIdxDec.value + " NumElem:" + outNbElementDec.value + "\n"); } return macd; } public MethodResults performMACD(String stockName, double[] input) { this.loadInputs(stockName); System.out.printf("Periods fast:%d slow:%d signal:%d\n", config.inputMACDFastPeriod, config.inputMACDSlowPeriod, config.inputMACDSignalPeriod); //************* DECISION TEST *************// MInteger outBegIdx = new MInteger(); MInteger outNbElement = new MInteger(); double []macd = new double [input.length - 1]; double []macdSignal = new double [input.length - 1]; double []macdHis = new double [input.length - 1]; double[] output = this.actionMACD(input, outBegIdx, outNbElement, macd, macdSignal, macdHis, config.inputMACDFastPeriod, config.inputMACDSlowPeriod, config.inputMACDSignalPeriod); methodResults.putResult(stockName, macd[outNbElement.value - 1]); sender = new GraphSender(stockName); for (int elem = 0; elem <= outNbElement.value; elem++) { DateIterator dateIterator = new DateIterator(portfolioConfig.inputStartingDate, portfolioConfig.inputEndingDate); dateIterator.move(elem + outBegIdx.value); sender.setSeriesName("Original"); sender.addForSending(dateIterator.getCurrent(), input[elem + outBegIdx.value]); } sender.sendAllStored(); if (config.inputPrintResults) { sender = new GraphSender(stockName); sender.setPlotName("MACD"); sender.setSeriesName(this.getMethName()); DateIterator dateIterator = new DateIterator(portfolioConfig.inputStartingDate, portfolioConfig.inputEndingDate); dateIterator.move(outBegIdx.value); for (int i = 0; i < outNbElement.value && dateIterator.hasNext(); i++) { Date stockDate = dateIterator.next(); sender.addForSending(stockDate, macd[i]); } sender.sendAllStored(); } System.out.printf("%s (%s) has %d successrate\n", this.getMethName(), stockName, methodResults.getSuccessRate().intValue()); return methodResults; } @Override public MethodResults performMethod(String stockName, double []input) { //Load config for a stock this.loadInputs(stockName); //Perform testing if it is asked if (false) { EvaluateMethodSignals budjetCounter = new EvaluateMethodSignals(); for (StateIterator iter = new StateIterator() .addParam("macdFastPeriod", config.inputDecisionFastPeriod) .addParam("macdSlowPeriod", config.inputDecisionSlowPeriod) .addParam("macdSignal", config.inputDecisionSinal); iter.hasNext() != StateIterator.END_STATE; iter.nextState()) { budjetCounter.initialize(stockName, "DecisionMACD", portfolioConfig.inputAssumedBudjet); this.performDecisionTest(budjetCounter, stockName, input, iter.nextInt("macdFastPeriod"), iter.nextInt("macdSlowPeriod"), iter.nextInt("macdSignal")); if(budjetCounter.newBest()) { config.inputMACDFastPeriod = iter.nextInt("macdFastPeriod"); config.inputMACDSlowPeriod = iter.nextInt("macdSlowPeriod"); config.inputMACDSignalPeriod = iter.nextInt("macdSignal"); } } this.config.outputSuccessRate = budjetCounter.getProfitInProcents(); methodResults.putSuccessRate(stockName, budjetCounter.getProfitInProcents()); this.configFile.storeConfig(config); budjetCounter.printBestResults(); budjetCounter.dumpResults(); } //Perform method return this.performMACD(stockName, input); } public MethodResults runCalculation() { throw new UnsupportedOperationException("Not supported yet."); } public MethodResults runCalculation(MarketData data) { throw new UnsupportedOperationException("Not supported yet."); } }