Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
}
const seriesPlotDefaults: IPlotConfig = {
legend: {
show: false,
},
};
function plotSeries(this: ISeries, plotConfig?: IPlotConfig, axisMap?: IAxisMap): IPlotAPI {
const serializedData = this
.inflate((value: any) => ({ __value__: value }))
.serialize();
return new PlotAPI(serializedData, plotConfig || {}, axisMap || {}, seriesPlotDefaults);
}
Series.prototype.startPlot = startPlot;
Series.prototype.endPlot = endPlot;
Series.prototype.plot = plotSeries;
//
// Augment IDataFrame and DataFrame with plot function.
//
declare module "data-forge/build/lib/dataframe" {
interface IDataFrame {
startPlot(): void;
endPlot(): void;
plot(plotDef?: IPlotConfig, axisMap?: IAxisMap): IPlotAPI;
}
interface DataFrame {
startPlot(): void;
const seriesPlotDefaults: IPlotConfig = {
legend: {
show: false,
},
};
function plotSeries(this: ISeries, plotConfig?: IPlotConfig, axisMap?: IAxisMap): IPlotAPI {
const serializedData = this
.inflate((value: any) => ({ __value__: value }))
.serialize();
return new PlotAPI(serializedData, plotConfig || {}, axisMap || {}, seriesPlotDefaults);
}
Series.prototype.startPlot = startPlot;
Series.prototype.endPlot = endPlot;
Series.prototype.plot = plotSeries;
//
// Augment IDataFrame and DataFrame with plot function.
//
declare module "data-forge/build/lib/dataframe" {
interface IDataFrame {
startPlot(): void;
endPlot(): void;
plot(plotDef?: IPlotConfig, axisMap?: IAxisMap): IPlotAPI;
}
interface DataFrame {
startPlot(): void;
endPlot(): void;
const seriesPlotDefaults: IPlotConfig = {
legend: {
show: false,
},
};
function plotSeries(this: ISeries, plotConfig?: IPlotConfig, axisMap?: IAxisMap): IPlotAPI {
const serializedData = this
.inflate((value: any) => ({ __value__: value }))
.serialize();
return new PlotAPI(serializedData, plotConfig || {}, axisMap || {}, seriesPlotDefaults);
}
Series.prototype.startPlot = startPlot;
Series.prototype.endPlot = endPlot;
Series.prototype.plot = plotSeries;
//
// Augment IDataFrame and DataFrame with plot function.
//
declare module "data-forge/build/lib/dataframe" {
interface IDataFrame {
startPlot(): void;
endPlot(): void;
plot(plotDef?: IPlotConfig, axisMap?: IAxisMap): IPlotAPI;
}
interface DataFrame {
startPlot(): void;
endPlot(): void;
/**
* Compute the momentum.
* https://en.wikipedia.org/wiki/Momentum_(technical_analysis)
*/
function momentum(this: ISeries, period: number): ISeries {
assert.isNumber(period, "Expected 'period' parameter to 'Series.momentum' to be a number that specifies the time period for computing momentum.");
return this.rollingWindow(period)
.select<[IndexT, number]>(window => [window.getIndex().last(), window.last() - window.first()])
.withIndex(pair => pair[0])
.select(pair => pair[1]);
}
Series.prototype.momentum = momentum;
value: window.last(),
middle: avg,
upper: avg + (stddev * stdDevMultUpper),
lower: avg - (stddev * stdDevMultLower),
}
return [
window.getIndex().last(),
bollingerRecord
];
})
.withIndex(pair => pair[0])
.inflate(pair => pair[1]);
};
Series.prototype.bollinger = bollinger;
assert.isNumber(period, "Expected 'period' parameter to 'Series.roc' to be a number that specifies the time period for computing rate of change.");
return this.rollingWindow(period)
.select<[IndexT, number]>(window => {
const first = window.first();
return [
window.getIndex().last(),
((window.last() - first) / first) * 100
];
})
.withIndex(pair => pair[0])
.select(pair => pair[1]);
}
Series.prototype.roc = roc;
interface Series {
sma(period: number): ISeries;
}
}
function sma(this: ISeries, period: number): ISeries {
assert.isNumber(period, "Expected 'period' parameter to 'Series.sma' to be a number that specifies the time period of the moving average.");
return this.rollingWindow(period)
.select<[IndexT, number]>(window => [window.getIndex().last(), window.average()])
.withIndex(pair => pair[0])
.select(pair => pair[1]);
}
Series.prototype.sma = sma;
}
}
function direction(this: ISeries, period: number = 2): ISeries {
assert.isNumber(period, "Expected 'period' parameter to 'Series.direction' to be a number that specifies the time period for the direction test.");
return this.rollingWindow(2)
.select<[IndexT, number]>(window => [
window.getIndex().last(),
Math.sign(window.last() - window.first()),
])
.withIndex(pair => pair[0])
.select(pair => pair[1]);
}
Series.prototype.direction = direction;
.withSeries("Uptrend", upTrend)
.withSeries("Downtrend", downTrend)
.deflate((row: any) => row.Uptrend && row.Uptrend || row.Downtrend)
.select((value) => {
if (typeof(value) === "number" && value < 0 || value > 0) {
prevTrendValue = value;
return value;
}
else {
return prevTrendValue;
}
})
.bake();
}
Series.prototype.trends = trends;
function crsi(this: ISeries, rsiPeriod: number, streakRsiPeriod: number, percentRankPeriod: number): ISeries {
assert.isNumber(rsiPeriod, "Expected 'rsiPeriod' parameter to 'DataFrame.crsi' to be a number that specifies the time period for the rsi component of crsi.");
assert.isNumber(streakRsiPeriod, "Expected 'streakRsiPeriod' parameter to 'DataFrame.crsi' to be a number that specifies the time period for the streak/updown component of crsi.");
assert.isNumber(percentRankPeriod, "Expected 'percentRankPeriod' parameter to 'DataFrame.crsi' to be a number that specifies the time period for the roc component of crsi.");
const rsi = this.rsi(rsiPeriod);
const streaks = this.streaks(2).rsi(streakRsiPeriod);
const percentRank = this.amountChange(2).bake().percentRank(percentRankPeriod); //TODO: Don't want to have to do this bake. But %rank is quite slow otherwise.
return rsi.merge(streaks, percentRank)
.where(values => values.filter(value => value !== undefined).length === 3)
.select(([rsi, streak, percentRank]) => (rsi + streak + percentRank)/3);
}
Series.prototype.crsi = crsi;