@backtest-kit/graph 6.10.0 → 6.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -8
- package/build/index.cjs +3 -2
- package/build/index.mjs +4 -3
- package/package.json +4 -4
- package/types.d.ts +4 -4
package/README.md
CHANGED
|
@@ -99,7 +99,7 @@ npm install @backtest-kit/graph backtest-kit
|
|
|
99
99
|
- 🔒 **Type-safe values**: TypeScript infers the return type of every node through the graph via generics
|
|
100
100
|
- 🧱 **Two APIs**: Low-level `INode` for runtime/storage, high-level `TypedNode` + builders for authoring
|
|
101
101
|
- 💾 **DB-ready serialization**: `serialize` / `deserialize` convert the graph to a flat `IFlatNode[]` list with `id` / `nodeIds`
|
|
102
|
-
- 🔌 **Context-aware fetch**: `SourceNode.fetch` receives `(symbol, when, exchangeName)` from the execution context automatically
|
|
102
|
+
- 🔌 **Context-aware fetch**: `SourceNode.fetch` receives `(symbol, when, currentPrice, exchangeName)` from the execution context automatically
|
|
103
103
|
|
|
104
104
|
## 📖 Usage
|
|
105
105
|
|
|
@@ -110,14 +110,14 @@ Use `sourceNode` and `outputNode` to define a typed computation graph. TypeScrip
|
|
|
110
110
|
```typescript
|
|
111
111
|
import { sourceNode, outputNode, resolve } from '@backtest-kit/graph';
|
|
112
112
|
|
|
113
|
-
// SourceNode<number> — fetch receives symbol, when, exchangeName from context
|
|
114
|
-
const closePrice = sourceNode(async (symbol, when, exchangeName) => {
|
|
113
|
+
// SourceNode<number> — fetch receives symbol, when, currentPrice, exchangeName from context
|
|
114
|
+
const closePrice = sourceNode(async (symbol, when, currentPrice, exchangeName) => {
|
|
115
115
|
const candles = await getCandles(symbol, '1h', 1, exchangeName);
|
|
116
116
|
return candles[0].close; // number
|
|
117
117
|
});
|
|
118
118
|
|
|
119
119
|
// SourceNode<number>
|
|
120
|
-
const volume = sourceNode(async (symbol, when, exchangeName) => {
|
|
120
|
+
const volume = sourceNode(async (symbol, when, currentPrice, exchangeName) => {
|
|
121
121
|
const candles = await getCandles(symbol, '1h', 1, exchangeName);
|
|
122
122
|
return candles[0].volume; // number
|
|
123
123
|
});
|
|
@@ -147,14 +147,14 @@ const signal: TypedNode = {
|
|
|
147
147
|
nodes: [
|
|
148
148
|
{
|
|
149
149
|
type: NodeType.SourceNode,
|
|
150
|
-
fetch: async (symbol, when, exchangeName) => {
|
|
150
|
+
fetch: async (symbol, when, currentPrice, exchangeName) => {
|
|
151
151
|
const plots = await run(File.fromPath('timeframe_4h.pine'), { symbol, timeframe: '4h', limit: 100 });
|
|
152
152
|
return extract(plots, { allowLong: 'AllowLong', allowShort: 'AllowShort', noTrades: 'NoTrades' });
|
|
153
153
|
},
|
|
154
154
|
},
|
|
155
155
|
{
|
|
156
156
|
type: NodeType.SourceNode,
|
|
157
|
-
fetch: async (symbol, when, exchangeName) => {
|
|
157
|
+
fetch: async (symbol, when, currentPrice, exchangeName) => {
|
|
158
158
|
const plots = await run(File.fromPath('timeframe_15m.pine'), { symbol, timeframe: '15m', limit: 100 });
|
|
159
159
|
return extract(plots, { position: 'Signal', priceOpen: 'Close', priceTakeProfit: 'TakeProfit', priceStopLoss: 'StopLoss' });
|
|
160
160
|
},
|
|
@@ -195,7 +195,7 @@ const result = outputNode(
|
|
|
195
195
|
import { addStrategy } from 'backtest-kit';
|
|
196
196
|
import { sourceNode, outputNode, resolve } from '@backtest-kit/graph';
|
|
197
197
|
|
|
198
|
-
const rsi = sourceNode(async (symbol, when, exchangeName) => {
|
|
198
|
+
const rsi = sourceNode(async (symbol, when, currentPrice, exchangeName) => {
|
|
199
199
|
// ... compute RSI
|
|
200
200
|
return 55.2;
|
|
201
201
|
});
|
|
@@ -229,7 +229,7 @@ import NodeType from '@backtest-kit/graph/enum/NodeType';
|
|
|
229
229
|
const priceNode: INode = {
|
|
230
230
|
type: NodeType.SourceNode,
|
|
231
231
|
description: 'Close price',
|
|
232
|
-
fetch: async (symbol, when, exchangeName) => 42,
|
|
232
|
+
fetch: async (symbol, when, currentPrice, exchangeName) => 42,
|
|
233
233
|
};
|
|
234
234
|
|
|
235
235
|
const outputNode: INode = {
|
package/build/index.cjs
CHANGED
|
@@ -50,10 +50,11 @@ async function resolve(node) {
|
|
|
50
50
|
if (node.type === NodeType$1.SourceNode) {
|
|
51
51
|
const { symbol, when } = backtestKit.lib.executionContextService.context;
|
|
52
52
|
const { exchangeName } = backtestKit.lib.methodContextService.context;
|
|
53
|
-
|
|
53
|
+
const currentPrice = await backtestKit.getAveragePrice(symbol);
|
|
54
|
+
return await node.fetch(symbol, when, currentPrice, exchangeName);
|
|
54
55
|
}
|
|
55
56
|
const values = await Promise.all(node.nodes.map(resolve));
|
|
56
|
-
return node.compute(values);
|
|
57
|
+
return await node.compute(values);
|
|
57
58
|
}
|
|
58
59
|
|
|
59
60
|
/**
|
package/build/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ExecutionContextService, MethodContextService, lib } from 'backtest-kit';
|
|
1
|
+
import { ExecutionContextService, MethodContextService, lib, getAveragePrice } from 'backtest-kit';
|
|
2
2
|
import { randomString } from 'functools-kit';
|
|
3
3
|
|
|
4
4
|
var NodeType;
|
|
@@ -48,10 +48,11 @@ async function resolve(node) {
|
|
|
48
48
|
if (node.type === NodeType$1.SourceNode) {
|
|
49
49
|
const { symbol, when } = lib.executionContextService.context;
|
|
50
50
|
const { exchangeName } = lib.methodContextService.context;
|
|
51
|
-
|
|
51
|
+
const currentPrice = await getAveragePrice(symbol);
|
|
52
|
+
return await node.fetch(symbol, when, currentPrice, exchangeName);
|
|
52
53
|
}
|
|
53
54
|
const values = await Promise.all(node.nodes.map(resolve));
|
|
54
|
-
return node.compute(values);
|
|
55
|
+
return await node.compute(values);
|
|
55
56
|
}
|
|
56
57
|
|
|
57
58
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backtest-kit/graph",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.12.0",
|
|
4
4
|
"description": "Compose backtest-kit computations as a typed directed acyclic graph. Define source nodes that fetch market data and output nodes that compute derived values — then resolve the whole graph in topological order.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Petr Tripolsky",
|
|
@@ -67,17 +67,17 @@
|
|
|
67
67
|
"ts-morph": "27.0.2",
|
|
68
68
|
"tslib": "2.7.0",
|
|
69
69
|
"typedoc": "0.27.9",
|
|
70
|
-
"backtest-kit": "6.
|
|
70
|
+
"backtest-kit": "6.12.0",
|
|
71
71
|
"worker-testbed": "2.0.0"
|
|
72
72
|
},
|
|
73
73
|
"peerDependencies": {
|
|
74
|
-
"backtest-kit": "^6.
|
|
74
|
+
"backtest-kit": "^6.12.0",
|
|
75
75
|
"typescript": "^5.0.0"
|
|
76
76
|
},
|
|
77
77
|
"dependencies": {
|
|
78
78
|
"di-kit": "^1.1.1",
|
|
79
79
|
"di-scoped": "^1.0.21",
|
|
80
|
-
"functools-kit": "^2.0.
|
|
80
|
+
"functools-kit": "^2.0.2",
|
|
81
81
|
"get-moment-stamp": "^1.1.2"
|
|
82
82
|
},
|
|
83
83
|
"publishConfig": {
|
package/types.d.ts
CHANGED
|
@@ -27,7 +27,7 @@ interface INode {
|
|
|
27
27
|
* Источник данных для SourceNode.
|
|
28
28
|
* Вызывается при вычислении узла без входящих зависимостей.
|
|
29
29
|
*/
|
|
30
|
-
fetch?: (symbol: string, when: Date, exchangeName: ExchangeName) => Promise<Value> | Value;
|
|
30
|
+
fetch?: (symbol: string, when: Date, currentPrice: number, exchangeName: ExchangeName) => Promise<Value> | Value;
|
|
31
31
|
/**
|
|
32
32
|
* Функция вычисления для OutputNode.
|
|
33
33
|
* Получает на вход массив значений, возвращённых fetch/compute
|
|
@@ -60,7 +60,7 @@ type InferNodeValue<T extends TypedNode> = T extends SourceNode<infer V> ? V : T
|
|
|
60
60
|
type SourceNode<T extends Value = Value> = {
|
|
61
61
|
type: NodeType.SourceNode;
|
|
62
62
|
description?: string;
|
|
63
|
-
fetch: (symbol: string, when: Date, exchangeName: ExchangeName) => Promise<T> | T;
|
|
63
|
+
fetch: (symbol: string, when: Date, currentPrice: number, exchangeName: ExchangeName) => Promise<T> | T;
|
|
64
64
|
};
|
|
65
65
|
/**
|
|
66
66
|
* Узел вычисления. TNodes — tuple входящих зависимостей,
|
|
@@ -79,7 +79,7 @@ type OutputNode<TNodes extends TypedNode[] = TypedNode[], TResult extends Value
|
|
|
79
79
|
*/
|
|
80
80
|
type TypedNode = SourceNode<Value> | OutputNode<TypedNode[], Value>;
|
|
81
81
|
|
|
82
|
-
declare const sourceNode: <T extends Value>(fetch: (symbol: string, when: Date, exchangeName: ExchangeName) => Promise<T> | T) => SourceNode<T>;
|
|
82
|
+
declare const sourceNode: <T extends Value>(fetch: (symbol: string, when: Date, currentPrice: number, exchangeName: ExchangeName) => Promise<T> | T) => SourceNode<T>;
|
|
83
83
|
declare const outputNode: <TNodes extends TypedNode[], TResult extends Value = Value>(compute: (values: InferValues<TNodes>) => Promise<TResult> | TResult, ...nodes: TNodes) => OutputNode<TNodes, TResult>;
|
|
84
84
|
|
|
85
85
|
/**
|
|
@@ -124,7 +124,7 @@ interface IFlatNode {
|
|
|
124
124
|
* Источник данных для SourceNode — не сериализуется в БД,
|
|
125
125
|
* восстанавливается на стороне приложения.
|
|
126
126
|
*/
|
|
127
|
-
fetch?: (symbol: string, when: Date, exchangeName: ExchangeName) => Promise<Value> | Value;
|
|
127
|
+
fetch?: (symbol: string, when: Date, currentPrice: number, exchangeName: ExchangeName) => Promise<Value> | Value;
|
|
128
128
|
/**
|
|
129
129
|
* Функция вычисления для OutputNode — не сериализуется в БД,
|
|
130
130
|
* восстанавливается на стороне приложения.
|