This is a backtesting framwork(again, kinda) to understand if doing SIP with any kind of strategy that people talk about are worth looking into or not.
The Current implementation takes data in CSV:
"Date","Open","High","Low","Close"
"19 Aug 2022","17966.55","17992.20","17710.75","17758.45"
and converts it to this format:
{
Date: '19 Aug 2022',
Open: '17966.55',
High: '17992.20',
Low: '17710.75',
Close: '17758.45',
momentDate: Moment<2022-08-19T00:00:00+05:30>,
UnitPrice: 17758.45
}
- UnitPrice is considered same as Nifty Closing price of that day.
- Can change it to ur favorite Fund's Daily nav
- momentDate is a internal date feild that converts the Date to a moment.js format
- Currently Nifty50 10yrs data is loaded into the script
/**
*
* @param {Number} startDate 1-31 start sip on this date
* @param {Number} sipAmount
* @param {Boolean} enableAlgo should enabled the formulae or not
* @param {typeof Formulae.formulaToBuyOn} formulaToBuyOn callback function
* @param {typeof Formulae.multiplierFormula} multiplier callback function
*/
const tradingService = new TradingService(
START_DATE,
SIP_AMOUNT,
true,
// THis is the expression that needs to hit in order to place buy order
Formulae.formulaToBuyOn,
// This is the expression that multiplies the SIP amount according to the last multiplier and how many times the formula hit in a month
Formulae.multiplierFormula,
);
The parameters:
- Start date which day of the month you want to start the SIP
- Self explanatory SIP amount
- if you want the algorithm/strategy you want to be enabled or not. Works if you want to measure the base xirr
- a Callback for the formula/Strategy/algorthm you want to create. It is an expression so returning truthy value means there will be a buy call
- a Callback for the multiplier of the SIP amount. For example if you want to invest double the amount if your formula hits then you can set it here.
- The algorithm currently baked into this is: if in a month the nifty index falls 500 points then BUY.
/**
* The expression if true a buy call will be placed
* @param {Number} startingNiftyThatMonth at the price the first sip was bought
* @param {NiftyData} niftyData
* @returns
*/
static formulaToBuyOn(startingNiftyThatMonth, niftyData) {
const actualThreshold = THRESHOLD * ((100 - PERCENTAGE_ACCEPTABLE_DELTA) / 100);
return startingNiftyThatMonth - Number(niftyData.Close) >= actualThreshold;
}
- The multiplier algorithm: First 500 buy SIP amount, if it falls another 500 invest 2x SIP amount, another 500 4x SIP amount. so, X,2X,4X and so on.
/**
* if want to increase sip amount if the formula hits
* @param {Number} lastMultiplier
* @param {Number} ithForumulaHit the formula hits for that month. Zero based. So the first Hit will be zero.
* @returns
*/
static multiplierFormula(lastMultiplier, ithForumulaHit, niftyData) {
if (!ithForumulaHit) return 1;
return lastMultiplier * 2;
}
- Clone the repo
npm install
.npm start
% npm start > sip-optimizer@1.0.0 start > nodemon -x "npx babel-node src/index.js" [nodemon] 2.0.19 [nodemon] to restart at any time, enter `rs` [nodemon] watching path(s): *.* [nodemon] watching extensions: js,mjs,json [nodemon] starting `npx babel-node src/index.js` ---------------------- AlgoEnabled: true Threshold: 500 Current Value: 1709702.3957544165 Invested Value: 885000 Profit: 824702.3957544165 XIRR: 14.58731463444985 ---------------------- [nodemon] clean exit - waiting for changes before restart
Note: Can probably use it as node module. Didn't test.
For further development, feel free to fork the repo.
- Current plans for this repo are creating a chart with different threshold amounts and different strategies and put the chart in the Readme itself.
- Instead of manually downloading the data, injesting an API(preferably free) to get the data instead.
Disclaimer: Its not like an investment tool, its a pet project for backtesting some interesting claims people make. Given that there are other tools for probably 1000x better if you want to seriously do algo-trading then I suggest you use those.