@backtest-kit/sidekick 0.1.0 → 0.1.2
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/package.json +1 -1
- package/src/classes/{PartialProfitTakingAction.mjs → BacktestPartialProfitTakingAction.mjs} +3 -3
- package/src/classes/BacktestPositionMonitorAction.mjs +53 -0
- package/src/classes/BacktestTightenStopOnBreakevenAction.mjs +13 -0
- package/src/config/params.mjs +1 -0
- package/src/enum/ActionName.mjs +3 -1
- package/src/logic/action/backtest_partial_profit_taking.action.mjs +9 -0
- package/src/logic/action/backtest_position_monitor.action.mjs +9 -0
- package/src/logic/action/backtest_tighten_stop_on_breakeven.action.mjs +9 -0
- package/src/logic/index.mjs +3 -1
- package/src/logic/strategy/main.strategy.mjs +3 -1
- package/src/main/bootstrap.mjs +52 -0
- package/src/utils/getArgs.mjs +15 -23
- package/template/package.mustache +5 -6
- package/src/logic/action/partial_profit_taking.action.mjs +0 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backtest-kit/sidekick",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "The easiest way to create a new Backtest Kit trading bot project. Like create-react-app, but for algorithmic trading with LLM integration and technical analysis.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Petr Tripolsky",
|
|
@@ -3,8 +3,8 @@ import { ActionBase, Constant, commitPartialProfit } from "backtest-kit";
|
|
|
3
3
|
/**
|
|
4
4
|
* Scale out at Kelly-optimized levels
|
|
5
5
|
*/
|
|
6
|
-
export class
|
|
7
|
-
async
|
|
6
|
+
export class BacktestPartialProfitTakingAction extends ActionBase {
|
|
7
|
+
async partialProfitAvailable({ symbol, level }) {
|
|
8
8
|
if (level === Constant.TP_LEVEL3) {
|
|
9
9
|
await commitPartialProfit(symbol, 33);
|
|
10
10
|
}
|
|
@@ -17,4 +17,4 @@ export class PartialProfitTakingAction extends ActionBase {
|
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
export default
|
|
20
|
+
export default BacktestPartialProfitTakingAction;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { ActionBase } from "backtest-kit";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Monitors position lifecycle and logs open/close events in backtest mode
|
|
5
|
+
*/
|
|
6
|
+
export class BacktestPositionMonitorAction extends ActionBase {
|
|
7
|
+
async signalBacktest(event) {
|
|
8
|
+
switch (event.action) {
|
|
9
|
+
case "scheduled":
|
|
10
|
+
console.log(`[POSITION SCHEDULED] ${event.symbol}`);
|
|
11
|
+
console.log(` Strategy: ${event.strategyName}`);
|
|
12
|
+
console.log(` Current Price: ${event.currentPrice}`);
|
|
13
|
+
console.log(` Entry Price: ${event.signal.priceOpen}`);
|
|
14
|
+
console.log(` Signal ID: ${event.signal.id}`);
|
|
15
|
+
console.log(` Direction: ${event.signal.position}`);
|
|
16
|
+
console.log(` Stop Loss: ${event.signal.priceStopLoss}`);
|
|
17
|
+
console.log(` Take Profit: ${event.signal.priceTakeProfit}`);
|
|
18
|
+
break;
|
|
19
|
+
|
|
20
|
+
case "opened":
|
|
21
|
+
console.log(`[POSITION OPENED] ${event.symbol}`);
|
|
22
|
+
console.log(` Strategy: ${event.strategyName}`);
|
|
23
|
+
console.log(` Entry Price: ${event.currentPrice}`);
|
|
24
|
+
console.log(` Signal ID: ${event.signal.id}`);
|
|
25
|
+
console.log(` Direction: ${event.signal.position}`);
|
|
26
|
+
console.log(` Stop Loss: ${event.signal.priceStopLoss}`);
|
|
27
|
+
console.log(` Take Profit: ${event.signal.priceTakeProfit}`);
|
|
28
|
+
break;
|
|
29
|
+
|
|
30
|
+
case "closed":
|
|
31
|
+
console.log(`[POSITION CLOSED] ${event.symbol}`);
|
|
32
|
+
console.log(` Strategy: ${event.strategyName}`);
|
|
33
|
+
console.log(` Entry Price (adj): ${event.pnl.priceOpen}`);
|
|
34
|
+
console.log(` Exit Price (adj): ${event.pnl.priceClose}`);
|
|
35
|
+
console.log(` Signal ID: ${event.signal.id}`);
|
|
36
|
+
console.log(` Close Reason: ${event.closeReason}`);
|
|
37
|
+
console.log(` PnL: ${event.pnl.pnlPercentage.toFixed(2)}%`);
|
|
38
|
+
console.log(` Win: ${event.pnl.pnlPercentage > 0 ? "YES" : "NO"}`);
|
|
39
|
+
break;
|
|
40
|
+
|
|
41
|
+
case "cancelled":
|
|
42
|
+
console.log(`[POSITION CANCELLED] ${event.symbol}`);
|
|
43
|
+
console.log(` Strategy: ${event.strategyName}`);
|
|
44
|
+
console.log(` Signal ID: ${event.signal.id}`);
|
|
45
|
+
console.log(` Current Price: ${event.currentPrice}`);
|
|
46
|
+
console.log(` Cancel Reason: ${event.reason}`);
|
|
47
|
+
console.log(` Cancelled At: ${new Date(event.closeTimestamp).toISOString()}`);
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export default BacktestPositionMonitorAction;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ActionBase, commitTrailingStop } from "backtest-kit";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Tightens trailing-stop by 3% when breakeven is reached
|
|
5
|
+
*/
|
|
6
|
+
export class BacktestTightenStopOnBreakevenAction extends ActionBase {
|
|
7
|
+
async breakevenAvailable({ symbol, currentPrice }) {
|
|
8
|
+
// Tighten trailing-stop by 3% (negative value brings stop-loss closer to entry)
|
|
9
|
+
await commitTrailingStop(symbol, -3, currentPrice);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export default BacktestTightenStopOnBreakevenAction;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const CC_OLLAMA_API_KEY = process.env.CC_OLLAMA_API_KEY || "";
|
package/src/enum/ActionName.mjs
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export default {
|
|
2
|
-
|
|
2
|
+
BacktestPartialProfitTakingAction: "backtest_partial_profit_taking_action",
|
|
3
|
+
BacktestTightenStopOnBreakevenAction: "backtest_tighten_stop_on_breakeven_action",
|
|
4
|
+
BacktestPositionMonitorAction: "backtest_position_monitor_action",
|
|
3
5
|
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { addActionSchema } from "backtest-kit";
|
|
2
|
+
import ActionName from "../../enum/ActionName.mjs";
|
|
3
|
+
import { BacktestPartialProfitTakingAction } from "../../classes/BacktestPartialProfitTakingAction.mjs";
|
|
4
|
+
|
|
5
|
+
addActionSchema({
|
|
6
|
+
actionName: ActionName.BacktestPartialProfitTakingAction,
|
|
7
|
+
handler: BacktestPartialProfitTakingAction,
|
|
8
|
+
note: "Scale out at Kelly-optimized levels (33%, 33%, 34%)",
|
|
9
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { addActionSchema } from "backtest-kit";
|
|
2
|
+
import ActionName from "../../enum/ActionName.mjs";
|
|
3
|
+
import { BacktestPositionMonitorAction } from "../../classes/BacktestPositionMonitorAction.mjs";
|
|
4
|
+
|
|
5
|
+
addActionSchema({
|
|
6
|
+
actionName: ActionName.BacktestPositionMonitorAction,
|
|
7
|
+
handler: BacktestPositionMonitorAction,
|
|
8
|
+
note: "Monitors and logs position lifecycle events (open/close/scheduled)",
|
|
9
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { addActionSchema } from "backtest-kit";
|
|
2
|
+
import ActionName from "../../enum/ActionName.mjs";
|
|
3
|
+
import { BacktestTightenStopOnBreakevenAction } from "../../classes/BacktestTightenStopOnBreakevenAction.mjs";
|
|
4
|
+
|
|
5
|
+
addActionSchema({
|
|
6
|
+
actionName: ActionName.BacktestTightenStopOnBreakevenAction,
|
|
7
|
+
handler: BacktestTightenStopOnBreakevenAction,
|
|
8
|
+
note: "Tighten trailing-stop by 3% when breakeven is reached",
|
|
9
|
+
});
|
package/src/logic/index.mjs
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import "./exchange/binance.exchange.mjs";
|
|
2
2
|
|
|
3
|
-
import "./action/
|
|
3
|
+
import "./action/backtest_partial_profit_taking.action.mjs";
|
|
4
|
+
import "./action/backtest_tighten_stop_on_breakeven.action.mjs";
|
|
5
|
+
import "./action/backtest_position_monitor.action.mjs";
|
|
4
6
|
|
|
5
7
|
import "./frame/dec_2025.frame.mjs";
|
|
6
8
|
import "./frame/nov_2025.frame.mjs";
|
|
@@ -6,6 +6,8 @@ import { commitHistorySetup } from "../../func/market.func.mjs";
|
|
|
6
6
|
import StrategyName from "../../enum/StrategyName.mjs";
|
|
7
7
|
import RiskName from "../../enum/RiskName.mjs";
|
|
8
8
|
|
|
9
|
+
import { CC_OLLAMA_API_KEY } from "../../config/params.mjs";
|
|
10
|
+
|
|
9
11
|
addStrategySchema({
|
|
10
12
|
strategyName: StrategyName.MainStrategy,
|
|
11
13
|
interval: "5m",
|
|
@@ -19,7 +21,7 @@ addStrategySchema({
|
|
|
19
21
|
return await ollama(
|
|
20
22
|
messages,
|
|
21
23
|
"glm-4.6:cloud",
|
|
22
|
-
|
|
24
|
+
CC_OLLAMA_API_KEY
|
|
23
25
|
);
|
|
24
26
|
},
|
|
25
27
|
riskList: [
|
package/src/main/bootstrap.mjs
CHANGED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Backtest, listenError, overrideStrategySchema } from "backtest-kit";
|
|
2
|
+
|
|
3
|
+
import { getArgs } from "../utils/getArgs.mjs";
|
|
4
|
+
|
|
5
|
+
import ActionName from "../enum/ActionName.mjs";
|
|
6
|
+
|
|
7
|
+
const beginBacktest = async () => {
|
|
8
|
+
const { symbol, frameName, strategyName, exchangeName } = getArgs();
|
|
9
|
+
|
|
10
|
+
overrideStrategySchema({
|
|
11
|
+
strategyName,
|
|
12
|
+
actions: [
|
|
13
|
+
ActionName.BacktestPartialProfitTakingAction,
|
|
14
|
+
ActionName.BacktestTightenStopOnBreakevenAction,
|
|
15
|
+
ActionName.BacktestPositionMonitorAction,
|
|
16
|
+
],
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
Backtest.background(symbol, {
|
|
20
|
+
strategyName,
|
|
21
|
+
frameName,
|
|
22
|
+
exchangeName,
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const beginPaper = async () => {
|
|
27
|
+
throw new Error("Todo: implement");
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const beginLive = async () => {
|
|
31
|
+
throw new Error("Todo: implement");
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const main = async () => {
|
|
35
|
+
const { backtest, live, paper } = getArgs();
|
|
36
|
+
|
|
37
|
+
if (backtest) {
|
|
38
|
+
await beginBacktest();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (paper) {
|
|
42
|
+
await beginPaper();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (live) {
|
|
46
|
+
await beginLive();
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
listenError(console.log);
|
|
51
|
+
|
|
52
|
+
main();
|
package/src/utils/getArgs.mjs
CHANGED
|
@@ -1,25 +1,17 @@
|
|
|
1
1
|
import { singleshot } from "functools-kit";
|
|
2
|
-
import { parseArgs } from "
|
|
2
|
+
import { parseArgs } from "backtest-kit";
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
type: "boolean",
|
|
19
|
-
},
|
|
20
|
-
},
|
|
21
|
-
strict: false,
|
|
22
|
-
allowPositionals: true,
|
|
23
|
-
});
|
|
24
|
-
return values;
|
|
25
|
-
});
|
|
4
|
+
import ExchangeName from "../enum/ExchangeName.mjs";
|
|
5
|
+
import StrategyName from "../enum/StrategyName.mjs";
|
|
6
|
+
import FrameName from "../enum/FrameName.mjs";
|
|
7
|
+
|
|
8
|
+
const DEFAULT_SYMBOL = "BTCUSDT";
|
|
9
|
+
|
|
10
|
+
export const getArgs = singleshot(() =>
|
|
11
|
+
parseArgs({
|
|
12
|
+
exchangeName: ExchangeName.BinanceExchange,
|
|
13
|
+
strategyName: StrategyName.MainStrategy,
|
|
14
|
+
frameName: FrameName.October2025,
|
|
15
|
+
symbol: DEFAULT_SYMBOL,
|
|
16
|
+
})
|
|
17
|
+
);
|
|
@@ -5,17 +5,16 @@
|
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Backtest Kit trading bot project",
|
|
7
7
|
"scripts": {
|
|
8
|
-
"start": "node ./src/index.mjs"
|
|
9
|
-
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
|
+
"start": "node ./src/index.mjs --backtest"
|
|
10
9
|
},
|
|
11
10
|
"dependencies": {
|
|
12
|
-
"@backtest-kit/ollama": "^0.1.
|
|
13
|
-
"@backtest-kit/signals": "^0.1.
|
|
11
|
+
"@backtest-kit/ollama": "^0.1.1",
|
|
12
|
+
"@backtest-kit/signals": "^0.1.1",
|
|
14
13
|
"@huggingface/inference": "^4.7.1",
|
|
15
14
|
"@langchain/core": "^0.3.57",
|
|
16
15
|
"@langchain/xai": "^0.0.2",
|
|
17
|
-
"agent-swarm-kit": "^1.1.
|
|
18
|
-
"backtest-kit": "^2.0.
|
|
16
|
+
"agent-swarm-kit": "^1.1.182",
|
|
17
|
+
"backtest-kit": "^2.0.7",
|
|
19
18
|
"ccxt": "^4.4.41",
|
|
20
19
|
"dotenv": "^16.4.7",
|
|
21
20
|
"functools-kit": "^1.0.95",
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { addActionSchema } from "backtest-kit";
|
|
2
|
-
import ActionName from "../../enum/ActionName.mjs";
|
|
3
|
-
import { PartialProfitTakingAction } from "../../classes/PartialProfitTakingAction.mjs";
|
|
4
|
-
|
|
5
|
-
addActionSchema({
|
|
6
|
-
actionName: ActionName.PartialProfitTakingAction,
|
|
7
|
-
handler: PartialProfitTakingAction,
|
|
8
|
-
});
|