Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
let peakCapital = startingCapital;
let workingDrawdown = 0;
for (const trade of trades) {
workingCapital *= trade.growth;
if (workingCapital < peakCapital) {
workingDrawdown = workingCapital - peakCapital;
}
else {
peakCapital = workingCapital;
workingDrawdown = 0; // Reset at the peak.
}
drawdown.push(workingDrawdown);
}
return new Series(drawdown);
}
function ema(this: ISeries, period: number): ISeries {
assert.isNumber(period, "Expected 'period' parameter to 'Series.ema' to be a number that specifies the time period of the moving average.");
// https://www.investopedia.com/ask/answers/122314/what-exponential-moving-average-ema-formula-and-how-ema-calculated.asp
const mult = (2 / (period + 1));
let avgValue = this.take(period).average(); //TODO: this destroy the index.
return new Series({
index: [ this.getIndex().skip(period-1).first() ], // TODO: The construction of this 1 elements series is quite awkward.
values: [ avgValue ],
})
.concat(
this.skip(period)
.select(value => {
avgValue = ((value - avgValue) * mult) + avgValue;
return avgValue;
})
.bake()
);
}
throw new Error("Expected 'startingCapital' argument to 'computeEquityCurve' to be a positive number that specifies the amount of capital used to compute the equity curve.");
}
if (!isObject(trades) && trades.count() > 0) {
throw new Error("Expected 'trades' argument to 'computeEquityCurve' to be a Data-Forge DataFrame that contains a set of trades for which to compute the equity curve.");
}
const equityCurve: number[] = [ startingCapital ];
let workingCapital = startingCapital;
for (const trade of trades) {
workingCapital *= trade.growth;
equityCurve.push(workingCapital);
}
return new Series(equityCurve);
}
const random = new MersenneTwister(0);
const samples: IDataFrame[] = [];
for (let iterationIndex = 0; iterationIndex < numIterations; ++iterationIndex) {
const sample: ITrade[] = [];
for (var tradeIndex = 0; tradeIndex < numSamples; ++tradeIndex) {
var tradeCopyIndex = getRandomInt(random, 0, numTrades-1);
sample.push(tradesArray[tradeCopyIndex]);
}
samples.push(new DataFrame(sample));
}
return new Series>(samples);
}
if (!isObject(trades) && trades.count() > 0) {
throw new Error("Expected 'trades' argument to 'monteCarlo' to be a Data-Forge DataFrame that contains a population of trades to sample during monte carlo simulation.");
}
if (!isNumber(numIterations) || numIterations < 1) {
throw new Error("Expected 'numIterations' argument to 'monteCarlo' to be a number >= 1 that specifies the number of iteration of monte carlo simulation to perform.");
}
if (!isNumber(numSamples) || numSamples < 1) {
throw new Error("Expected 'numSamples' argument to 'monteCarlo' to be a number >= 1 that specifies the size of the sample to create for each iteration of the monte carlo simulation.");
}
const tradesArray = trades.toArray();
const numTrades = tradesArray.length;
if (numTrades === 0) {
return new Series>();
}
const random = new MersenneTwister(0);
const samples: IDataFrame[] = [];
for (let iterationIndex = 0; iterationIndex < numIterations; ++iterationIndex) {
const sample: ITrade[] = [];
for (var tradeIndex = 0; tradeIndex < numSamples; ++tradeIndex) {
var tradeCopyIndex = getRandomInt(random, 0, numTrades-1);
sample.push(tradesArray[tradeCopyIndex]);
}
samples.push(new DataFrame(sample));
}