backtest-kit 1.0.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/LICENSE +21 -0
- package/README.md +269 -0
- package/build/index.cjs +584 -0
- package/build/index.mjs +573 -0
- package/package.json +86 -0
- package/types.d.ts +213 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Petr Tripolsky
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
# Backtest Kit
|
|
2
|
+
|
|
3
|
+
A powerful TypeScript framework for backtesting trading strategies with clean architecture and real-time execution capabilities.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- π **Clean Architecture** - Separation of concerns with DI container
|
|
8
|
+
- π **Strategy Backtesting** - Test your trading strategies on historical data
|
|
9
|
+
- π **Real-time Execution** - Run strategies live with configurable intervals
|
|
10
|
+
- π **VWAP Pricing** - Volume-weighted average price calculation
|
|
11
|
+
- π― **Signal Management** - Automatic signal lifecycle (open/close) with TP/SL
|
|
12
|
+
- π **PNL Calculation** - Accurate profit/loss with fees and slippage
|
|
13
|
+
- π **Beautiful Reports** - Markdown tables with statistics
|
|
14
|
+
- π **Flexible Schema** - Plug your own data sources
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Quick Start
|
|
23
|
+
|
|
24
|
+
### 1. Add Data Source (Candles)
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
import { addCandle } from "./src/function/add";
|
|
28
|
+
|
|
29
|
+
addCandle({
|
|
30
|
+
getCandles: async (symbol, interval, since, limit) => {
|
|
31
|
+
// Fetch candle data from your source (exchange API, database, etc.)
|
|
32
|
+
return [
|
|
33
|
+
{
|
|
34
|
+
timestamp: Date.now(),
|
|
35
|
+
open: 50000,
|
|
36
|
+
high: 51000,
|
|
37
|
+
low: 49000,
|
|
38
|
+
close: 50500,
|
|
39
|
+
volume: 1000,
|
|
40
|
+
},
|
|
41
|
+
];
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### 2. Add Strategy
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
import { addStrategy } from "./src/function/add";
|
|
50
|
+
|
|
51
|
+
addStrategy({
|
|
52
|
+
getSignal: async (symbol) => {
|
|
53
|
+
// Your signal generation logic
|
|
54
|
+
return {
|
|
55
|
+
id: "signal-1",
|
|
56
|
+
position: "long",
|
|
57
|
+
note: "BTC breakout",
|
|
58
|
+
priceOpen: 50000,
|
|
59
|
+
priceTakeProfit: 51000,
|
|
60
|
+
priceStopLoss: 49000,
|
|
61
|
+
minuteEstimatedTime: 60,
|
|
62
|
+
timestamp: Date.now(),
|
|
63
|
+
};
|
|
64
|
+
},
|
|
65
|
+
callbacks: {
|
|
66
|
+
onOpen: (backtest, symbol, data) => {
|
|
67
|
+
console.log("Signal opened:", data);
|
|
68
|
+
},
|
|
69
|
+
onClose: (backtest, symbol, priceClose, data) => {
|
|
70
|
+
console.log("Signal closed at:", priceClose);
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### 3. Run Backtest
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
import { runBacktest, runBacktestGUI } from "./src/function/backtest";
|
|
80
|
+
|
|
81
|
+
// Generate timeframes (every minute for 24 hours)
|
|
82
|
+
const timeframes = Array.from({ length: 1440 }, (_, i) => {
|
|
83
|
+
const date = new Date("2024-01-01T00:00:00Z");
|
|
84
|
+
date.setMinutes(date.getMinutes() + i);
|
|
85
|
+
return date;
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// Simple backtest (returns data only)
|
|
89
|
+
const result = await runBacktest("BTCUSDT", timeframes);
|
|
90
|
+
console.log(result.results); // Array of closed trades with PNL
|
|
91
|
+
|
|
92
|
+
// Backtest with terminal output
|
|
93
|
+
runBacktestGUI("BTCUSDT", timeframes);
|
|
94
|
+
// Prints beautiful ASCII table to console
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**Terminal Output:**
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
βββββ¬βββββββββββββββββββββββββββ¬βββββββββββββ¬ββββββββββββ¬βββββββββββββ¬βββββββββββ
|
|
101
|
+
β # β Time β Note β Price β Reason β PNL % β
|
|
102
|
+
βββββΌβββββββββββββββββββββββββββΌβββββββββββββΌββββββββββββΌβββββββββββββΌβββββββββββ€
|
|
103
|
+
β 1 β 2024-01-01T00:05:00.000Z β BTC Long β 51000.00 β take_profitβ π’ +1.98%β
|
|
104
|
+
β 2 β 2024-01-01T01:30:00.000Z β BTC Short β 50800.00 β stop_loss β π΄ -0.42%β
|
|
105
|
+
βββββΌβββββββββββββββββββββββββββΌβββββββββββββΌββββββββββββΌβββββββββββββΌβββββββββββ€
|
|
106
|
+
β β β β β β β
|
|
107
|
+
βββββΌβββββββββββββββββββββββββββΌβββββββββββββΌββββββββββββΌβββββββββββββΌβββββββββββ€
|
|
108
|
+
βTOTALβ 2 trades β Win: 1 β Loss: 1 β - β +1.56% β
|
|
109
|
+
βββββ΄βββββββββββββββββββββββββββ΄βββββββββββββ΄ββββββββββββ΄βββββββββββββ΄βββββββββββ
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### 4. Real-time Execution
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
import { startRun, stopRun, stopAll } from "./src/function/run";
|
|
116
|
+
|
|
117
|
+
// Start strategy for multiple symbols
|
|
118
|
+
startRun({ symbol: "BTCUSDT", interval: 5 * 60 * 1000 }); // 5 minutes
|
|
119
|
+
startRun({ symbol: "ETHUSDT", interval: 5 * 60 * 1000 });
|
|
120
|
+
|
|
121
|
+
// Stop specific symbol
|
|
122
|
+
stopRun("BTCUSDT");
|
|
123
|
+
|
|
124
|
+
// Stop all
|
|
125
|
+
stopAll();
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### 5. Advanced: Reduce Pattern
|
|
129
|
+
|
|
130
|
+
Use the reduce pattern to iterate timeframes with custom logic:
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
import { reduce } from "./src/function/reduce";
|
|
134
|
+
|
|
135
|
+
interface Context {
|
|
136
|
+
count: number;
|
|
137
|
+
timestamps: Date[];
|
|
138
|
+
apiCalls: number;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const result = await reduce<Context>(
|
|
142
|
+
"BTCUSDT",
|
|
143
|
+
timeframes,
|
|
144
|
+
async (acc, index, when, symbol) => {
|
|
145
|
+
acc.count++;
|
|
146
|
+
acc.timestamps.push(when);
|
|
147
|
+
|
|
148
|
+
// Make your custom API calls, LLM requests, etc.
|
|
149
|
+
const response = await fetch(`/api/analyze?symbol=${symbol}&when=${when}`);
|
|
150
|
+
acc.apiCalls++;
|
|
151
|
+
|
|
152
|
+
return acc;
|
|
153
|
+
},
|
|
154
|
+
{ count: 0, timestamps: [], apiCalls: 0 }
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
// Use accumulated data
|
|
158
|
+
console.log(result.accumulator);
|
|
159
|
+
// { count: 1440, timestamps: [...], apiCalls: 1440 }
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Architecture
|
|
163
|
+
|
|
164
|
+
```
|
|
165
|
+
src/
|
|
166
|
+
βββ function/ # High-level API functions
|
|
167
|
+
β βββ add.ts # Add schemas (strategy, candle)
|
|
168
|
+
β βββ backtest.ts # Backtesting functions
|
|
169
|
+
β βββ reduce.ts # Reduce pattern for accumulation
|
|
170
|
+
β βββ run.ts # Real-time execution
|
|
171
|
+
βββ client/ # Client implementations
|
|
172
|
+
β βββ ClientCandle.ts # Candle client with VWAP
|
|
173
|
+
β βββ ClientStrategy.ts # Strategy client with signal lifecycle
|
|
174
|
+
βββ interfaces/ # TypeScript interfaces
|
|
175
|
+
β βββ Strategy.interface.ts
|
|
176
|
+
β βββ Candle.interface.ts
|
|
177
|
+
βββ lib/ # Core library with DI
|
|
178
|
+
βββ core/ # Dependency injection
|
|
179
|
+
βββ services/ # Services (schema, connection, public)
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Configuration
|
|
183
|
+
|
|
184
|
+
### Fee and Slippage
|
|
185
|
+
|
|
186
|
+
Configured in `src/interfaces/Strategy.interface.ts`:
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
export const PERCENT_SLIPPAGE = 0.1; // 0.1%
|
|
190
|
+
export const PERCENT_FEE = 0.1; // 0.1%
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Signal Close Reasons
|
|
194
|
+
|
|
195
|
+
- `time_expired` - Signal duration exceeded
|
|
196
|
+
- `take_profit` - Take profit target reached
|
|
197
|
+
- `stop_loss` - Stop loss triggered
|
|
198
|
+
|
|
199
|
+
## API Reference
|
|
200
|
+
|
|
201
|
+
### Functions
|
|
202
|
+
|
|
203
|
+
#### `addCandle(candleSchema: ICandleSchema)`
|
|
204
|
+
Add candle data source.
|
|
205
|
+
|
|
206
|
+
#### `addStrategy(strategySchema: IStrategySchema)`
|
|
207
|
+
Add trading strategy.
|
|
208
|
+
|
|
209
|
+
#### `runBacktest(symbol: string, timeframes: Date[]): Promise<IBacktestResult>`
|
|
210
|
+
Run backtest and return closed trades only.
|
|
211
|
+
|
|
212
|
+
#### `runBacktestGUI(symbol: string, timeframes: Date[]): void`
|
|
213
|
+
Run backtest and print beautiful ASCII table to terminal.
|
|
214
|
+
|
|
215
|
+
#### `reduce<T>(symbol, timeframes, callback, initialValue): Promise<IReduceResult<T>>`
|
|
216
|
+
Iterate timeframes with accumulator pattern. Callback receives `(accumulator, index, when, symbol)`.
|
|
217
|
+
|
|
218
|
+
#### `startRun(config: IRunConfig)`
|
|
219
|
+
Start real-time strategy execution.
|
|
220
|
+
|
|
221
|
+
#### `stopRun(symbol: string)`
|
|
222
|
+
Stop specific symbol execution.
|
|
223
|
+
|
|
224
|
+
#### `stopAll()`
|
|
225
|
+
Stop all running strategies.
|
|
226
|
+
|
|
227
|
+
## Types
|
|
228
|
+
|
|
229
|
+
### Signal Data
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
interface ISignalData {
|
|
233
|
+
id: string;
|
|
234
|
+
position: "long" | "short";
|
|
235
|
+
note: string;
|
|
236
|
+
priceOpen: number;
|
|
237
|
+
priceTakeProfit: number;
|
|
238
|
+
priceStopLoss: number;
|
|
239
|
+
minuteEstimatedTime: number;
|
|
240
|
+
timestamp: number;
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Tick Results
|
|
245
|
+
|
|
246
|
+
```typescript
|
|
247
|
+
type IStrategyTickResult =
|
|
248
|
+
| IStrategyTickResultIdle // No active signal
|
|
249
|
+
| IStrategyTickResultOpened // Signal just opened
|
|
250
|
+
| IStrategyTickResultActive // Signal is active
|
|
251
|
+
| IStrategyTickResultClosed; // Signal closed with PNL
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
## Use Cases
|
|
255
|
+
|
|
256
|
+
The reduce pattern is perfect for:
|
|
257
|
+
- **LLM Integration** - Feed historical data to AI models for analysis
|
|
258
|
+
- **Custom Analytics** - Build your own metrics and statistics
|
|
259
|
+
- **API Aggregation** - Collect data from multiple sources over time
|
|
260
|
+
- **Data Processing** - Transform and accumulate timeframe data
|
|
261
|
+
- **Real-time Trading** - Use `startRun` for live strategy execution
|
|
262
|
+
|
|
263
|
+
## License
|
|
264
|
+
|
|
265
|
+
MIT
|
|
266
|
+
|
|
267
|
+
## Contributing
|
|
268
|
+
|
|
269
|
+
Pull requests are welcome. For major changes, please open an issue first.
|