联系我们
简单又实用的WordPress网站制作教学
当前位置:网站首页 > 程序开发学习 > 正文

Investor – A Java Quantitative Trading Library

作者:小教学发布时间:2023-10-02分类:程序开发学习浏览:77


导读:Investor–AJavaQuantitativeTradingLibraryPublishedbypschatzmannon30.May2018...

Investor – A Java Quantitative Trading Library

Published by pschatzmann on 30. May 2018

Introduction

Last year I was busy to build my own project which provides an easy to use functionality to implement and evaluate automatic stock trading strategies. It is implemented in java and therefore can be used in any environment which builds on the JVM.

It provides the following functionality:
– Simple access to stock data
– Declarative formulation of trading strategies
– Evaluation of trading strategies
– Optimization of trading strategies
– Support of portfolio of multiple stocks / trading strategies

At the end it should be possible to easily formulate and evaluate stock strategy and to evaluate the impact of changes on assumptions.

In this document we demonstrates the basic functionality using Scala: We are using JupyterLab with the BeakerX Scala Kernel. The Jupyter source code can be found on github. And finally here is the link to the Javadoc.

Setup

We need to add the java libraries:

%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

Added new repo: maven-public

Imports

First we define all the imports which are used in this demo:

// 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;

// ta4j
import org.ta4j.core._;
import org.ta4j.core.analysis._;
import org.ta4j.core.analysis.criteria._;
import org.ta4j.core.indicators._;
import org.ta4j.core.indicators.helpers._;
import org.ta4j.core.trading.rules._;

// 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.integration.ChartData.FieldName._
import ch.pschatzmann.stocks.strategy.OptimizedStrategy.Schedule._
import java.util.stream...

We register the automatic displayers for charts. We are also not interested in information messages from the log, so we define a higher log level:

Displayers.setup("WARN")

true

Basic Data Structures: Universe, StockID, StockData

A StockID is identifiying a stock by the trading symbol and the exchange.

The Uninverse is a collection of StockIDs. We can use the universe to find stocks or to process a collection relevant stocks.
– QuandlWIKIUniverse
– QuandlSixUniverse
– QuandlEuronextUniverse
– MarketUniverse
– JsonUniverse
– ListUniverse

var universe = new ListUniverse(Arrays.asList(new StockID("AAPL","NASDAQ")));
var values = universe.list();

Displayers.display(values)

tickerexchange
AAPLNASDAQ
var universe = new QuandlSixUniverse();
var values = Context.head(universe.list(),10);

Displayers.display(values)

tickerexchange
ARP290071876CHFSIX
AN8068571086CHFSIX
AT0000652011CHFSIX
AT0000741053CHFSIX
AT0000606306CHFSIX
AT0000676903CHFSIX
AT0000743059CHFSIX
AT0000644505CHFSIX
AT0000720008CHFSIX
AT0000697750CHFSIX

Just as a side note: The API provides java collections. It is possible to convert them to a Scala type – e.q a Seq.

var universe = new IEXUniverse();
var values = Context.head(universe.list(),10);

Displayers.display(values)

tickerexchange
A
AA
AABA
AAC
AADR
AAL
AAMC
AAME
AAN
AAOI
import scala.collection.JavaConverters;

JavaConverters.asScalaBufferConverter(values).asScala.toSeq
[[:A, :AA, :AABA, :AAC, :AADR, :AAL, :AAMC, :AAME, :AAN, :AAOI]]

The StockData is the class which provides the history of stock rates and some stock related KPIs. We need to indicate a Reader which defines the source of the data.

Currently we support
– YahooReader
– QuandlWIKIReader
– QuandlSixReader
– MarketArchiveHttpReader
– AlphaVantageReader
– IEXReader

Here is the example how to retrieve the stock history:

var stockdata = new StockData(new StockID("AAPL", "NASDAQ"), new IEXReader());

Displayers.display(Context.tail(stockdata.getHistory(),10));

indexdatelowhighopenclosingadjustmentFactorvolume
12482018-05-14187.86189.01188.1520778772
12492018-05-15185.1186.78186.4423695159
12502018-05-16186186.07188.1819183064
12512018-05-17186.36188186.9917294029
12522018-05-18186.13187.19186.3118297728
12532018-05-21186.9106188187.6318400787
12542018-05-22186.78188.375187.1615240704
12552018-05-23185.76186.35188.3620058415
12562018-05-24186.21188.77188.1523233975
12572018-05-25187.65188.23188.5817460963

Charts

Unfortunatly the BeakerX charting currently does not work in Jupyterlab. Therfore we use JFeeChart http://www.jfree.org/jfreechart/.

Now, we can display a stock chart in just 1 line:

var aapl = new StockData(new StockID("AAPL", "NASDAQ"), new MarketArchiveHttpReader());
new TimeSeriesChart().add(aapl)

Technical Analysis with TA4J

Ta4j is an open source Java library for technical analysis. It provides the basic components for creation, evaluation and execution of trading strategies.

We can use our StockData functionality as data source for TA4J to e.g. to calculate indicators:

var stockData:IStockData = new StockData(new StockID("AAPL", "NASDAQ"), new MarketArchiveHttpReader());
// translate to Ta4j TimeSeries
var series = new Ta4jTimeSeries(stockData, new DateRange(Context.date("2017-01-01"),new Date()));
// Closing Prices
var closePrice:Indicator[Decimal] = new ClosePriceIndicator(series);
// Getting the simple moving average (SMA) of the close price over the last 5 ticks
var shortSma:Indicator[Decimal] = new SMAIndicator(closePrice, 5);
// Getting a longer SMA (e.g. over the 30 last ticks)
var longSma:Indicator[Decimal] = new SMAIndicator(closePrice, 30);

// create chart
var chart = new TimeSeriesChart()
chart.add(shortSma,"shortSma")
chart.add(closePrice,"close")
chart.add(longSma,"longSma")

chart

Trading with TA4J

Here is the complete trading and evaluation example which we took from the TA4J documentation that can be found at
https://github.com/ta4j/ta4j/wiki/Getting%20started.

The example has been converted to Scala:

var stockData = new StockData(new StockID("AAPL", "NASDAQ"), new MarketArchiveHttpReader());
var series = new Ta4jTimeSeries(stockData);
var closePrice = new ClosePriceIndicator(series);

// Getting the simple moving average (SMA) of the close price over the last 5 ticks
var shortSma = new SMAIndicator(closePrice, 5);
// Getting a longer SMA (e.g. over the 30 last ticks)
var longSma = new SMAIndicator(closePrice, 30);

// Buying rules
// We want to buy:
//  - if the 5-ticks SMA crosses over 30-ticks SMA
//  - or if the price goes below a defined price (e.g $800.00)
var buyingRule = new CrossedUpIndicatorRule(shortSma, longSma)
        .or(new CrossedDownIndicatorRule(closePrice, Decimal.valueOf("800")));

// Selling rules
// We want to sell:
//  - if the 5-ticks SMA crosses under 30-ticks SMA
//  - or if if the price looses more than 3%
//  - or if the price earns more than 2%
var sellingRule = new CrossedDownIndicatorRule(shortSma, longSma)
        .or(new StopLossRule(closePrice, Decimal.valueOf("3")))
        .or(new StopGainRule(closePrice, Decimal.valueOf("2")));

var strategy = new BaseStrategy(buyingRule, sellingRule);

// Running our juicy trading strategy...
var manager = new TimeSeriesManager(series);
var tradingRecord = manager.run(strategy);
println("Number of trades for our strategy: " + tradingRecord.getTradeCount());

// Getting the cash flow of the resulting trades
var cashFlow = new CashFlow(series, tradingRecord);

// Getting the profitable trades ratio
var profitTradesRatio = new AverageProfitableTradesCriterion();
println("Profitable trades ratio: " + profitTradesRatio.calculate(series, tradingRecord));

// Getting the reward-risk ratio
var rewardRiskRatio = new RewardRiskRatioCriterion();
println("Reward-risk ratio: " + rewardRiskRatio.calculate(series, tradingRecord));

// Total profit of our strategy
// vs total profit of a buy-and-hold strategy
var vsBuyAndHold = new VersusBuyAndHoldCriterion(new TotalProfitCriterion());
println("Our profit vs buy-and-hold profit: " + vsBuyAndHold.calculate(series, tradingRecord));

"--END--"
Number of trades for our strategy: 218
Profitable trades ratio: 0.536697247706422
Reward-risk ratio: 1.8774625448568232
Our profit vs buy-and-hold profit: 0.0019066141135999938





--END--

So far we have seen how we can use our functionality toghether with TA4J to implement an automatic trading and evaluation platform.

In the next Chapter we demonstrate our own Trading Simulation and Optimization functionality.

Accounts and Paper Trader

The Account class is used to record and evaluate trades. We need to indicate the opening amount, the open date of the account and the Fees Model (IFeesModel).
We can optionally register a generic reader or a ticker specific reader which defines from where the stock information is read.

The requested stock trades are recorded with the addTransaction() method. Positive quantities are purchased, negative quantities are sold.

The paper trader implements the basic trading (simulation) functionality. We can indicate a delay (with setDelay() and the price logic with setPrice(). In our example the trade is executed on the next day with the open rate.

With the execute() method we start the processing which is processing the open unfilled orders.

var stockdata = new StockID("AAPL", "NASDAQ");
var account = new Account("Simulation","USD", 100000.00, Context.date("2015-01-01"), new PerTradeFees(10.0));

account.putReader(new MarketArchiveHttpReader());
account.addTransaction(new Transaction(Context.date("2015-01-04"), stockdata, +100l));
account.addTransaction(new Transaction(Context.date("2015-10-04"), stockdata, -90l));

var trader = new PaperTrader(account);
// configure alternative logic
trader.setDelay(new OneDayDelay());
trader.setPrice(new OpenPrice());
trader.execute();

// display the resulting transactions
Displayers.display(account.getTransactions());

activestockIDdatequantityrequestedPricefilledPricefeescommentidimpactOnCashbuyOrSellrequestedPriceType
true
KeyValue
tickerCash
exchangeAccount
2015-01-0100007217808a-02f5-4204-8c33-0ffb74e1e423100000NACashTransfer
true
KeyValue
tickerAAPL
exchangeNASDAQ
2015-01-051000102.509910d8590f3b-7f8c-4795-8eaa-a01e73ce0f91-10260.9933BuyMarket
true
KeyValue
tickerAAPL
exchangeNASDAQ
2015-10-05-900105.336410fd1bd3ec-b5fb-4a86-8521-84e9c20d9d2a9470.2776SellMarket

Trading Strategies

The heart of automatic trading are the “trading strategies”. A class which implements ITradingStrategy can be used for automatic trading. A class which implements IOptimizableTradingStrategy can be used for automatic parameter optimization and automatic trading.

The framework comes with the following standard strategies:

TradingStrategyFactory.list()
[CCICorrectionStrategy, GlobalExtremaStrategy, MovingMomentumStrategy, RSI2Strategy, BuyAndHoldStrategy]

The Fitness class will be used to evaluate the strategies. As a result it provides both the input and the calculated KPI ouput parameters and updates the account.

You can use the SimulatedFitness class if you want to avoid the update to the account.

Displayers.display(account.getTransactions().collect(Collectors.toList()))
activestockIDdatequantityrequestedPricefilledPricefeescommentidimpactOnCashbuyOrSellrequestedPriceType
true
KeyValue
tickerCash
exchangeAccount
2015-01-0100007217808a-02f5-4204-8c33-0ffb74e1e423100000NACashTransfer
true
KeyValue
tickerAAPL
exchangeNASDAQ
2015-01-051000102.509910d8590f3b-7f8c-4795-8eaa-a01e73ce0f91-10260.9933BuyMarket
true
KeyValue
tickerAAPL
exchangeNASDAQ
2015-10-05-900105.336410fd1bd3ec-b5fb-4a86-8521-84e9c20d9d2a9470.2776SellMarket
var account = new Account("Simulation","USD", 100000.00, Context.date("2015-01-01"), new PerTradeFees(10.0));
var stockdata = new StockData(new StockID("AAPL", "NASDAQ"), new MarketArchiveHttpReader());
var strategy = new RSI2Strategy(stockdata);
var trader = new PaperTrader(account);
var state = new Fitness(trader).getFitness(strategy, account.getDateRange());

// print one parameter
println("Return: " + state.result().getValue(KPI.AbsoluteReturn));

// print all parameters
Displayers.display(state.result().getParameters())
Return: 56741.0
KeyValue
ReturnPercentAnualized19
NumberOfTrades5
SharpeRatio1
MaxDrawDownPercent33517
PurchasedValue92884
ReturnPurcentStdDev0
RealizedGains-7066
NumberOfBuys3
TotalFees50
AbsoluteReturn56741
MaxDrawDownLowValue88757
MaxDrawDownNumberOfDays458
AbsoluteReturnAvaragePerDay74
ActualValue156741
MaxDrawDownHighValue122274
AbsoluteReturnStdDev1235
UnrealizedGains63858
ReturnPercent57
NumberOfTradedStocks1
Cash97
NumberOfCashTransfers1
NumberOfSells2
Displayers.display(account.getTransactions())
activestockIDdatequantityrequestedPricefilledPricefeescommentidimpactOnCashbuyOrSellrequestedPriceType
true
KeyValue
tickerCash
exchangeAccount
2015-01-0100001af70412-cea9-4c63-a3ad-5e6ba047f31b100000NACashTransfer
true
KeyValue
tickerAAPL
exchangeNASDAQ
2015-01-129660103.4187101e16cf8a-81fb-4115-8bff-6e65abc38749-99912.458BuyMarket
true
KeyValue
tickerAAPL
exchangeNASDAQ
2015-08-17-9660112.3154105bf75205-f175-4760-9ec9-6a8402bd5219108486.6756SellMarket
true
KeyValue
tickerAAPL
exchangeNASDAQ
2016-04-1510200106.332310c4543d5d-108e-4383-8088-d723dab52bfd-108468.9442BuyMarket
true
KeyValue
tickerAAPL
exchangeNASDAQ
2016-05-10-1020090.979103fbc5afb-00f2-49ca-bce4-364a77cbe0b192788.5762SellMarket
true
KeyValue
tickerAAPL
exchangeNASDAQ
2016-08-118780105.67931058710958-a9ac-49eb-861f-9ec8b66d5988-92796.3972BuyMarket
// create chart for total values
var chart = new TimeSeriesChart();
chart.add(account.getTotalValueHistory(), "Total Value")
chart.add(account.getCashHistoryForAllDates(), "Cash")
chart.add(account.getActualValueHistory(), "Actual Value")
chart.addLabels(account.getTransactions())

chart

In order to get a better understanding of the development of the values over time we can
chart the Acocunt information.

Displayers.display(account.getTransactions())
activestockIDdatequantityrequestedPricefilledPricefeescommentidimpactOnCashbuyOrSellrequestedPriceType
true
KeyValue
tickerCash
exchangeAccount
2015-01-0100001af70412-cea9-4c63-a3ad-5e6ba047f31b100000NACashTransfer
true
KeyValue
tickerAAPL
exchangeNASDAQ
2015-01-129660103.4187101e16cf8a-81fb-4115-8bff-6e65abc38749-99912.458BuyMarket
true
KeyValue
tickerAAPL
exchangeNASDAQ
2015-08-17-9660112.3154105bf75205-f175-4760-9ec9-6a8402bd5219108486.6756SellMarket
true
KeyValue
tickerAAPL
exchangeNASDAQ
2016-04-1510200106.332310c4543d5d-108e-4383-8088-d723dab52bfd-108468.9442BuyMarket
true
KeyValue
tickerAAPL
exchangeNASDAQ
2016-05-10-1020090.979103fbc5afb-00f2-49ca-bce4-364a77cbe0b192788.5762SellMarket
true
KeyValue
tickerAAPL
exchangeNASDAQ
2016-08-118780105.67931058710958-a9ac-49eb-861f-9ec8b66d5988-92796.3972BuyMarket

Trading Strategies Description

import scala.collection.JavaConversions._

var list = new ArrayList[HashMap[String,String]]()
for (strategy <-  TradingStrategyFactory.list()) {
    var map = new HashMap[String,String]();
    map.put("Name", strategy)
    map.put("Description",TradingStrategyFactory.getStrategyDesciption(strategy))
    list.add(map)
}

Displayers.display(list)
DescriptionName
Developed by Donald Lambert, the Commodity Channel Index (CCI) is a momentum oscillator that can be used to identify a new trend or warn of extreme conditions. This strategy uses weekly CCI to dictate the trading bias when it surges above +100 or plunges below -100, which are key levels noted by Lambert. Once the trading bias is set, daily CCI is used to generate trading signals when it reaches its extremes.Details can be found in stockcharts

CCICorrectionStrategy
This strategy compares the current price to the global extrema over a week. We ar going long if the close price goes below the minimum price. We are going short if the close price goes above the maximum price.GlobalExtremaStrategy
Many trading strategies are based on a process, not a single signal. This process often involves a series of steps that ultimately lead to a signal. Typically, chartists first establish a trading bias or long-term perspective. Second, chartists wait for pullbacks or bounces that will improve the risk-reward ratio. Third, chartists look for a reversal that indicates a subsequent upturn or downturn in price. The strategy put forth here uses moving average to define the trend, the Stochastic Oscillator to identify corrections within that trend and the MACD-Histogram to signal short-term reversals. It is a complete strategy based on a three step process.

http://stockcharts.com/school/doku.php?id=chart_school:trading_strategies:moving_momentum

MovingMomentumStrategy
Developed by Larry Connors, the 2-period RSI strategy is a mean-reversion trading strategy designed to buy or sell securities after a corrective period. The strategy is rather simple. Connors suggests looking for buying opportunities when 2-period RSI moves below 10, which is considered deeply oversold. Conversely, traders can look for short-selling opportunities when 2-period RSI moves above 90. This is a rather aggressive short-term strategy designed to participate in an ongoing trend. It is not designed to identify major tops or bottoms. Before looking at the details, note that this article is designed to educate chartists on possible strategies. We are not presenting a stand-alone trading strategy that can be used right out of the box. Instead, this article is meant to enhance strategy development and refinement.
See http://stockcharts.com/school/doku.php?id=chart_school:trading_strategies:rsi2.
RSI2Strategy
We buy the title when the account is opened and hold the stock. This strategy can be used as a baseline to compare the other strategies.BuyAndHoldStrategy

Comparing Trading Strategies

Here is a small example which compares the trading strategies for Apple starting from 2015-01-01

import java.util.ArrayList

def calculateResult(account:Account, strategy : IOptimizableTradingStrategy) : java.util.Map[String,Object] = {
    var state = new SimulatedFitness(account).getFitness(strategy, account.getDateRange());
    var result = state.getMap();
    // add strategy name to result
    result.put("Strategy", strategy.getClass().getSimpleName());
    return result;
}

var account = new Account("Simulation","USD", 100000.00, Context.date("2015-01-01"), new PerTradeFees(10.0));
var sd = Context.getStockData("AAPL", "NASDAQ");

var result = new ArrayList[java.util.Map[String,Object]]();
result.add(calculateResult(account, new RSI2Strategy(sd)));
result.add(calculateResult(account, new BuyAndHoldStrategy(sd)));
result.add(calculateResult(account, new CCICorrectionStrategy(sd)));
result.add(calculateResult(account, new GlobalExtremaStrategy(sd)));
result.add(calculateResult(account, new MovingMomentumStrategy(sd)));

Displayers.display(result)
PurchasedValueSharpeRatioRealizedGainsUnrealizedGainsLongSMAPeriodCashMaxDrawDownLowValueNumberOfTradesNumberOfTradedStocksEntryLimitRSIPeriodNumberOfCashTransfersAbsoluteReturnAvaragePerDayNumberOfSellsMaxDrawDownHighValueShortSMAPeriodReturnPercentAnualizedAbsoluteReturnStdDevExitLimitAbsoluteReturnNumberOfBuysReturnPercentTotalFeesMaxDrawDownNumberOfDaysActualValueMaxDrawDownPercentReturnPurcentStdDevStrategy
928841-7066638582009788757515217421222745191235955674135750458156741335170RSI2Strategy
99990107236814850031119401222012416157235817210426172358371980BuyAndHoldStrategy
794041-20566487414774745311371102875911062814522830487128145281300CCICorrectionStrategy
13983914027901398399437144115222112952131031398392240440318139839185820GlobalExtremaStrategy
1058850592501058858312141182106331274058852640331105885232100MovingMomentumStrategy

Custom Trading Strategies

Finally we demonstrate how you can implement your custom Strategy. The indicators and trading strategy functionality is based on TA4J https://github.com/ta4j/ta4j.

The simplest and fastest way is to implement a BaseStrategy by extending the CommonTradingStrategy:

import ch.pschatzmann.dates._;
import ch.pschatzmann.stocks._;
import ch.pschatzmann.stocks.accounting._;
import ch.pschatzmann.stocks.integration._;
import ch.pschatzmann.stocks.execution._;
import ch.pschatzmann.stocks.execution.fees._;
import ch.pschatzmann.stocks.strategy._;
import ch.pschatzmann.stocks.strategy.optimization._;
import ch.pschatzmann.stocks.input._;
import ch.pschatzmann.stocks.parameters._;
import org.ta4j.core._;
import org.ta4j.core.analysis._;
import org.ta4j.core.analysis.criteria._;
import org.ta4j.core.indicators._;
import org.ta4j.core.indicators.helpers._;
import org.ta4j.core.trading.rules._;
import ch.pschatzmann.display.Displayers

class DemoStrategy(sd : StockData) extends CommonTradingStrategy (sd){
    // Define BaseStrategy
    def buildStrategy(timeSeries : TimeSeries) : BaseStrategy = {
        val closePrices = new ClosePriceIndicator(timeSeries);
        // Getting the max price over the past week
        val maxPrices = new MaxPriceIndicator(timeSeries);
        val weekMaxPrice = new HighestValueIndicator(maxPrices, 7);
        // Getting the min price over the past week
        val minPrices = new MinPriceIndicator(timeSeries);
        val weekMinPrice = new LowestValueIndicator(minPrices, 7);
        // Going long if the close price goes below the min price
        val downWeek = new MultiplierIndicator(weekMinPrice, Decimal.valueOf(1.004));
        val buyingRule = new UnderIndicatorRule(closePrices, downWeek);
        // Going short if the close price goes above the max price
        val upWeek = new MultiplierIndicator(weekMaxPrice, Decimal.valueOf(0.996));
        val sellingRule = new OverIndicatorRule(closePrices, upWeek);

        return new BaseStrategy(buyingRule, sellingRule);
    }  
}

var apple = new StockData(new StockID("AAPL", "NASDAQ"), new MarketArchiveHttpReader());
var account = new Account("Simulation","USD", 100000.00, Context.date("2015-01-01"), new PerTradeFees(10.0));
var strategy = new DemoStrategy(apple);
var trader = new PaperTrader(account);
var state = new Fitness(trader).getFitness(strategy, account.getDateRange());

//println("Return: "+state.result().getValue(KPI.AbsoluteReturn));
Displayers.display(state.getMap());

KeyValue
AbsoluteReturnStdDev1031
PurchasedValue139839
SharpeRatio1
RealizedGains40279
AbsoluteReturn39839
UnrealizedGains0
NumberOfBuys22
Cash139839
ReturnPercent40
MaxDrawDownLowValue94371
TotalFees440
MaxDrawDownNumberOfDays318
NumberOfTrades44
NumberOfTradedStocks1
NumberOfCashTransfers1
ActualValue139839
MaxDrawDownPercent18582
ReturnPurcentStdDev0
AbsoluteReturnAvaragePerDay52
NumberOfSells22
MaxDrawDownHighValue112952
ReturnPercentAnualized13

An alternaive approach is to implement the interface directly:

import ch.pschatzmann.dates._;
import ch.pschatzmann.stocks._;
import ch.pschatzmann.stocks.accounting._;
import ch.pschatzmann.stocks.integration._;
import ch.pschatzmann.stocks.execution._;
import ch.pschatzmann.stocks.execution.fees._;
import ch.pschatzmann.stocks.strategy._;
import ch.pschatzmann.stocks.strategy.optimization._;
import ch.pschatzmann.stocks.input._;
import ch.pschatzmann.stocks.parameters._;
import org.ta4j.core._;
import org.ta4j.core.analysis._;
import org.ta4j.core.analysis.criteria._;
import org.ta4j.core.indicators._;
import org.ta4j.core.indicators.helpers._;
import org.ta4j.core.trading.rules._;
import ch.pschatzmann.display.Displayers

/**
 * Strategy implemented in Scala 
 */
class DemoStrategy extends ITradingStrategy {
    var state = new State();
    val stockdata = new StockData(new StockID("AAPL", "NASDAQ"), new MarketArchiveHttpReader());

    def getStrategy():Strategy = {
        var timeSeries = new Ta4jTimeSeries(getStockData());
        val closePrices = new ClosePriceIndicator(timeSeries);
        // Getting the max price over the past week
        val maxPrices = new MaxPriceIndicator(timeSeries);
        val weekMaxPrice = new HighestValueIndicator(maxPrices, 7);
        // Getting the min price over the past week
        val minPrices = new MinPriceIndicator(timeSeries);
        val weekMinPrice = new LowestValueIndicator(minPrices, 7);
        // Going long if the close price goes below the min price
        val downWeek = new MultiplierIndicator(weekMinPrice, Decimal.valueOf(1.004));
        val buyingRule = new UnderIndicatorRule(closePrices, downWeek);
        // Going short if the close price goes above the max price
        val upWeek = new MultiplierIndicator(weekMaxPrice, Decimal.valueOf(0.996));
        val sellingRule = new OverIndicatorRule(closePrices, upWeek);

        return new BaseStrategy(buyingRule, sellingRule);
    }

    def getStockData():StockData = {
        return stockdata;
    }

    def getName():String = {
        return "DemoStrategy";
    }

    def getDescription():String = {
        return "Demo strategy implemented in scala";
    }

    def getParameters():State = {
        return state;
    }

    def reset() {}

}

var account = new Account("Simulation","USD", 100000.00, Context.date("2015-01-01"), new PerTradeFees(10.0));
var strategy = new DemoStrategy();
var trader = new PaperTrader(account);
var state = new Fitness(trader).getFitness(strategy,account.getDateRange());

//println("Return: "+state.result().getValue(KPI.AbsoluteReturn));
Displayers.display(state.getMap());

KeyValue
AbsoluteReturnStdDev1031
PurchasedValue139839
SharpeRatio1
RealizedGains40279
AbsoluteReturn39839
UnrealizedGains0
NumberOfBuys22
Cash139839
ReturnPercent40
MaxDrawDownLowValue94371
TotalFees440
MaxDrawDownNumberOfDays318
NumberOfTrades44
NumberOfTradedStocks1
NumberOfCashTransfers1
ActualValue139839
MaxDrawDownPercent18582
ReturnPurcentStdDev0
AbsoluteReturnAvaragePerDay52
NumberOfSells22
MaxDrawDownHighValue112952
ReturnPercentAnualized13

see also:

  1. Deeplearning4j – Iris Classification Example
  2. Deeplearning4j – Recurrent Neural Networks (RNN)
  3. Arduino Raspberry Pico – Looking Under the Hood
  4. Multiple Wordpess Instances in Docker with NGINX & https
  5. Docker and Treafik – A Comprehensive Tutorial
  6. Docker + WordPress = Danger
  7. Microcontrollers and MIDI – Using the Bluetooth Serial Interface
  8. Identity Management and Authentication for Java Webservices and Javascript GUIs
  9. WooCommerce und Java REST Webhooks
  10. AI Thinker AudioKit – A simple Synthesizer with STK



标签:Investor – A Java Quantitative Trading Library_临水逸的博客


程序开发学习排行
最近发表
网站分类
标签列表