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

^


Leave a Reply

Your email address will not be published. Required fields are marked *