@ backtest-kit/ pitchts (英语)
在自办的节点.js环境中运行 TradingView Pine 脚本 v5/v6 反测试- kit。执行您现有的
.pine具有 1:1 语法兼容性并提取结构化交易信号的指标——没有 TradingView 账户,没有重写.

电源 松树 ——开源的"松花文稿"转录和运行时间.
📚 文档 • 妇女 参考执行情况 • 妇女 松树病历 • 妇女 GitHub 图像
npm install @backtest-kit/pinets pinets backtest-kit
为什么
您的边缘已经作为 TradingView Pine 脚本存在—— 在 JavaScript 中重写它是一种容易出错的繁忙工作, 从原作中漂移出. 此软件包运行 .pine 作为 在 backest- kit 的执行上下文中 : getCandles 输入其外观安全数据,60+指标被构建在(没有手动TA数学)中,同样的脚本具有回溯测试和活性的力量. 你画它 plot() 输出到一个结构化的信号,你完成.
- 📜 松脚本 v5/v6 ——本地贸易维尤语法, 1:1相容.
- 🎯 60+指标 ——SMA,EMA,RSI,MACD,博林格乐队,ATR,Stochastic,ADX,
- 🔌 发动机集成 ——运行于后端测试-kit的时间上下文(无外观-ahead).
- 📁 文件或内入 装入 a
.pine文件或通过代码字符串. - 🗺️ 灵活提取 - 任何地图
plot()键入数据,并进行回放和变换. - ⚡ 缓存执行 ——回忆文件为重复运行读取.
- 🛡️ 类型安全 ——提取出的数据上完全通用.
快开始
松树脚本只需要揭露几块命名地块; getSignal 将其映射到一个 ISignalDto。 。 。 .
战略. pine + 得到 Signal
//@version=5
indicator("EMA cross — 1H, 100 candles")
rsi = ta.rsi(close, 10)
atr = ta.atr(10)
ema_fast = ta.ema(close, 7)
ema_slow = ta.ema(close, 16)
long_cond = ta.crossover(ema_fast, ema_slow) and rsi < 65
short_cond = ta.crossunder(ema_fast, ema_slow) and rsi > 35
plot(close, "Close")
plot(long_cond ? 1 : short_cond ? -1 : 0, "Signal")
plot(long_cond ? close - atr*1.5 : close + atr*1.5, "StopLoss")
plot(long_cond ? close + atr*3 : close - atr*3, "TakeProfit")
plot(60, "EstimatedTime") // minutes
import { File, getSignal } from '@backtest-kit/pinets';
import { addStrategy } from 'backtest-kit';
addStrategy({
strategyName: 'pine-ema-cross', interval: '5m', riskName: 'demo',
getSignal: async (symbol) =>
getSignal(File.fromPath('strategy.pine'), { symbol, timeframe: '1h', limit: 100 }),
});
内置代码不需要文件 :
import { Code, getSignal } from '@backtest-kit/pinets';
const signal = await getSignal(
Code.fromString(`//@version=5\nindicator("RSI")\nrsi=ta.rsi(close,14)\natr=ta.atr(14)\nplot(close,"Close")\nplot(rsi<30?1:rsi>70?-1:0,"Signal")\nplot(close-atr*2,"StopLoss")\nplot(close+atr*3,"TakeProfit")`),
{ symbol: 'BTCUSDT', timeframe: '15m', limit: 100 });
所需地块 getSignal()
| 绘图名称 | 数值 | 含义 |
|---|---|---|
"Signal" | 1 编号 : -1 编号 : 0 | 长 / 短 / 无信号 |
"Close" | close | 入场价格 |
"StopLoss" | 价格 | 停止损失水平 |
"TakeProfit" | 价格 | 盈利水平 |
"EstimatedTime" | 分钟 | 持有时间(可选,默认240) |
自定义地块也很好——使用 run + 键 extract 以图示他们.
自定义提取
run() 返回原始绘图数据; extract() 编号 : extractRows() 将其拉入有可选回放和变换的打字形状.
已提取( ) - 最新条值
import { File, run, extract } from '@backtest-kit/pinets';
const plots = await run(File.fromPath('indicators.pine'), { symbol: 'ETHUSDT', timeframe: '1h', limit: 200 });
const data = await extract(plots, {
rsi: 'RSI', macd: 'MACD', // plot name → number
prevRsi: { plot: 'RSI', barsBack: 1 }, // previous bar
trendStrength: { plot: 'ADX', transform: (v) => v > 25 ? 'strong' : 'weak' },
});
// { rsi: 55.2, macd: 12.5, prevRsi: 52.1, trendStrength: 'strong' }
取出 Rows( ) —— 每条栏, 时间标记
import { File, run, extractRows } from '@backtest-kit/pinets';
const plots = await run(File.fromPath('indicators.pine'), { symbol: 'ETHUSDT', timeframe: '1h', limit: 200 });
const rows = await extractRows(plots, {
rsi: 'RSI', macd: 'MACD',
prevRsi: { plot: 'RSI', barsBack: 1 },
trend: { plot: 'ADX', transform: (v) => v > 25 ? 'strong' : 'weak' },
});
// rows[1] = { timestamp: '2024-01-01T01:00:00.000Z', rsi: 52.1, macd: -1.5, prevRsi: 48.3, trend: 'weak' }
extract() 对 extractRows(): 所有栏目的单个最新对象对数组;缺少值 0 对 null; 无时间戳对 ISO timestamp· ; barsBack 从最后一个酒吧对 从每个酒吧自己的索引。 使用 extract 用于当前栏下的信号生成, extractRows 用于数据集导出/历史分析.
至 SignalDto () —— 将提取的值变成信号
帮手 getSignal 内部使用,用于自定义图(例如通过 @backtest-kit/graph) (中文(简体) ). 地图 position 1编号 :-1编号 :0 → long编号 :short编号 :null,带有TP/SL/估计时间,带有可选的明文 priceOpen数字 :
import { run, extract, toSignalDto } from '@backtest-kit/pinets';
import { randomString } from 'functools-kit';
const plots = await run(File.fromPath('strategy.pine'), { symbol, timeframe: '15m', limit: 100 });
const data = await extract(plots, { position: 'Signal', priceTakeProfit: 'TakeProfit', priceStopLoss: 'StopLoss', minuteEstimatedTime: 'EstimatedTime' });
const signal = toSignalDto(randomString(), data, null); // ISignalDto | null
调试定制( C)
turnPlotData/mark down——检查地块输出
import { File, run, dumpPlotData, toMarkdown } from '@backtest-kit/pinets';
const plots = await run(File.fromPath('strategy.pine'), { symbol: 'BTCUSDT', timeframe: '1h', limit: 100 });
await dumpPlotData('signal-001', plots, 'ema-cross', './dump/ta'); // → markdown files
const md = await toMarkdown(plots); // markdown table as a string
使用 Pine / 使用 Indicator / set Logger —— 互换内部
import { usePine, useIndicator, setLogger } from '@backtest-kit/pinets';
import { Pine } from 'pinets';
usePine(Pine); // register a custom Pine constructor
useIndicator(MyIndicatorCtor); // register a custom indicator constructor
setLogger({ log: (m, d) => console.log(`[${m}]`, d), info: () => {}, error: console.error });
为什么不在JS中重新写?
差别
// ❌ Manual rewrite — re-derive every indicator, drift from the original
const candles = await getCandles('BTCUSDT', '5m', 100);
const closes = candles.map(c => c.close);
const rsi = RSI.calculate({ values: closes, period: 14 });
const emaFast = EMA.calculate({ values: closes, period: 9 });
// …port all the Pine logic by hand
// ✅ With pinets — copy the .pine straight from TradingView
const signal = await getSignal(File.fromPath('strategy.pine'), { symbol: 'BTCUSDT', timeframe: '5m', limit: 100 });
使用已有的脚本 ^ 60+ 指示器, 没有手动数学 ^ 相同的代码回回测试和活 ^ 完整的时间序列回望语义 ^ 类型安全提取 .
API 参考
| 导出 | 说明 |
|---|---|
getSignal(source, opts) | 运行 Pine 脚本 结构 ISignalDto (位置、TP/SL,估计时间) |
run(source, opts) | 运行 Pine 脚本 → 原始地图数据 |
extract(plots, mapping) | 带有自定义映射的最新列值( 丢失 ) 0(中文(简体) ) |
extractRows(plots, mapping) | 所有栏为加时标行(缺) null(中文(简体) ) |
toSignalDto(id, data, priceOpen?) | 已提取地图 { position, … } → ISignalDto | null |
dumpPlotData(id, plots, name, dir) | 向下标记文件丢弃绘图数据 |
toMarkdown(plots) • 妇女 markdown(...) | 将平地图作为平地表 |
File.fromPath(path) | 从 a 装入松脚本 .pine 文件( 记忆) |
Code.fromString(code) | 使用内线松脚本 |
usePine(ctor) • 妇女 useIndicator(ctor) | 注册自定义 Pine / 指标构建器 |
setLogger(logger) | 自定义日志 |
lib | 高级使用的IoC内部容器 |
AXIS_SYMBOL | 轴线提供者符号符号 |
选项 (单位:千美元)run编号 :getSignal: symbol, (中文(简体) ), timeframe (松花烛间隔), limit (要取的手提箱——必须覆盖指标热量;加热前栏是: N/A) (中文(简体) ).
类型 : PlotExtractConfig, (中文(简体) ), PlotMapping, (中文(简体) ), ExtractedData, (中文(简体) ), ExtractedDataRow, (中文(简体) ), CandleModel, (中文(简体) ), PlotModel, (中文(简体) ), PlotRecord, (中文(简体) ), SymbolInfoModel, (中文(简体) ), ILogger, (中文(简体) ), IPine编号 :TPineCtor, (中文(简体) ), IIndicator编号 :TIndicatorCtor, (中文(简体) ), IProvider。 。 。 .
完整源图
classes/{Code,File}.ts • 妇女 function/{pine,indicator,run,extract,setup,strategy,dump,markdown}.function.ts • 妇女 helpers/toSignalDto.ts • 妇女 model/{Candle,Plot,SymbolInfo}.model.ts • 妇女 interface/{Logger,Pine,Indicator,Provider}.interface.ts • 妇女 lib/ 木卫一(core/{di,provide,types}, (中文(简体) ), services/{base/LoggerService, cache/PineCacheService, connection/{Pine,Indicator}ConnectionService, context/ExchangeContextService, data/PineDataService, job/PineJobService, markdown/PineMarkdownService, provider/{Axis,Candle}ProviderService}) (中文(简体) ). 上方的地图导出到其中之一时 src/ 没有证件.
* 贡献
叉/ PR 打开 GitHub 图像。 。 。 .
许可证
麻省理工学院 特立奥尔斯基平板电脑