Forecasting
The longer you look back, the farther you can look forward. (Winston Churchill)
Forecastig of the development of stocks is quite a challangning task with uncertain outcome. We currently support the following approaches:
– Forecast based on History
– Arima
Setup
%classpath config resolver maven-public http://pschatzmann.ch:8081/repository/maven-public/
%classpath add mvn ch.pschatzmann:investor:0.9-SNAPSHOT
%classpath add mvn ch.pschatzmann:jupyter-jdk-extensions:0.0.1-SNAPSHOT
Added new repo: maven-public
Added jars: [websocket-common-9.2.20.v20161216.jar, commons-cli-1.3.1.jar, htmlunit-2.24.jar, qdox-1.5.jar, investor-0.9-SNAPSHOT.jar, httpclient-4.5.3.jar, hamcrest-core-1.1.jar, slf4j-api-1.7.25.jar, commons-codec-1.10.jar, jetty-io-9.2.20.v20161216.jar, timeseries-forecast-1.1.1.jar, commons-lang3-3.5.jar, jackson-databind-2.9.4.jar, commons-io-2.5.jar, htmlunit-core-js-2.23.jar, jackson-annotations-2.9.4.jar, jetty-util-9.2.20.v20161216.jar, YahooFinanceAPI-3.12.3.jar, sevenzipjbinding-all-platforms-9.20-2.00beta.jar, sevenzipjbinding-9.20-2.00beta.jar, sojo-1.0.5.jar, commons-jcs-core-2.0.jar, websocket-client-9.2.20.v20161216.jar, jfreechart-1.5.0.jar, ant-1.5.jar, combinatoradix-0.8.2.jar, cssparser-0.9.21.jar, jackson-core-2.9.4.jar, httpcore-4.4.6.jar, xercesImpl-2.11.0.jar, neko-htmlunit-2.24.jar, httpmime-4.5.2.jar, log4j-1.2.17.jar, sac-1.3.jar, ta4j-core-0.10.jar, websocket-api-9.2.20.v20161216.jar, jcl-over-slf4j-1.7.25.jar, xalan-2.7.2.jar, slf4j-log4j12-1.7.25.jar, junit-4.10.jar, commons-attributes-api-2.2.jar, xml-apis-1.4.01.jar, serializer-2.7.2.jar]
Added jars: [concurrent-1.3.4.jar, jcs-1.3.jar, avalon-framework-4.1.3.jar, commons-logging-1.1.jar, in-memory-stardb-0.0.1-SNAPSHOT.jar, logkit-1.0.1.jar, common-0.0.1-SNAPSHOT.jar, jupyter-jdk-extensions-0.0.1-SNAPSHOT.jar, servlet-api-2.3.jar]
// our stock evaluation framwork
import ch.pschatzmann.dates._;
import ch.pschatzmann.stocks._;
import ch.pschatzmann.stocks.data.universe._;
import ch.pschatzmann.stocks.input._;
import ch.pschatzmann.stocks.accounting._;
import ch.pschatzmann.stocks.accounting.kpi._;
import ch.pschatzmann.stocks.execution._;
import ch.pschatzmann.stocks.execution.fees._;
import ch.pschatzmann.stocks.execution.price._;
import ch.pschatzmann.stocks.parameters._;
import ch.pschatzmann.stocks.strategy._;
import ch.pschatzmann.stocks.strategy.optimization._;
import ch.pschatzmann.stocks.strategy.allocation._;
import ch.pschatzmann.stocks.strategy.selection._;
import ch.pschatzmann.stocks.integration._;
import ch.pschatzmann.stocks.forecasting._;
import ch.pschatzmann.stocks.integration.ChartData.FieldName._;
import ch.pschatzmann.stocks.strategy.OptimizedStrategy.Schedule._;
// java
import java.util.stream.Collectors;
import java.util._;
import java.lang._;
import java.util.function.Consumer;
// jupyter custom displayer
import ch.pschatzmann.display.Displayers
import ch.pschatzmann.dates._
import ch.pschatzmann.stocks._
import ch.pschatzmann.stocks.data.universe._
import ch.pschatzmann.stocks.input._
import ch.pschatzmann.stocks.accounting._
import ch.pschatzmann.stocks.accounting.kpi._
import ch.pschatzmann.stocks.execution._
import ch.pschatzmann.stocks.execution.fees._
import ch.pschatzmann.stocks.execution.price._
import ch.pschatzmann.stocks.parameters._
import ch.pschatzmann.stocks.strategy._
import ch.pschatzmann.stocks.strategy.optimization._
import ch.pschatzmann.stocks.strategy.allocation._
import ch.pschatzmann.stocks.strategy.selection._
import ch.pschatzmann.stocks.integration._
import ch.pschatzmann.stocks.forecasting._
import ch.pschatzmann.stocks.integration.ChartData.FieldName._
import ch.pschatzmann.stocks.strategy.Optimized...
Displayers.setup("WARN")
Context.setCachingActive(false);
Context.isCachingActive();
false
Forecasting for AAPL
First we determine the history.
var aapl = new StockData(new StockID("AAPL", "NASDAQ"), new MarketArchiveHttpReader());
var history = aapl.getHistory(Context.date("1995-01-01"))
Displayers.display(Context.tail(history,10));
index |
date |
low |
high |
open |
closing |
adjustmentFactor |
volume |
9345 |
2018-01-04 |
172.08 |
173.47 |
172.54 |
173.03 |
1 |
22434600 |
9346 |
2018-01-05 |
173.05 |
175.37 |
173.44 |
175 |
1 |
23660000 |
9347 |
2018-01-08 |
173.93 |
175.61 |
174.35 |
174.35 |
1 |
20567800 |
9348 |
2018-01-09 |
173.41 |
175.06 |
174.55 |
174.33 |
1 |
21584000 |
9349 |
2018-01-10 |
173 |
174.3 |
173.16 |
174.29 |
1 |
23959900 |
9350 |
2018-01-11 |
174.49 |
175.49 |
174.59 |
175.28 |
1 |
18667700 |
9351 |
2018-01-12 |
175.65 |
177.36 |
176.18 |
177.09 |
1 |
25418100 |
9352 |
2018-01-16 |
176.14 |
179.39 |
177.9 |
176.19 |
1 |
29565900 |
9353 |
2018-01-17 |
175.07 |
179.25 |
176.15 |
179.1 |
1 |
34386800 |
9354 |
2018-01-18 |
178.25 |
180.1 |
179.37 |
179.26 |
1 |
31035300 |
Displayers.display(new TimeSeriesChart().add(aapl).displayChart())
Simulation of Future using the Past
One possiblity is to simulate the future based on the development of the past: Looking at the chart we can e.g.
investigate how our strategy would behave if we would be in a simialr position like on March 2015.
We simulate the future develpment based on the development starting from
– 2012-09-01 of the AAPL stock
– 2015-03-01 of the AAPL stock
– 2017-03-01 of the NYSE Composite Index
var nya = new StockData(new StockID("^NYA", "INDEX"), new MarketArchiveHttpReader());
var aapl = new StockData(new StockID("AAPL", "NASDAQ"), new MarketArchiveHttpReader());
var aaplWithFuture1 = new ForecasterFromSimulationOnHistory(Context.date("2012-09-01")).forecast(aapl, 200)
var aaplWithFuture2 = new ForecasterFromSimulationOnHistory(Context.date("2015-03-01")).forecast(aapl, 200)
var aaplWithFuture3 = new ForecasterFromSimulationOnHistory(Context.date("2017-03-01"),nya).forecast(aapl, 200)
// display chart
var chart = new TimeSeriesChart()
var startDisplayDate = Context.date("2012-01-01")
chart.add(aaplWithFuture1.getHistory(startDisplayDate),"1)2012-09-01")
chart.add(aaplWithFuture2.getHistory(startDisplayDate),"2)2015-03-01")
chart.add(aaplWithFuture3.getHistory(startDisplayDate),"3)2017-03-01 nya")
Displayers.display(chart.displayChart())
Result for Worst Case Option 1
var dates = Context.getDateRanges("2018-01-01","2019-01-01");
var account1 = new Account("Simulation","USD", 100000.00, dates.get(0).getStart(), new PerTradeFees(10.0));
var aapl = new StockData(new StockID("AAPL", "NASDAQ"), new MarketArchiveHttpReader());
var aaplWithFuture1 = new ForecasterFromSimulationOnHistory(Context.date("2012-09-01")).forecast(aapl, 200)
var strategy1 = new RSI2Strategy(aaplWithFuture1);
var trader1 = new PaperTrader(account1);
var state = new Fitness(trader1).getFitness(strategy1, dates.get(0));
state.result()
ReturnPercent:-14; NumberOfCashTransfers:1; TotalFees:20; MaxDrawDownPercent:26331; MaxDrawDownNumberOfDays:189; SharpeRatio:-1; NumberOfTradedStocks:1; MaxDrawDownHighValue:106269; Cash:86022; ReturnPercentAnualized:-16; NumberOfBuys:1; AbsoluteReturn:-13978; ActualValue:86022; ReturnPurcentStdDev:0; PurchasedValue:86022; AbsoluteReturnAvaragePerDay:-65; AbsoluteReturnStdDev:884; NumberOfTrades:2; UnrealizedGains:0; NumberOfSells:1; RealizedGains:-13958; MaxDrawDownLowValue:79938;
Displayers.display(account1.getTransactions().collect(Collectors.toList()));
active |
stockID |
date |
quantity |
requestedPrice |
filledPrice |
fees |
comment |
id |
buyOrSell |
requestedPriceType |
impactOnCash |
true |
Key |
Value |
ticker |
Cash |
exchange |
Account |
|
2018-01-01 |
0 |
0 |
0 |
0 |
|
69617c78-c2b2-4845-8752-caed9c8d147e |
NA |
CashTransfer |
100000 |
true |
Key |
Value |
ticker |
AAPL |
exchange |
NASDAQ |
|
2018-01-29 |
564 |
0 |
177.1629 |
10 |
|
d0e2e074-f212-4d2b-b851-55713526d637 |
Buy |
Market |
-99929.898 |
true |
Key |
Value |
ticker |
AAPL |
exchange |
NASDAQ |
|
2018-04-05 |
-564 |
0 |
152.4155 |
10 |
|
f6bf2e77-b143-42e6-9918-4f48bd56229a |
Sell |
Market |
85952.3228 |
Result for Option 2
var dates = Context.getDateRanges("2018-01-01","2019-01-01");
var account2 = new Account("Simulation","USD", 100000.00, dates.get(0).getStart(), new PerTradeFees(10.0));
var aapl = new StockData(new StockID("AAPL", "NASDAQ"), new MarketArchiveHttpReader());
var aaplWithFuture2 = new ForecasterFromSimulationOnHistory(Context.date("2015-03-01")).forecast(aapl, 200)
var strategy2 = new RSI2Strategy(aaplWithFuture2);
var trader2 = new PaperTrader(account2);
var state2 = new Fitness(trader2).getFitness(strategy2, dates.get(0));
state2.result()
ReturnPercent:-7; NumberOfCashTransfers:1; TotalFees:20; MaxDrawDownPercent:14709; MaxDrawDownNumberOfDays:142; SharpeRatio:0; NumberOfTradedStocks:1; MaxDrawDownHighValue:105272; Cash:95; ReturnPercentAnualized:-8; NumberOfBuys:1; AbsoluteReturn:-6522; ActualValue:101610; ReturnPurcentStdDev:0; PurchasedValue:99990; AbsoluteReturnAvaragePerDay:-30; AbsoluteReturnStdDev:1023; NumberOfTrades:2; UnrealizedGains:1620; NumberOfSells:1; RealizedGains:0; MaxDrawDownLowValue:90562;
Displayers.display(account2.getTransactions().collect(Collectors.toList()));
active |
stockID |
date |
quantity |
requestedPrice |
filledPrice |
fees |
comment |
id |
buyOrSell |
requestedPriceType |
impactOnCash |
true |
Key |
Value |
ticker |
Cash |
exchange |
Account |
|
2018-01-01 |
0 |
0 |
0 |
0 |
|
91e8a043-174d-43e8-b172-0d70a8613ae7 |
NA |
CashTransfer |
100000 |
true |
Key |
Value |
ticker |
AAPL |
exchange |
NASDAQ |
|
2018-01-25 |
569 |
0 |
175.5629 |
10 |
|
376a9292-d4d4-4ac5-be5f-12994520da3e |
Buy |
Market |
-99905.2801 |
true |
Key |
Value |
ticker |
AAPL |
exchange |
NASDAQ |
|
2018-07-09 |
-569 |
0 |
164.1354 |
10 |
|
bb10b925-f330-4105-bdca-82df18e86465 |
Sell |
Market |
93383.0537 |
Result for Best Case – Option 3
var dates = Context.getDateRanges("2018-01-01","2019-01-01");
var account3 = new Account("Simulation","USD", 100000.00, dates.get(0).getStart(), new PerTradeFees(10.0));
var aapl = new StockData(new StockID("AAPL", "NASDAQ"), new MarketArchiveHttpReader());
var aaplWithFuture3 = new ForecasterFromSimulationOnHistory(Context.date("2017-03-01"),nya).forecast(aapl, 200)
var strategy3 = new RSI2Strategy(aaplWithFuture3);
var trader3 = new PaperTrader(account3);
var state3 = new Fitness(trader3).getFitness(strategy3, dates.get(0));
state3.result()
ReturnPercent:-13; NumberOfCashTransfers:1; TotalFees:20; MaxDrawDownPercent:18979; MaxDrawDownNumberOfDays:193; SharpeRatio:-2; NumberOfTradedStocks:1; MaxDrawDownHighValue:102109; Cash:87017; ReturnPercentAnualized:-15; NumberOfBuys:1; AbsoluteReturn:-12983; ActualValue:87017; ReturnPurcentStdDev:0; PurchasedValue:87017; AbsoluteReturnAvaragePerDay:-61; AbsoluteReturnStdDev:533; NumberOfTrades:2; UnrealizedGains:0; NumberOfSells:1; RealizedGains:-12963; MaxDrawDownLowValue:83129;
Displayers.display(account3.getTransactions().collect(Collectors.toList()));
active |
stockID |
date |
quantity |
requestedPrice |
filledPrice |
fees |
comment |
id |
buyOrSell |
requestedPriceType |
impactOnCash |
true |
Key |
Value |
ticker |
Cash |
exchange |
Account |
|
2018-01-01 |
0 |
0 |
0 |
0 |
|
b0d54243-5a94-4f4a-9101-cd248ccafc1b |
NA |
CashTransfer |
100000 |
true |
Key |
Value |
ticker |
AAPL |
exchange |
NASDAQ |
|
2018-01-29 |
558 |
0 |
179.1682 |
10 |
|
8d5d9d4e-ca04-4995-8466-8f581146cbe0 |
Buy |
Market |
-99985.8511 |
true |
Key |
Value |
ticker |
AAPL |
exchange |
NASDAQ |
|
2018-03-28 |
-558 |
0 |
155.9368 |
10 |
|
ff119376-82bc-419b-a5a6-d2b8b228638e |
Sell |
Market |
87002.7313 |
Arima
import ch.pschatzmann.stocks.forecasting._
import com.workday.insights.timeseries.arima.struct.ArimaParams
var aapl = new StockData(new StockID("^NYA", "INDEX"), new MarketArchiveHttpReader());
var params = new ArimaParams(1, 0, 0, 0, 0, 0, 0);
var arima = new ForecasterARIMA(params)
var aaplArima = arima.forecast(aapl, 800)
// display chart
var chart = new TimeSeriesChart()
chart.add(aaplArima.getHistory(Context.date("2016-01-01")),"AAPL")
chart
var result = arima.getClose()
println(result.getRMSE())
println(result.getMaxNormalizedVariance)
result.getLog()
2916.0361215978332
1097.4211097962977
{"Best ModelInterface Param" : "ModelInterface ParamsInterface:, p= 1, d= 0, q= 0, P= 0, D= 0, Q= 0, m= 0","Forecast Size" : "800","Input Size" : "13102"}
var result = arima.getOpen()
println(result.getRMSE())
println(result.getMaxNormalizedVariance)
result.getLog()
2915.742853883635
969.6583958825637
{"Best ModelInterface Param" : "ModelInterface ParamsInterface:, p= 1, d= 0, q= 0, P= 0, D= 0, Q= 0, m= 0","Forecast Size" : "800","Input Size" : "13102"}
0 Comments