Skip to content
This repository has been archived by the owner on Feb 16, 2020. It is now read-only.

Commit

Permalink
Performance Analyzer fixes and features (#2178)
Browse files Browse the repository at this point in the history
* Update performanceAnalyzer.js

* Update logger.js

* Update logger.js

* Update performanceAnalyzer.js
  • Loading branch information
stereohelix authored and askmike committed May 17, 2018
1 parent a639317 commit c6faee1
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 16 deletions.
10 changes: 6 additions & 4 deletions plugins/performanceAnalyzer/logger.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,7 @@ if(mode === 'backtest') {
log.info(`(PROFIT REPORT) start time:\t\t\t ${report.startTime}`);
log.info(`(PROFIT REPORT) end time:\t\t\t ${report.endTime}`);
log.info(`(PROFIT REPORT) timespan:\t\t\t ${report.timespan}`);
if(report.sharpe)
log.info(`(PROFIT REPORT) sharpe ratio:\t\t\t ${report.sharpe}`);
log.info(`(PROFIT REPORT) exposure:\t\t\t ${report.exposure}`);
log.info();
log.info(`(PROFIT REPORT) start price:\t\t\t ${report.startPrice} ${this.currency}`);
log.info(`(PROFIT REPORT) end price:\t\t\t ${report.endPrice} ${this.currency}`);
Expand All @@ -109,8 +108,11 @@ if(mode === 'backtest') {
`(PROFIT REPORT) simulated yearly profit:\t ${report.yearlyProfit}`,
`${this.currency} (${report.relativeYearlyProfit}%)`
);

log.info(`(PROFIT REPORT) sharpe ratio:\t\t\t ${report.sharpe}`);
log.info(`(PROFIT REPORT) expected downside:\t\t ${report.downside}`);
}

Logger.prototype.handleRoundtrip = function(rt) {
this.roundtrips.push(rt);
}
Expand All @@ -128,4 +130,4 @@ if(mode === 'backtest') {



module.exports = Logger;
module.exports = Logger;
34 changes: 22 additions & 12 deletions plugins/performanceAnalyzer/performanceAnalyzer.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
const _ = require('lodash');
const moment = require('moment');

const stats = require('../../core/stats');
const statslite = require('stats-lite');
const util = require('../../core/util');
const ENV = util.gekkoEnv();

Expand Down Expand Up @@ -30,9 +30,10 @@ const PerformanceAnalyzer = function() {

this.trades = 0;

this.sharpe = 0;

this.exposure = 0;
this.roundTrips = [];
this.losses = [];
this.roundTrip = {
entry: false,
exit: false
Expand Down Expand Up @@ -144,14 +145,12 @@ PerformanceAnalyzer.prototype.handleCompletedRoundtrip = function() {

this.deferredEmit('roundtrip', roundtrip);

// we need a cache for sharpe

// every time we have a new roundtrip
// update the cached sharpe ratio
this.sharpe = stats.sharpe(
this.roundTrips.map(r => r.profit),
perfConfig.riskFreeReturn
);
// update cached exposure
this.exposure = this.exposure + Date.parse(this.roundTrip.exit.date) - Date.parse(this.roundTrip.entry.date);
// track losses separately for downside report
if (roundtrip.exitBalance < roundtrip.entryBalance)
this.losses.push(roundtrip);

}

PerformanceAnalyzer.prototype.calculateReportStatistics = function() {
Expand All @@ -162,6 +161,15 @@ PerformanceAnalyzer.prototype.calculateReportStatistics = function() {
this.dates.end.diff(this.dates.start)
);
const relativeProfit = this.balance / this.start.balance * 100 - 100;

const percentExposure = this.exposure / (Date.parse(this.dates.end) - Date.parse(this.dates.start));

const sharpe = (relativeYearlyProfit - perfConfig.riskFreeReturn)
/ statslite.stdev(this.roundTrips.map(r => r.profit))
/ Math.sqrt(this.trades / (this.trades - 2));

const downside = statslite.percentile(this.losses.map(r => r.profit), 0.25)
* Math.sqrt(this.trades / (this.trades - 2));

const report = {
startTime: this.dates.start.utc().format('YYYY-MM-DD HH:mm:ss'),
Expand All @@ -180,7 +188,9 @@ PerformanceAnalyzer.prototype.calculateReportStatistics = function() {
endPrice: this.endPrice,
trades: this.trades,
startBalance: this.start.balance,
sharpe: this.sharpe
exposure: percentExposure,
sharpe,
downside
}

report.alpha = report.profit - report.market;
Expand Down

0 comments on commit c6faee1

Please sign in to comment.