Calculating Trades

Overview


Once you have a dataset that has asset prices and whatever indicators you wish to use to trade, you can calculate the trades of a given trading algorithm.

Trade Algorithm


A trade algorithm is a function that takes a record that contains the prices of all assets (and includes any indicators that have been calculated) and determines the relevant amount of each asset to hold over the coming period. Here we are assuming that our dataset is of the merged form.


let trade = function(price, portfolio){
	//calculate trades
	//return an object that has keys representing the asset ids 
	//with values that represent the number of units invested
}
					


Once a trade algorithm has been designed, you can calculate the trades once you have a datset.


let calculateTrades = async function(data, trade){
  let nav = 1;
  let portfolio = {cash:1};
  let stats = {};
  let results = [];
  for(let i=0;i<prices.length;i++){
    nav = 0;
    let price = prices[i];
    if('cash' in portfolio) nav+=portfolio.cash;
    for(let key in portfolio){
      if(key!=='cash') nav += price.close*portfolio[key];
    }
    portfolio = await trade(price, portfolio, nav, stats);
    results.push({
      nav:nav,
      portfolio:{...portfolio}
    });
  }
  return results;
}
					


This algorithm assumes that the prices are closing prices and that trades occur at the close. This function can be found in the trade module.


let td = await import('/lib/finance/backtest/v1.0.0/trade.mjs');

let trades = td.calculateTrades(price, trade);
					


Example


A complete example of calculating a backtest is given below. Starting with a set of prices, we add indicators to that set (in this example, we calculate backward looking returns) and append them to th price object. Then we run the backteset, using a trade function that fully invests if the current return is less than one, otherwise it goes to cash. (not an interesting or even intelligent trade strategy, but it demonstrates how to do the calculation)


let td = await import("/lib/finance/backtest/v1.0.0/trade.mjs");

let prices = [
	{date:'2000-01-01', close:100, id:'IBM'},
	{date:'2000-01-02', close:101, id:'IBM'},
	{date:'2000-01-03', close:100, id:'IBM'},
	{date:'2000-01-04', close:99, id:'IBM'},
	{date:'2000-01-05', close:102, id:'IBM'},
  ];

  //calculate the necessary indicators needed by the trade algorithm
  //in this case, we need to calculate the returns
prices = prices.map((p,i,data)=>{
  let result = {
    date:p.date,
    IBM:p.close,
    "return":null
  };
  if(i>0) result.return = p.close/data[i-1].close
  return result;
 }); 

let results = await td.calculateTrades(prices, (price, nav, portfolio)=>{
  if(price.return !== null && price.return < 1) return {IBM:nav/price.IBM};
  else return {cash:nav}
});
					
Try it!


Example Trade Functions


Trade Examples is a list of sample trade functions.

Extracting the NAV


Once you have calculated your trading strategy as above, you will want to compute various statistics to help assess the effectiveness of the strategy. The primary statistic is probably the NAV, from which you can compute a number of other statistics.

If you calculated the nav as above and set that value on each record, you can just use the map function to retrieve the NAV's as a separate array.


let nav = prices.map(p=>p.nav)
					

Contents