portfolio-analytics

0.0.4 • Public • Published

| French version

PortfolioAnalytics v0.0.4 (Changelog)

Travis Build Status

In order to track my personal stock market investments performances, as well as to analyse trading strategies on my blog Le Quant 40, I wanted to use portfolio performances measures computed in JavaScript.

Why in JavaScript ? Because I am a fan of Google Sheets, which is easily extensible thanks to Google Apps Script, a JavaScript-based language.

After several fruitless hours of Googling (incomplete codes, incorrect codes, undocumented codes...), I decided to create my own JavaScript library of such portfolio performances measures, hoping that it could be useful to other people...

Features

  • Compatible with Google Sheets
  • Compatible with any browser supporting ECMAScript 5 (i.e., front-end development)
  • Compatible with Node.js (i.e., back-end development)
  • (Performances) Automatically uses JavaScript Typed Arrays
  • (Accuracy) Internally uses accurate numerical algorithms (e.g., corrected two pass algorithms for mean, variance, skewness and kurtosis, accurate algorithm for error function...)
  • Code continuously tested and integrated by Travis CI
  • Code heavily documented using JSDoc

Usage

Usage in Google Sheets

If you would like to use PortfolioAnalytics in Google Sheets, you can either:

or:

  • Import the JavaScript files from the dist/gs directory into your spreadsheet script

In both cases, providing data to the PortfolioAnalytics functions is then accomplished your preferred way:

  • Using a wrapper function in your spreadsheet script, directly accessible from your spreadsheet, to which you can provide a standard data range (A1:A99...), e.g.:
function computeUlcerIndexWrapper(iEquityCurveRange) {
  // Convert the input range coming from the spreadsheet into an array
  var aInternalArray = [];
  for (var i=0; i<iEquityCurveRange.length; ++i) {
    aInternalArray.push(iEquityCurveRange[i][0]);
  }
    
  // Compute the index
  var ulcerIndex = PortfolioAnalytics.ulcerIndex(aInternalArray);
  
  // Return it to the spreadsheet
  return ulcerIndex;
}
  • Using pure Google Apps Script functions - typically the getRange(...) familly of functions -, optimized for speed, e.g.:
function computeUlcerIndex() {
  // Adapted from https://developers.google.com/apps-script/reference/spreadsheet/sheet#getrangerow-column-numrows
 var ss = SpreadsheetApp.getActiveSpreadsheet();
 var sheet = ss.getSheets()[0];
 var range = sheet.getRange(1, 1, 100); // A1:A100
 var values = range.getValues();
 
 // Convert the above range into an array
 var aInternalArray = [];
 for (var row in values) {
   for (var col in values[row]) {
     aInternalArray.push(values[row][col]);
   }
 }
 
  // Compute the index
  var ulcerIndex = PortfolioAnalytics.ulcerIndex(aInternalArray);
  
  // Do something with it (use it in a computation, write it back to the spreadsheet, etc.)
  ...
}

You can find examples of PortfolioAnalytics usage in this spreadsheet.

Usage inside a browser

If you would like to use PortfolioAnalytics inside a browser you can download its source code and/or its minified source code.

You then just need to include this code in an HTML page, e.g.:

<script src="portfolio_analytics.dist.min.js" type="text/javascript"></script>

To be noted that if the browser is compatible with JavaScript Typed Arrays, you can provide such arrays in input to PortfolioAnalytics for better performances, e.g.:

PortfolioAnalytics.arithmeticReturns(new Float64Array([100.0, 109.75, 111.25]))
// Will output a Float64Array

Usage with Node.js

If you would like to use PortfolioAnalytics with Node.js, you simply need to declare it as a dependency of your project in your package.json file.

Then, this is standard Node.js code, e.g.:

var PortfolioAnalytics = require('portfolio-analytics');
...
var ui = PortfolioAnalytics.ulcerIndex([100, 110, 105, 102, 95]);
// ui == 0.07204222820421435

Examples

Drawdowns related measures

PortfolioAnalytics.maxDrawdown([1, 2, 1]); 
// The maximum drawdown
 
PortfolioAnalytics.drawdownFunction([1, 2, 1]); 
// The drawdown function
 
PortfolioAnalytics.topDrawdowns([1, 2, 1], 1); 
// The top 'n' drawdowns (second largest drawdown, etc.) with their start/end indexes
 
PortfolioAnalytics.ulcerIndex([1, 2, 1]);
// The Ulcer Index
 
PortfolioAnalytics.painIndex([1, 2, 1]);
// The Pain Index, also corresponding to the average of the drawdown function
 
PortfolioAnalytics.conditionalDrawdown([100, 90, 80], 0.5);
// The conditional drawdown

Returns related measures

PortfolioAnalytics.cumulativeReturn([1, 2, 1]); 
// The cumulative return from first to last period
 
PortfolioAnalytics.cagr([1, 2, 1], [new Date("2015-12-31"), new Date("2016-12-31"), new Date("2017-12-31")]); 
// The compound annual growth rate (CAGR) from first to last date
 
PortfolioAnalytics.arithmeticReturns([1, 2, 1]); 
// The arithmetic returns for all periods
 
PortfolioAnalytics.valueAtRisk([1, 2, 1], 0.7);
// The (percent) value at risk

Sharpe ratio related measures

PortfolioAnalytics.sharpeRatio([100, 110, 105, 107.5, 115], [100, 100, 100, 100, 100]); 
// The Sharpe ratio
 
PortfolioAnalytics.biasAdjustedSharpeRatio([100, 110, 105, 107.5, 115], [100, 100, 100, 100, 100]); 
// The Sharpe ratio adjusted for its bias
 
PortfolioAnalytics.doubleSharpeRatio([100, 110, 105, 107.5, 115], [100, 100, 100, 100, 100]); 
// The double Sharpe ratio (i.e., the Sharpe ratio, adjusted for its estimation risk)
 
PortfolioAnalytics.sharpeRatioConfidenceInterval([100, 110, 105, 107.5, 115], [100, 100, 100, 100, 100], 0.05); 
// The confidence interval for the Sharpe ratio (here, at 5% significance level)
 
PortfolioAnalytics.probabilisticSharpeRatio([100, 110, 105, 107.5, 115], [100, 100, 100, 100, 100], 0); 
// The probabilistic Sharpe ratio (i.e., the probability that the Sharpe ratio is greater 
// than a reference Sharpe ratio, here 0)
 
PortfolioAnalytics.minimumTrackRecordLength([100, 110, 105, 107.5, 115], [100, 100, 100, 100, 100], 0.05, 0); 
// The minimum track record length (i.e., the minimal length of the track record of the performance 
// to have statistical confidence, here at 95%, that the Sharpe ratio is greater than a reference Sharpe ratio, here 0)

Returns to variability related measures

PortfolioAnalytics.gainToPainRatio([1, 2, 1]); 
// The gain to pain ratio

How to contribute ?

Fork the projet from Github...

Instal the Grunt dependencies

npm install

Develop...

Compile

  • The following command generates the files to be used inside a browser or with Node.js in the dist directory:
grunt deliver
  • The following command generates the files to be used in Google Sheets in the dist\gs directory:
grunt deliver-gs

Test

Any of the following two commands run the QUnit unit tests contained in the test directory on the generated file dist\portfolio_analytics.dev.min.js:

npm test
grunt test

Submit a pull-request...

License

MIT License

Package Sidebar

Install

npm i portfolio-analytics

Weekly Downloads

32

Version

0.0.4

License

MIT

Last publish

Collaborators

  • lequant40