In this document we demonstrate how to use the Edgar Database for the selection of the stocks into a portfilio with the help of the Investor library.
This functionality is using the Edgar Webservice which is based on the data which is available on https://www.sec.gov/edgar.shtml.
Setup
We add the necessary jars and import the related packages.
%classpath config resolver maven-public http://software.pschatzmann.ch/repository/maven-public/
%classpath add mvn ch.pschatzmann:investor:0.9-SNAPSHOT
%classpath add mvn ch.pschatzmann:jupyter-jdk-extensions:0.0.1-SNAPSHOT
// 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.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;
import scala.collection.JavaConverters
/// jupyter custom displayer
import ch.pschatzmann.display.Displayers
Added new repo: maven-public
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.integration.ChartData.FieldName._
import ch.pschatzmann.stocks.strategy.OptimizedStrategy.Schedule._
import java.util.stream…
Displayers.setup()
Context.setCachingActive(false);
Context.isCachingActive();
false
EdgarUniverse
We can use the EdgarUniverse to select stocks which are available in the Edgar Database.
The data is selected by specifying one or mulitple parameters for one year or for multiple years if we define a list of multiplication factors which define the weights for each year: E.g (1.0, 1.0, 1.0) is selecting 3 years where the values are fully counted.
If no parmameter is specified we use the following list: “NetIncomeLoss”,”ProfitLoss”,”OperatingIncomeLoss”.
Here are a couple of examples:
// top 10 companyies with the highest Net Income in the year 2017
new EdgarUniverse(2017, 10)
[:AAPL, :MSFT, :XOM, :FB, :PG, :GOOG, :CSCO, :ORCL, :PSX, :PCS]
// top 10 companyies with the highest Net Income in the year 2015
new EdgarUniverse(2015, 10, Arrays.asList("NetIncomeLoss"))
[:AAPL, :GOOG, :XOM, :MSFT, :ORCL, :CSCO, :UAL, :PG, :CZR, :PSX]
// top 10 companyies with the highest R&D in the year 2017
new EdgarUniverse(2017, 10, Arrays.asList("ResearchAndDevelopmentExpense"))
[:GOOG, :MSFT, :AAPL, :CSCO, :BMY, :ORCL, :FB, :PG, :VMW, :BXLT]
// top 10 companyies with the highest Net Income in the year 2015-2017
new EdgarUniverse(2017, Arrays.asList(0.5, 0.8, 1.0), 10, Arrays.asList("NetIncomeLoss"), true)
[:AAPL, :XOM, :MSFT, :ORCL, :PG, :CSCO, :GOOG, :PSX, :NKE, :FB]
// top 10 companyies with the highest Net Income Increases in the year 2014-2017
var u = new EdgarUniverse(2017, Arrays.asList(0.2, 0.5, 0.8, 1.0), 10, Arrays.asList("NetIncomeLoss"), true)
u.setCalculatePercentChange(true)
u
[:UFCS, :TTD, :NEFE, :LBMH, :GNBT, :SULT, :ZETAIII, :TORM, :PSPW, :GORO]
// top 10 companyies with the highest Net Income Increases in the year 2015-2017
var u = new EdgarUniverse(2017, Arrays.asList(0.5, 0.8, 1.0), 10, Arrays.asList("NetIncomeLoss"), true)
u.setCalculatePercentChange(true)
u
[:TTD, :NEFE, :LBMH, :GNBT, :SULT, :ZETAIII, :TORM, :GORO, :ANTB, :FSYS]
Stock Readers
Since the edgar filings only contain the ticker symbol w/o the information of the related exchange, we need to use one of the StockReaders which can cope with this:
– YahooReader
– QuandlWIKIReader
– AlphaVantageReader
– IEXReader
var reader = new YahooReader()
ch.pschatzmann.stocks.input.YahooReader@32f670bd
Selection of the Stocks with the Highest Profits
For the past n years we determine the top n stocks of the previos year and we execute the evaluation of the selected stock with the best strategies. The portfiolio of selected stocks is updated every year.
We determine the Universe and the trading strategy selection for the prior year and then execute the strategy for the current period.
If a stock has been deselected (from the latest universe) the system waits for the next sell signal to liquidate the stock.
var periods = Context.getDateRanges("2011-01-01","2012-01-01","2013-01-01","2014-01-01","2015-01-01","2016-01-01","2017-01-01");
var account = new Account("Simulation", "USD", 100000.00, periods.get(0).getStart(), new PerTradeFees(6.95))
var strategies = TradingStrategyFactory.list()
var trader = new PaperTrader(account);
var allocationStrategy = new DistributedAllocationStrategy(trader);
var executor = new StrategyExecutor(trader, allocationStrategy);
for (i <- 1 to 5) {
var year = Context.getYear(periods.get(i-1).getStart());
var portfolioUniverse = new EdgarUniverse(year, 10)
var strategySelector = new StrategySelector(account, strategies, periods.get(i-1), KPI.AbsoluteReturn)
var stockSelector = new StockSelector(strategySelector)
var result = stockSelector.getSelection(10, portfolioUniverse, reader)
executor.setStrategies(result.getStrategies(reader));
executor.run(periods.get(i));
}
account.setCloseDate(periods.get(5).getEnd())
account.getKPIValues()
[Absolute Return 110935.92901799994, Absolute Return Avarage per day 73.46750266092711, Absolute Return StdDev 1272.9836060189323, Return % 110.93592901799994, Return % per year 18.501557983147574, Return % StdDev 0.007667029354465832, Sharp Ratio 1.0845780729422094, Max Draw Down % 13.407077915993506, Max Draw Down Absolute 26276.164564999985, Max Draw Down – Number of days 67, Max Draw Down – High 195987.25933899995, Max Draw Down – Low 169711.09477399997, Max Draw Down – Period 20150720-20150825, Number of Trades 660, Number of Buys 294, Number of Sells 357, Number of Cash Transfers 1, Number of Traded Stocks 14, Total Fees 0.0, Cash 100000.0, Total Value (at actual rates) including cash 100000.0, Total Value (at purchased rates) 100000.0, Realized Gains 0.0, Unrealized Gains 0.0]
Immediate Liquidation
With executor.setImmediateLiquidationOfDiscontinuedStocks(true) we can make sure that the stock is liquidated at the beginning of the period. Per default this setting is set to false.
In our example however this does not make any difference.
var periods = Context.getDateRanges("2011-01-01","2012-01-01","2013-01-01","2014-01-01","2015-01-01","2016-01-01","2017-01-01");
var account = new Account("Simulation", "USD", 100000.00, periods.get(0).getStart(), new PerTradeFees(6.95))
var strategies = TradingStrategyFactory.list()
var trader = new PaperTrader(account);
var allocationStrategy = new DistributedAllocationStrategy(trader);
var executor = new StrategyExecutor(trader, allocationStrategy);
executor.setImmediateLiquidationOfDiscontinuedStocks(true)
for (i <- 1 to 5) {
var year = Context.getYear(periods.get(i-1).getStart());
var portfolioUniverse = new EdgarUniverse(year, 10)
var strategySelector = new StrategySelector(account, strategies, periods.get(i-1), KPI.AbsoluteReturn)
var stockSelector = new StockSelector(strategySelector)
var result = stockSelector.getSelection(10, portfolioUniverse, reader)
executor.setStrategies(result.getStrategies(reader));
executor.run(periods.get(i));
}
account.setCloseDate(periods.get(5).getEnd())
account.getKPIValues()
[Absolute Return 110935.92901799994, Absolute Return Avarage per day 73.46750266092711, Absolute Return StdDev 1272.9836060189323, Return % 110.93592901799994, Return % per year 18.501557983147574, Return % StdDev 0.007667029354465832, Sharp Ratio 1.0845780729422094, Max Draw Down % 13.407077915993506, Max Draw Down Absolute 26276.164564999985, Max Draw Down – Number of days 67, Max Draw Down – High 195987.25933899995, Max Draw Down – Low 169711.09477399997, Max Draw Down – Period 20150720-20150825, Number of Trades 660, Number of Buys 294, Number of Sells 357, Number of Cash Transfers 1, Number of Traded Stocks 14, Total Fees 0.0, Cash 100000.0, Total Value (at actual rates) including cash 100000.0, Total Value (at purchased rates) 100000.0, Realized Gains 0.0, Unrealized Gains 0.0]
The Highest NetIncomeLoss for the last 4 years
In the examples above we did the selection of stocks from edgar based on one year. In the following example we use 4
years with decreasing weights into the past.
var periods = Context.getDateRanges("2011-01-01","2012-01-01","2013-01-01","2014-01-01","2015-01-01","2016-01-01","2017-01-01");
var account = new Account("Simulation", "USD", 100000.00, periods.get(0).getStart(), new PerTradeFees(6.95))
var strategies = TradingStrategyFactory.list()
var trader = new PaperTrader(account);
var allocationStrategy = new DistributedAllocationStrategy(trader);
var executor = new StrategyExecutor(trader, allocationStrategy);
for (i <- 1 to 5) {
var year = Context.getYear(periods.get(i-1).getStart());
var portfolioUniverse = new EdgarUniverse(year, Arrays.asList(0.1, 0.3, 0.5, 1.0), 10, Arrays.asList("NetIncomeLoss"), true)
var strategySelector = new StrategySelector(account, strategies, periods.get(i-1), KPI.AbsoluteReturn)
var stockSelector = new StockSelector(strategySelector)
var result = stockSelector.getSelection(10, portfolioUniverse, reader)
executor.setStrategies(result.getStrategies(reader));
executor.run(periods.get(i));
}
account.setCloseDate(periods.get(5).getEnd())
account.getKPIValues()
[Absolute Return 91674.36287099996, Absolute Return Avarage per day 60.7114985900662, Absolute Return StdDev 1125.80725621386, Return % 91.67436287099996, Return % per year 15.28917236498477, Return % StdDev 0.007289437564493472, Sharp Ratio 0.9964474472955415, Max Draw Down % 12.528013739524901, Max Draw Down Absolute 22594.888259, Max Draw Down – Number of days 69, Max Draw Down – High 180354.912828, Max Draw Down – Low 157760.024569, Max Draw Down – Period 20150716-20150825, Number of Trades 279, Number of Buys 100, Number of Sells 149, Number of Cash Transfers 1, Number of Traded Stocks 13, Total Fees 0.0, Cash 100000.0, Total Value (at actual rates) including cash 100000.0, Total Value (at purchased rates) 100000.0, Realized Gains 0.0, Unrealized Gains 0.0]
The Highest NetIncomeLoss % Changes for the last 4 years
In the previos examples we used the absolte parameter values to select the stock. In the following example we use
the calculated percent increase to do the selection:
var periods = Context.getDateRanges("2011-01-01","2012-01-01","2013-01-01","2014-01-01","2015-01-01","2016-01-01","2017-01-01");
var account = new Account("Simulation", "USD", 100000.00, periods.get(0).getStart(), new PerTradeFees(6.95))
var strategies = TradingStrategyFactory.list()
var trader = new PaperTrader(account);
var allocationStrategy = new DistributedAllocationStrategy(trader);
var executor = new StrategyExecutor(trader, allocationStrategy);
for (i <- 1 to 5) {
var year = Context.getYear(periods.get(i-1).getStart());
var portfolioUniverse = new EdgarUniverse(year, Arrays.asList(0.2, 0.5, 0.8, 1.0), 10, Arrays.asList("NetIncomeLoss"), true)
// calculate percentages
portfolioUniverse.setCalculatePercentChange(true)
// select only entries for which we have rates
portfolioUniverse.setReader(reader)
var strategySelector = new StrategySelector(account, strategies, periods.get(i-1), KPI.AbsoluteReturn)
var stockSelector = new StockSelector(strategySelector)
var result = stockSelector.getSelection(10, portfolioUniverse, reader)
executor.setStrategies(result.getStrategies(reader));
executor.run(periods.get(i));
}
account.setCloseDate(periods.get(5).getEnd())
account.getKPIValues()
[Absolute Return 7.534670300056998E7, Absolute Return Avarage per day 49898.47880832449, Absolute Return StdDev 750806.5447598386, Return % 75346.70300056998, Return % per year 12566.094742649659, Return % StdDev 0.8961801040280745, Sharp Ratio 0.4572988021119511, Max Draw Down % 57.63149010342141, Max Draw Down Absolute 396677.9932570002, Max Draw Down – Number of days 211, Max Draw Down – High 688300.7754010002, Max Draw Down – Low 291622.78214399994, Max Draw Down – Period 20140303-20141218, Number of Trades 2071, Number of Buys 992, Number of Sells 1005, Number of Cash Transfers 1, Number of Traded Stocks 9, Total Fees 0.0, Cash 100000.0, Total Value (at actual rates) including cash 100000.0, Total Value (at purchased rates) 100000.0, Realized Gains 0.0, Unrealized Gains 0.0]
The top R & D for the last 4 years
We assume that companies with higher R&D will be more prifitable in the futrue. Thefore we run a selection based on the
ResearchAndDevelopmentExpense parameter.
var periods = Context.getDateRanges("2011-01-01","2012-01-01","2013-01-01","2014-01-01","2015-01-01","2016-01-01","2017-01-01");
var account = new Account("Simulation", "USD", 100000.00, periods.get(0).getStart(), new PerTradeFees(6.95))
var strategies = TradingStrategyFactory.list()
var trader = new PaperTrader(account);
var allocationStrategy = new DistributedAllocationStrategy(trader);
var executor = new StrategyExecutor(trader, allocationStrategy);
for (i <- 1 to 5) {
var year = Context.getYear(periods.get(i-1).getStart());
var portfolioUniverse = new EdgarUniverse(year, Arrays.asList(0.2, 0.5, 0.8, 1.0), 10, Arrays.asList("ResearchAndDevelopmentExpense"), true)
var strategySelector = new StrategySelector(account, strategies, periods.get(i-1), KPI.AbsoluteReturn)
var stockSelector = new StockSelector(strategySelector)
var result = stockSelector.getSelection(10, portfolioUniverse, reader)
executor.setStrategies(result.getStrategies(reader));
executor.run(periods.get(i));
}
account.setCloseDate(periods.get(5).getEnd())
account.getKPIValues()
[Absolute Return 132432.49043699994, Absolute Return Avarage per day 87.70363605099334, Absolute Return StdDev 1418.0295992067922, Return % 132.43249043699993, Return % per year 22.086689338268684, Return % StdDev 0.009047709205959679, Sharp Ratio 1.0521000706609243, Max Draw Down % 17.4923968403975, Max Draw Down Absolute 31283.021613999997, Max Draw Down – Number of days 264, Max Draw Down – High 178837.82250899996, Max Draw Down – Low 147554.80089499996, Max Draw Down – Period 20150302-20160120, Number of Trades 492, Number of Buys 183, Number of Sells 273, Number of Cash Transfers 1, Number of Traded Stocks 14, Total Fees 0.0, Cash 100000.0, Total Value (at actual rates) including cash 100000.0, Total Value (at purchased rates) 100000.0, Realized Gains 0.0, Unrealized Gains 0.0]
Combining Multiple Edgar Universes
Finally we verfiy the result if we combine multiple Edgar universe queries.
var periods = Context.getDateRanges("2011-01-01","2012-01-01","2013-01-01","2014-01-01","2015-01-01","2016-01-01","2017-01-01");
var account = new Account("Simulation", "USD", 100000.00, periods.get(0).getStart(), new PerTradeFees(6.95))
var strategies = TradingStrategyFactory.list()
var trader = new PaperTrader(account);
var allocationStrategy = new DistributedAllocationStrategy(trader);
var executor = new StrategyExecutor(trader, allocationStrategy);
for (i <- 1 to 5) {
var year = Context.getYear(periods.get(i-1).getStart());
var portfolioUniverse = new ListUniverse()
portfolioUniverse.add(new EdgarUniverse(year, Arrays.asList(0.2, 0.5, 0.8, 1.0), 10, Arrays.asList("ResearchAndDevelopmentExpense"), true));
portfolioUniverse.add(new EdgarUniverse(year, Arrays.asList(0.1, 0.3, 0.5, 1.0), 10, Arrays.asList("NetIncomeLoss"), true));
var percentUniverse = new EdgarUniverse(year, Arrays.asList(0.2, 0.5, 0.8, 1.0), 10, Arrays.asList("NetIncomeLoss"), true);
percentUniverse.setCalculatePercentChange(true)
percentUniverse.setReader(reader)
portfolioUniverse.add(percentUniverse)
var strategySelector = new StrategySelector(account, strategies, periods.get(i-1), KPI.AbsoluteReturn)
var stockSelector = new StockSelector(strategySelector)
var result = stockSelector.getSelection(10, portfolioUniverse, reader)
executor.setStrategies(result.getStrategies(reader));
executor.run(periods.get(i));
}
account.setCloseDate(periods.get(5).getEnd())
account.getKPIValues()
[Absolute Return 2590477.323824001, Absolute Return Avarage per day 1715.5478965721861, Absolute Return StdDev 54115.573000169396, Return % 2590.4773238240014, Return % per year 432.0319560580068, Return % StdDev 0.35988216033679105, Sharp Ratio 0.4283444360447413, Max Draw Down % 28.32373779736678, Max Draw Down Absolute 621152.2363629988, Max Draw Down – Number of days 338, Max Draw Down – High 2193044.720322, Max Draw Down – Low 1571892.483959001, Max Draw Down – Period 20150323-20160120, Number of Trades 1165, Number of Buys 470, Number of Sells 624, Number of Cash Transfers 1, Number of Traded Stocks 20, Total Fees 0.0, Cash 100000.0, Total Value (at actual rates) including cash 100000.0, Total Value (at purchased rates) 100000.0, Realized Gains 0.0, Unrealized Gains 0.0]
Evaluation by Stock
Finally we check the contribution of each stock to the final result
account.getStockIDs()
[:ALV, :AMD, :BMY, :CCL, :CSCO, :GOOG, :GORO, :LEXG, :MXIM, :NAV, :NKE, :ORCL, :PEG, :PG, :PSX, :TORM, :UAL, :UFCS, :VMW, :XOM]
Displayers.display(account.getKPIValueByStockID(KPI.AbsoluteReturn))
Key | Value |
---|---|
:ALV | 43917.4517 |
:AMD | 374607.4 |
:BMY | 26007.5749 |
:CCL | 77770.5171 |
:CSCO | 106319.9304 |
:GOOG | 90385.743 |
:GORO | 78422.4839 |
:LEXG | 1887803.4234 |
:MXIM | 111056.0838 |
:NAV | 136403.905 |
:NKE | 109642.6169 |
:ORCL | 31564.3644 |
:PEG | 62550.7346 |
:PG | 8749.6637 |
:PSX | 79538.8133 |
:TORM | 9331.71 |
:UAL | 44121.4117 |
:UFCS | 88431.39 |
:VMW | 172154.7032 |
:XOM | -5573.9024 |
^
0 Comments