quant-zero
Version:
Node-Quant is a powerful Node.js package for developing and testing quantitative trading strategies in cryptocurrency markets, offering tools for backtesting and performance analysis.
1,032 lines (991 loc) • 30.5 kB
JavaScript
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var index_exports = {};
__export(index_exports, {
ChartingSystem: () => ChartingSystem,
CryptoPair: () => CryptoPair,
DataSourceType: () => DataSourceType,
Indicator: () => Indicator,
Indicators: () => indicators_exports,
Logger: () => Logger,
NumberReturnType: () => NumberReturnType,
OrderType: () => OrderType,
PositionType: () => PositionType,
ReportManager: () => ReportManager,
Strategy: () => Strategy,
TRADE_KEY: () => TRADE_KEY,
TimeFrame: () => TimeFrame,
TimelineEvents: () => TimelineEvents,
Trade: () => Trade,
TradeManager: () => TradeManager,
logger: () => logger
});
module.exports = __toCommonJS(index_exports);
// src/lib/ChartingSystem.ts
var ChartingSystem = class {
transform(rawData) {
return rawData;
}
};
// src/lib/Indicator.ts
var import_events = require("events");
// src/types.ts
var CryptoPair = /* @__PURE__ */ ((CryptoPair2) => {
CryptoPair2["BTCUSDT"] = "BTC/USDT";
CryptoPair2["ETHUSDT"] = "ETH/USDT";
CryptoPair2["SOLUSDT"] = "SOL/USDT";
CryptoPair2["BNBUSDT"] = "BNB/USDT";
CryptoPair2["LTCUSDT"] = "LTC/USDT";
CryptoPair2["DOGEUSDT"] = "DOGE/USDT";
return CryptoPair2;
})(CryptoPair || {});
var TimelineEvents = /* @__PURE__ */ ((TimelineEvents2) => {
TimelineEvents2["PROVIDED"] = "provided";
TimelineEvents2["FED"] = "fed";
TimelineEvents2["GENERATED"] = "generated";
return TimelineEvents2;
})(TimelineEvents || {});
var NumberReturnType = /* @__PURE__ */ ((NumberReturnType3) => {
NumberReturnType3["RELATIVE"] = "relative";
NumberReturnType3["FIXED"] = "fixed";
return NumberReturnType3;
})(NumberReturnType || {});
var OrderType = /* @__PURE__ */ ((OrderType2) => {
OrderType2["MARKET"] = "market";
OrderType2["LIMIT"] = "limit";
OrderType2["STOP"] = "stop";
return OrderType2;
})(OrderType || {});
var PositionType = /* @__PURE__ */ ((PositionType3) => {
PositionType3["LONG"] = "long";
PositionType3["SHORT"] = "short";
return PositionType3;
})(PositionType || {});
var TRADE_KEY = /* @__PURE__ */ ((TRADE_KEY2) => {
TRADE_KEY2["ID"] = "id";
TRADE_KEY2["isOpen"] = "isOpen";
TRADE_KEY2["isClosed"] = "isClosed";
TRADE_KEY2["PL"] = "PL";
TRADE_KEY2["TP"] = "TP";
TRADE_KEY2["SL"] = "SL";
TRADE_KEY2["positionSize"] = "size";
TRADE_KEY2["leverage"] = "leverage";
TRADE_KEY2["drawdown"] = "drawdown";
TRADE_KEY2["openPrice"] = "openPrice";
TRADE_KEY2["closePrice"] = "closePrice";
TRADE_KEY2["fee"] = "fee";
TRADE_KEY2["pair"] = "pair";
TRADE_KEY2["blockChainTrack"] = "blockChainTrack";
TRADE_KEY2["orderType"] = "orderType";
TRADE_KEY2["positionType"] = "positionType";
TRADE_KEY2["timestamp"] = "timestamp";
return TRADE_KEY2;
})(TRADE_KEY || {});
var DataSourceType = /* @__PURE__ */ ((DataSourceType2) => {
DataSourceType2["PRICE"] = "price";
DataSourceType2["FACTOR"] = "factor";
return DataSourceType2;
})(DataSourceType || {});
var TimeFrame = /* @__PURE__ */ ((TimeFrame2) => {
TimeFrame2["SECOND"] = "1s";
TimeFrame2["MINUTE"] = "1m";
TimeFrame2["TWO_MINUTES"] = "2m";
TimeFrame2["THREE_MINUTES"] = "3m";
TimeFrame2["FIVE_MINUTES"] = "5m";
TimeFrame2["TEN_MINUTES"] = "10m";
TimeFrame2["FIFTEEN_MINUTES"] = "15m";
TimeFrame2["THIRTY_MINUTES"] = "30m";
TimeFrame2["FORTY_FIVE_MINUTES"] = "45m";
TimeFrame2["HOUR"] = "1h";
TimeFrame2["TWO_HOURS"] = "2h";
TimeFrame2["THREE_HOURS"] = "3h";
TimeFrame2["FOUR_HOURS"] = "4h";
TimeFrame2["DAY"] = "1d";
TimeFrame2["WEEK"] = "1w";
TimeFrame2["MONTH"] = "1M";
return TimeFrame2;
})(TimeFrame || {});
// src/lib/Indicator.ts
var Indicator = class extends import_events.EventEmitter {
data = [];
name;
key;
description;
constructor({ name, key, description }) {
super();
this.name = name;
this.key = key;
this.description = description;
}
// Provides the first sample of data if not already provided
provide(data) {
if (this.data.length === 0 && data.length > 0) {
this.data = data;
this.emit("provided" /* PROVIDED */, this.data);
}
}
// Feeds new data in
feed(data) {
this.data.push(data);
this.emit("fed" /* FED */, data);
}
// Generates the result
generate() {
return null;
}
clear() {
this.data = [];
}
on(event, listener) {
return super.on(event, listener);
}
};
// src/lib/Logger.ts
var import_chalk = __toESM(require("chalk"), 1);
var Logger = class {
success(payload) {
console.log(import_chalk.default.green(payload));
}
debug(payload) {
console.log(payload);
}
info(payload) {
console.log(import_chalk.default.cyan(payload));
}
warn(payload) {
console.log(import_chalk.default.yellow(payload));
}
error(payload) {
console.log(import_chalk.default.red(payload));
}
};
var logger = new Logger();
// src/lib/Strategy.ts
var import_fs2 = __toESM(require("fs"), 1);
var import_path2 = __toESM(require("path"), 1);
// src/utils/dataInstaller.ts
var import_fs = __toESM(require("fs"), 1);
var import_path = __toESM(require("path"), 1);
// src/exchange.ts
var import_ccxt = __toESM(require("ccxt"), 1);
var exchange = new import_ccxt.default.binance();
var exchange_default = exchange;
// src/utils/dataInstaller.ts
async function downloadPairData(pair, timeFrame, dataLength, dataFolderPath) {
const fileName = `${pair.replace("/", "_")}_${dataLength}_${timeFrame}.json`;
const filePath = import_path.default.join(dataFolderPath, fileName);
if (import_fs.default.existsSync(filePath)) {
console.log(
`Data for ${pair} with length ${dataLength} already exists. Returning existing data.`
);
const existingData = import_fs.default.readFileSync(filePath, "utf-8");
return { path: filePath, data: JSON.parse(existingData) };
}
console.log(`Installing ${dataLength} candles for ${pair}.`);
const fetchedData = await exchange_default.fetchOHLCV(
pair,
timeFrame,
void 0,
dataLength,
{
paginate: true
}
);
import_fs.default.writeFileSync(filePath, JSON.stringify(fetchedData, null, 2));
return { path: filePath, data: fetchedData };
}
// src/utils/parseOHLCV.ts
var parseIntoRows = (data) => {
const timestamps = [];
const opens = [];
const highs = [];
const lows = [];
const closes = [];
const volumes = [];
data.forEach((candle) => {
timestamps.push(candle[0]);
opens.push(candle[1]);
highs.push(candle[2]);
lows.push(candle[3]);
closes.push(candle[4]);
volumes.push(candle[5]);
});
return { timestamps, opens, highs, lows, closes, volumes };
};
// src/charting/CandleSticks.ts
var CandleSticks = class extends ChartingSystem {
transform(rawData) {
const { opens, highs, lows, closes, timestamps, volumes } = parseIntoRows(rawData);
return {
open: opens,
high: highs,
low: lows,
close: closes,
timestamp: timestamps,
volume: volumes
};
}
};
// src/charting/HeikenAishi.ts
var import_technicalindicators = __toESM(require("technicalindicators"), 1);
// src/charting/Renko.ts
var import_technicalindicators2 = __toESM(require("technicalindicators"), 1);
// src/utils/generateId.ts
var import_crypto = __toESM(require("crypto"), 1);
var generateMD5Id = () => {
const seed = Math.random().toString();
return import_crypto.default.createHash("md5").update(seed).digest("hex");
};
// src/utils/maths/pl.ts
function calcPL(currentClose, openPrice, positionType) {
return positionType === "long" /* LONG */ ? 100 * ((currentClose - openPrice) / openPrice) : 100 * ((openPrice - currentClose) / openPrice);
}
// src/lib/Trade.ts
var Trade = class {
id;
tradeData;
constructor(options) {
this.id = generateMD5Id();
this.tradeData = /* @__PURE__ */ new Map([
["id" /* ID */, this.id],
["size" /* positionSize */, options.positionSize],
["leverage" /* leverage */, options.leverage],
["TP" /* TP */, options.TP],
["SL" /* SL */, options.SL],
["PL" /* PL */, 0],
["drawdown" /* drawdown */, 0],
["closePrice" /* closePrice */, void 0],
["openPrice" /* openPrice */, void 0],
["isClosed" /* isClosed */, false],
["fee" /* fee */, void 0],
["blockChainTrack" /* blockChainTrack */, void 0],
["timestamp" /* timestamp */, Date.now()],
["pair" /* pair */, options.pair],
["orderType" /* orderType */, options.orderType],
["positionType" /* positionType */, options.positionType],
["isOpen" /* isOpen */, options.open ?? false]
]);
}
open() {
if (!this.tradeData.get("isClosed" /* isClosed */)) {
this.tradeData.set("isOpen" /* isOpen */, true);
}
}
close() {
this.tradeData.set("isOpen" /* isOpen */, false);
}
updateTP(TP) {
this.tradeData.set("TP" /* TP */, TP);
}
updateSL(SL) {
this.tradeData.set("SL" /* SL */, SL);
}
getData() {
return Object.fromEntries(this.tradeData);
}
onUpdate(update, updates) {
if (this.tradeData.get("isClosed" /* isClosed */)) return;
const currentClose = Number(update.at(4) ?? 0);
if (!currentClose || currentClose === 0) return;
const openPrice = this.tradeData.get("openPrice" /* openPrice */);
const positionType = this.tradeData.get("positionType" /* positionType */);
if (!openPrice) {
this.tradeData.set("openPrice" /* openPrice */, currentClose);
return;
}
const pl = calcPL(currentClose, openPrice, positionType);
this.tradeData.set("PL" /* PL */, pl);
this.tradeData.set("closePrice" /* closePrice */, currentClose);
const currentDrawdown = this.tradeData.get("drawdown" /* drawdown */);
if (pl < currentDrawdown) {
this.tradeData.set("drawdown" /* drawdown */, pl);
}
}
getFootprint() {
}
};
// src/managers/TradeManager.ts
var TradeManager = class {
trades = /* @__PURE__ */ new Map();
strategy;
constructor(strategy) {
this.strategy = strategy;
}
onUpdate(update, updates) {
for (const trade of this.trades.values()) {
if (!trade.getData()["isClosed" /* isClosed */]) {
trade.onUpdate(update, updates);
}
}
}
getTrade(id) {
return this.trades.get(id) || null;
}
getTrades() {
return Array.from(this.trades.values());
}
createTrade(options) {
const trade = new Trade({
orderType: options.orderType,
pair: this.strategy.strategyOptions.pair,
positionSize: options.size,
positionType: options.positionType,
leverage: options.leverage ?? 1,
open: options.open ?? false,
SL: options.riskOptions?.SL,
TP: options.riskOptions?.TP,
isLive: false
});
this.trades.set(trade.id, trade);
return trade;
}
getTradeHistory() {
const trades = this.getTrades();
return trades.filter(async (trade) => {
const tradeData = await trade.getData();
return tradeData["isClosed" /* isClosed */];
});
}
closeTrade(tradeId) {
this.getTrade(tradeId)?.close();
}
clear() {
this.trades = /* @__PURE__ */ new Map();
}
};
// src/utils/maths/alpha.ts
function calcAlpha(r, rf = 0, beta, rm) {
return r - rf - beta * (rm - rf);
}
// src/utils/maths/beta.ts
function calcBeta(covariance, variance) {
return covariance / variance;
}
// src/utils/maths/covariance.ts
function calcCovariance(returns, marketReturn) {
const meanReturn = returns.reduce((sum, r) => sum + r, 0) / returns.length;
return returns.reduce(
(cov, r) => cov + (r - meanReturn) * (marketReturn - meanReturn),
0
) / returns.length;
}
// src/utils/maths/sharpeE.ts
function calcSharpeE(E, rp, rf = 0, sp) {
return E * (rp - rf) / sp;
}
// src/utils/maths/variance.ts
function calcVariance(returns) {
const meanReturn = returns.reduce((sum, r) => sum + r, 0) / returns.length;
return returns.reduce((varSum, r) => varSum + Math.pow(r - meanReturn, 2), 0) / returns.length;
}
// src/utils/maths/standarddev.ts
function calcStddev(returns) {
return Math.sqrt(calcVariance(returns));
}
// src/utils/getAvgMarketReturn.ts
async function getAvgMarketReturn(pair, timeFrame, dataLength) {
const data = await exchange_default.fetchOHLCV(
pair,
timeFrame,
void 0,
dataLength,
{ paginate: true }
);
let totalReturn = 0;
for (let i = 1; i < data.length; i++) {
const prevCandle = data[i - 1];
const currCandle = data[i];
if (!prevCandle || !currCandle) continue;
const prevClose = Number(prevCandle[4]);
const currClose = Number(currCandle[4]);
const returnPct = (currClose - prevClose) / prevClose * 100;
totalReturn += returnPct;
}
return totalReturn / (data.length - 1);
}
// src/lib/Strategy.ts
var Strategy = class {
name;
data = [];
strategyOptions;
tradeManager;
indicators = /* @__PURE__ */ new Map();
pairDataPath = "";
constructor(strategyOptions) {
const {
name,
dataLength = 100,
timeFrame = "1m" /* MINUTE */,
chartType = new CandleSticks(),
indicators = [],
simulationOptions,
pair
} = strategyOptions;
this.name = strategyOptions.name;
this.strategyOptions = {
name,
dataLength,
timeFrame,
chartType,
indicators,
simulationOptions: simulationOptions ?? { pair },
pair
};
this.tradeManager = new TradeManager(this);
}
async loadData() {
const { pair, timeFrame, dataLength } = this.strategyOptions;
const dataFolderPath = import_path2.default.join(process.cwd(), "data");
if (!import_fs2.default.existsSync(dataFolderPath)) {
import_fs2.default.mkdirSync(dataFolderPath);
}
const { path: pairDataPath, data } = await downloadPairData(
pair,
timeFrame,
dataLength,
dataFolderPath
);
this.pairDataPath = pairDataPath;
this.data = data;
}
provideAllIndicators() {
this.strategyOptions.indicators.forEach(
(indicator) => indicator.provide(this.data)
);
}
feedAllIndicators(data) {
this.strategyOptions.indicators.forEach((indicator) => indicator.feed(data));
}
async backtest({}) {
const results = {
alpha: 0,
beta: 0,
maxDrawdown: 0,
maxProfit: 0,
percentageProfitable: 0,
return: 0,
profitFactor: 0,
sharpeE: 0,
tradeCount: 0,
reportData: {
data: [],
trades: []
}
};
await Promise.all([this.internalStart(), this.onStart(this.data)]);
for (const update of this.data) {
await Promise.all([
this.internalUpdate(update, this.data),
this.onUpdate(update, this.data)
]);
}
const tradeHistory = this.tradeManager.getTradeHistory();
results.tradeCount = tradeHistory.length;
results.reportData.trades = tradeHistory;
if (tradeHistory.length === 0) {
return results;
}
const returns = tradeHistory.map((trade) => {
const { ["PL" /* PL */]: pl = 0, ["leverage" /* leverage */]: leverage = 1 } = trade.getData();
return pl * leverage;
});
const totalPL = returns.reduce((sum, r) => sum + r, 0);
const profitableTrades = returns.filter((r) => r > 0);
const lossTrades = returns.filter((r) => r < 0);
results.return = totalPL;
results.percentageProfitable = profitableTrades.length / returns.length * 100;
results.maxDrawdown = Math.min(...returns);
results.maxProfit = Math.max(...returns);
const grossProfit = profitableTrades.reduce((sum, r) => sum + r, 0);
const grossLoss = Math.abs(lossTrades.reduce((sum, r) => sum + r, 0));
results.profitFactor = grossLoss !== 0 ? grossProfit / grossLoss : grossProfit;
const averageReturn = totalPL / returns.length;
const riskFreeRate = 0;
const marketReturn = await getAvgMarketReturn(
this.strategyOptions.pair,
"1M" /* MONTH */,
60
// 5 years * 12 months
);
const covariance = calcCovariance(returns, marketReturn) || 0;
const variance = calcVariance(returns) || 0;
const standardDeviation = calcStddev(returns);
results.beta = calcBeta(covariance, variance);
results.alpha = calcAlpha(
averageReturn,
riskFreeRate,
results.beta,
marketReturn
);
results.sharpeE = calcSharpeE(
averageReturn,
results.return,
riskFreeRate,
standardDeviation
);
results.reportData.data.push({
name: `${this.strategyOptions.pair.replaceAll("/", "_")}_${this.strategyOptions.timeFrame}`,
type: "price" /* PRICE */,
data: this.data
});
this.indicators.forEach((indicatorData, indicatorKey) => {
results.reportData.data.push({
name: indicatorKey,
type: "factor" /* FACTOR */,
data: indicatorData
});
});
return results;
}
internalStart() {
this.strategyOptions.indicators.forEach((indicator) => {
indicator.clear();
});
}
async internalUpdate(update, updates) {
this.feedAllIndicators(update);
await Promise.all(
this.strategyOptions.indicators.map(async (indicator) => {
this.indicators.set(indicator.key, await indicator.generate());
})
);
this.tradeManager.onUpdate(update, updates);
}
live() {
}
onStart(updates) {
}
onUpdate(update, updates) {
}
};
// src/managers/Report/ReportManager.ts
var import_express = __toESM(require("express"), 1);
var import_path3 = __toESM(require("path"), 1);
var import_meta = {};
var ReportManager = class {
app = (0, import_express.default)();
PORT = 2555;
viewsPath;
constructor() {
this.viewsPath = new URL("./", import_meta.url).pathname;
this.initializeApp();
}
initializeApp() {
this.app.use(import_express.default.json());
this.app.set("views", this.viewsPath);
this.app.use(import_express.default.static(this.viewsPath));
this.app.listen(this.PORT, () => {
console.log(`Report server listening on port ${this.PORT}`);
});
}
generateReport(strategy, reportData) {
const reportId = generateMD5Id();
const { trades, data } = reportData;
const reportRouter = import_express.default.Router();
const priceData = data.filter((e) => e.type === "price" /* PRICE */);
const factorData = data.filter((e) => e.type === "factor" /* FACTOR */);
reportRouter.get("/price-data", (_, res) => {
res.json(priceData);
});
reportRouter.get("/factor-data", (_, res) => {
res.json(factorData);
});
reportRouter.get("/trade-data", (_, res) => {
res.json(trades);
});
reportRouter.get("/", (_, res) => {
const buildPath = import_path3.default.join(this.viewsPath, "performance/dist/index.html").replace("\\C", "C");
res.sendFile(buildPath);
});
this.app.use(`/${reportId}`, reportRouter);
console.log(
`Report for ${strategy.name}: http://localhost:${this.PORT}/${reportId}`
);
}
};
// src/indicators/index.ts
var indicators_exports = {};
__export(indicators_exports, {
ADX: () => ADX,
ATR: () => ATR,
BB: () => BB,
EMA: () => EMA,
ForceIndex: () => ForceIndex,
IchimokuCloud: () => IchimokuCloud,
MACD: () => MACD,
RSI: () => RSI,
SMA: () => SMA,
StockRSI: () => StockRSI,
VWAP: () => VWAP,
VolumeProfile: () => VolumeProfile,
WEMA: () => WEMA
});
// src/indicators/EMA.ts
var import_technicalindicators3 = __toESM(require("technicalindicators"), 1);
var EMA = class extends Indicator {
period = 9;
constructor(key, options) {
super({
name: "EMA",
key,
description: "Exponential Moving Average."
});
if (options.period) this.period = options.period;
}
generate() {
const values = this.data.map((update) => update[4]).filter((value) => value !== void 0);
const ema = import_technicalindicators3.default.EMA.calculate({
period: this.period,
values
});
return ema;
}
};
// src/indicators/SMA.ts
var import_technicalindicators4 = __toESM(require("technicalindicators"), 1);
var SMA = class extends Indicator {
period = 9;
constructor(key, options) {
super({
name: "SMA",
key,
description: "Simple Moving Average."
});
if (options.period) this.period = options.period;
}
generate() {
const values = this.data.map((update) => update[4]).filter((value) => value !== void 0);
const sma = import_technicalindicators4.default.SMA.calculate({
period: this.period,
values
});
return sma;
}
};
// src/indicators/ATR.ts
var import_technicalindicators5 = __toESM(require("technicalindicators"), 1);
var ATR = class extends Indicator {
period = 14;
constructor(key, options) {
super({
name: "ATR",
key,
description: "Average True Range."
});
if (options.period) this.period = options.period;
}
generate() {
const { highs, lows, closes } = parseIntoRows(this.data);
const atr = import_technicalindicators5.default.ATR.calculate({
period: this.period,
high: highs,
low: lows,
close: closes
});
return atr;
}
};
// src/indicators/RSI.ts
var import_technicalindicators6 = __toESM(require("technicalindicators"), 1);
var RSI = class extends Indicator {
period = 14;
constructor(key, options) {
super({
name: "RSI",
key,
description: "Relative Strength Index."
});
if (options.period) this.period = options.period;
}
generate() {
const values = this.data.map((update) => update[4]).filter((value) => value !== void 0);
const rsi = import_technicalindicators6.default.RSI.calculate({
period: this.period,
values
});
return rsi;
}
};
// src/indicators/MACD.ts
var import_technicalindicators7 = __toESM(require("technicalindicators"), 1);
var MACD = class extends Indicator {
fastPeriod = 12;
slowPeriod = 26;
signalSmoothing = 9;
MAType = "SMA";
MAOscillatorType = "SMA";
constructor(key, options) {
super({
name: "MACD",
key,
description: "Moving Average Convergence/Divergence."
});
if (options.fastPeriod) this.fastPeriod = options.fastPeriod;
if (options.slowPeriod) this.slowPeriod = options.slowPeriod;
if (options.signalSmoothing) this.signalSmoothing = options.signalSmoothing;
if (options.MAOscillatorType)
this.MAOscillatorType = options.MAOscillatorType;
if (options.MAType) this.MAType = options.MAType;
}
generate() {
const values = this.data.map((update) => update[4]).filter((value) => value !== void 0);
const macd = import_technicalindicators7.default.MACD.calculate({
fastPeriod: this.fastPeriod,
slowPeriod: this.slowPeriod,
SimpleMAOscillator: this.MAOscillatorType === "SMA" ? true : false,
SimpleMASignal: this.MAType === "SMA" ? true : false,
signalPeriod: this.signalSmoothing,
values
});
return macd;
}
};
// src/indicators/StochRSI.ts
var import_technicalindicators8 = __toESM(require("technicalindicators"), 1);
var StockRSI = class extends Indicator {
dPeriod = 9;
kPeriod = 12;
rsiPeriod = 14;
stochasticPeriod = 16;
constructor(key, options) {
super({
name: "Bollinger Bands",
key,
description: "Boillinger Bands."
});
if (options.dPeriod) this.dPeriod = options.dPeriod;
if (options.kPeriod) this.kPeriod = options.kPeriod;
if (options.rsiPeriod) this.rsiPeriod = options.rsiPeriod;
if (options.stochasticPeriod)
this.stochasticPeriod = options.stochasticPeriod;
}
generate() {
const values = this.data.map((update) => update[4]).filter((value) => value !== void 0);
const stochRSI = import_technicalindicators8.default.StochasticRSI.calculate({
values,
dPeriod: this.dPeriod,
kPeriod: this.kPeriod,
rsiPeriod: this.rsiPeriod,
stochasticPeriod: this.stochasticPeriod
});
return stochRSI;
}
};
// src/indicators/BB.ts
var import_technicalindicators9 = __toESM(require("technicalindicators"), 1);
var BB = class extends Indicator {
period = 9;
stdDev = 1;
constructor(key, options) {
super({
name: "Bollinger Bands",
key,
description: "Boillinger Bands."
});
if (options.period) this.period = options.period;
if (options.stdDev) this.stdDev = options.stdDev;
}
generate() {
const values = this.data.map((update) => update[4]).filter((value) => value !== void 0);
const bb = import_technicalindicators9.default.BollingerBands.calculate({
values,
period: this.period,
stdDev: this.stdDev
});
return bb;
}
};
// src/indicators/IchimokuCloud.ts
var import_technicalindicators10 = __toESM(require("technicalindicators"), 1);
var IchimokuCloud = class extends Indicator {
basePeriod = 9;
conversionPeriod = 12;
spanPeriod = 16;
displacement = 21;
constructor(key, options) {
super({
name: "Ichimoku Cloud",
key,
description: "Ichimoku Cloud."
});
if (options.basePeriod) this.basePeriod = options.basePeriod;
if (options.conversionPeriod)
this.conversionPeriod = options.conversionPeriod;
if (options.spanPeriod) this.spanPeriod = options.spanPeriod;
if (options.displacement) this.displacement = options.displacement;
}
generate() {
const { highs, lows } = parseIntoRows(this.data);
const ichimoku = import_technicalindicators10.default.IchimokuCloud.calculate({
basePeriod: this.basePeriod,
conversionPeriod: this.conversionPeriod,
spanPeriod: this.spanPeriod,
displacement: this.displacement,
high: highs,
low: lows
});
return ichimoku;
}
};
// src/indicators/WEMA.ts
var import_technicalindicators11 = __toESM(require("technicalindicators"), 1);
var WEMA = class extends Indicator {
period = 9;
constructor(key, options) {
super({
name: "Weighted Exponential Moving Average",
key,
description: "Weighted Exponential Moving Average."
});
if (options.period) this.period = options.period;
}
generate() {
const values = this.data.map((update) => update[4]).filter((value) => value !== void 0);
const wema = import_technicalindicators11.default.WEMA.calculate({
period: this.period,
values
});
return wema;
}
};
// src/indicators/ADX.ts
var import_technicalindicators12 = __toESM(require("technicalindicators"), 1);
var ADX = class extends Indicator {
period = 9;
constructor(key, options) {
super({
name: "ADX",
key,
description: "Trend Strength."
});
if (options.period) this.period = options.period;
}
generate() {
const { closes, highs, lows } = parseIntoRows(this.data);
const adx = import_technicalindicators12.default.ADX.calculate({
period: this.period,
close: closes,
high: highs,
low: lows
});
return adx;
}
};
// src/indicators/VolumeProfile.ts
var import_technicalindicators13 = __toESM(require("technicalindicators"), 1);
var VolumeProfile = class extends Indicator {
numberOfBars = 20;
constructor(key, options) {
super({
name: "Volume Profile",
key,
description: "Volume Profile."
});
if (options.numberOfBars) this.numberOfBars = options.numberOfBars;
}
generate() {
const { closes, highs, lows, opens, volumes } = parseIntoRows(this.data);
const volumeProfile = import_technicalindicators13.default.VolumeProfile.calculate({
close: closes,
high: highs,
low: lows,
open: opens,
volume: volumes,
noOfBars: this.numberOfBars
});
return volumeProfile;
}
};
// src/indicators/VWAP.ts
var import_technicalindicators14 = __toESM(require("technicalindicators"), 1);
var VWAP = class extends Indicator {
constructor(key) {
super({
name: "VWAP",
key,
description: "Volume-weighted Average Price."
});
}
generate() {
const { closes, highs, lows, opens, timestamps, volumes } = parseIntoRows(
this.data
);
const vwap = import_technicalindicators14.default.VWAP.calculate({
close: closes,
high: highs,
low: lows,
volume: volumes
});
return vwap;
}
};
// src/indicators/ForceIndex.ts
var import_technicalindicators15 = __toESM(require("technicalindicators"), 1);
var ForceIndex = class extends Indicator {
period = 9;
constructor(key, options) {
super({
name: "ForceIndex",
key,
description: "Force Index."
});
if (options.period) this.period = options.period;
}
generate() {
const { closes, volumes } = parseIntoRows(this.data);
const forceIndex = import_technicalindicators15.default.ForceIndex.calculate({
period: this.period,
close: closes,
volume: volumes
});
return forceIndex;
}
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
ChartingSystem,
CryptoPair,
DataSourceType,
Indicator,
Indicators,
Logger,
NumberReturnType,
OrderType,
PositionType,
ReportManager,
Strategy,
TRADE_KEY,
TimeFrame,
TimelineEvents,
Trade,
TradeManager,
logger
});
//# sourceMappingURL=index.cjs.map