/* 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 * RSI RSI on hintaa seuraava oskilaattori, joka saavuttaa 0-100 välisiä arvoja. Se vertaa viimeisten ylöspäin tapahtuneiden hintamuutosten voimakkuutta alaspäin suuntautuneisiin hintamuutoksiin. Suosituimmat tarkasteluvälit ovat 9, 14 ja 25 päivän RSI. Tulkinta: - RSI huipussa: korkea arvo (yli 70/noususuhdanteessa yleensä 80) indikoi yliostotilannetta - RSI pohjassa: matala arvo (alle 30/laskusuhdanteessa yleenäs 20) indikoi aliostotilannetta Signaalit: - Osta, kun RSI:n arvo leikkaa aliostorajan alapuolelta - Myy, kun RSI:n arvo leikkaa yliostorajan yläpuolelta Vaihtoehtoisesti: - Osta, kun RSI leikkaa keskilinjan (50) alapuolelta - Myy, kun RSI leikkaa keskilinjan (50) yläpuolelta */ 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.util.Date; import org.jtotus.common.DateIterator; import org.jtotus.config.ConfigLoader; import org.jtotus.gui.graph.GraphSender; import java.io.File; import org.jtotus.common.StateIterator; import org.jtotus.config.ConfTaLibSMA; import org.jtotus.methods.evaluators.EvaluateMethodSignals; import org.jtotus.methods.evaluators.TimeSeriesCondition; /** * * @author Evgeni Kappinen */ public class TaLibSMA extends TaLibAbstract implements MethodEntry { //INPUTS TO METHOD: private ConfTaLibSMA config = null; private ConfigLoader<ConfTaLibSMA> configFile = null; public TaLibSMA() { super(); } public void loadInputs(String configStock) { configFile = new ConfigLoader<ConfTaLibSMA>(super.portfolioConfig.portfolioName + File.separator + configStock + File.separator + this.getMethName()); if (configFile.getConfig() == null) { //Load default values config = new ConfTaLibSMA(); configFile.storeConfig(config); } else { config = configFile.getConfig(); } super.child_config = config; configFile.applyInputsToObject(this); } public double[] actionSMA(double[] input, int intput_size, MInteger outBegIdxDec, MInteger outNbElementDec, int decSMAPeriod) { final Core core = new Core(); final int allocationSizeDecision = intput_size - core.smaLookback(decSMAPeriod); if (allocationSizeDecision <= 0) { System.err.printf("No data for period (%d)\n", allocationSizeDecision); return null; } double[] outputDec = new double[allocationSizeDecision]; RetCode decCode = core.sma(0, intput_size - 1, input, decSMAPeriod, outBegIdxDec, outNbElementDec, outputDec); if (decCode.compareTo(RetCode.Success) != 0) { //Error return empty method results throw new java.lang.IllegalStateException("SMA failed:" + decSMAPeriod + " Begin:" + outBegIdxDec.value + " NumElem:" + outNbElementDec.value + "\n"); } return outputDec; } /************* 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 decSMAPeriod) { MInteger outBegIdx = new MInteger(); MInteger outNbElement = new MInteger(); double[] output = this.actionSMA(input, input.length - 1, outBegIdx, outNbElement, decSMAPeriod); DateIterator dateIterator = new DateIterator(portfolioConfig.inputStartingDate, portfolioConfig.inputEndingDate); TimeSeriesCondition signals = new TimeSeriesCondition(); signals.declareFunc("A", input); signals.declareFunc("B", output); dateIterator.move(outBegIdx.value); for (int elem = 1; elem <= outNbElement.value && dateIterator.hasNext(); elem++) { Date date = dateIterator.next(); if (signals.setA(elem + outBegIdx.value).crosses().setB(elem).and().smaller().isTrue()) { evaluator.buy(input[elem + outBegIdx.value], -1, date); } else if (signals.setA(elem + outBegIdx.value).crosses().setB(elem).and().bigger().isTrue()) { evaluator.sell(input[elem + outBegIdx.value], -1, date); } } } public MethodResults performSMA(String stockName, double[] input) { int inputSize = input.length - 1; MInteger outBegIdx = new MInteger(); MInteger outNbElement = new MInteger(); double[] output = this.actionSMA(input, inputSize, outBegIdx, outNbElement, config.inputSMAPeriod); methodResults.putResult(stockName, output[output.length - 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.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, output[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 (config.inputPerfomDecision) { EvaluateMethodSignals budjetCounter = new EvaluateMethodSignals(); for (StateIterator iter = new StateIterator().addParam("SMAperiod", config.inputSMADecisionPeriod); iter.hasNext() != StateIterator.END_STATE; iter.nextState()) { budjetCounter.initialize(stockName, "DecisionSMA", portfolioConfig.inputAssumedBudjet); this.performDecisionTest(budjetCounter, stockName, input, iter.nextInt("SMAperiod")); if(budjetCounter.newBest()) { config.inputSMAPeriod = iter.nextInt("SMAperiod"); } } this.config.outputSuccessRate = budjetCounter.getProfitInProcents(); methodResults.putSuccessRate(stockName, budjetCounter.getProfitInProcents()); this.configFile.storeConfig(config); budjetCounter.printBestResults(); budjetCounter.dumpResults(); } //Perform method return this.performSMA(stockName, input); } public MethodResults runCalculation() { throw new UnsupportedOperationException("Not supported yet."); } public MethodResults runCalculation(MarketData data) { throw new UnsupportedOperationException("Not supported yet."); } }