From f66cc073b22c374ae1e1acd29bd9534a398ef6a5 Mon Sep 17 00:00:00 2001 From: aleksnick Date: Sat, 5 Sep 2026 10:46:56 +0300 Subject: [PATCH 1/2] fix: separate strategy risk estimates from execution costs --- src/TrendFollow/config.ts | 6 ++++-- src/TrendFollow/core.ts | 6 +++--- src/TrendFollow/strategy.ts | 4 ++-- src/__tests__/configContract.test.ts | 21 +++++++++++++++++++++ 4 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/TrendFollow/config.ts b/src/TrendFollow/config.ts index ab55fc0..f8bf514 100644 --- a/src/TrendFollow/config.ts +++ b/src/TrendFollow/config.ts @@ -1,4 +1,4 @@ -import { FEE_PERCENT } from "@tradejs/core/constants"; +import { FEE_PERCENT as RISK_FEE_RATE } from "@tradejs/core/constants"; import { BacktestPriceMode, Direction, @@ -23,7 +23,9 @@ export const config = { ML_ENABLED: false, ML_THRESHOLD: 0.1, MIN_AI_QUALITY: 3, - FEE_PERCENT, + RISK_FEE_RATE, + RISK_SLIPPAGE_BPS: 0, + RISK_MARKET_IMPACT_BPS: 0, MAX_LOSS_VALUE: 10, MA_FAST: 14, MA_MEDIUM: 49, diff --git a/src/TrendFollow/core.ts b/src/TrendFollow/core.ts index 316001b..33dcea5 100644 --- a/src/TrendFollow/core.ts +++ b/src/TrendFollow/core.ts @@ -156,10 +156,10 @@ export const createTrendFollowCore: CreateStrategyCore< fallback: 2, }), maxLossValue: config.MAX_LOSS_VALUE, - feeRate: Number(config.FEE_PERCENT ?? 0), + feeRate: Number(config.RISK_FEE_RATE ?? 0), slippageBps: - Number(config.SLIPPAGE_BASE_BPS ?? 0) + - Number(config.SLIPPAGE_MARKET_IMPACT_BPS ?? 0), + Number(config.RISK_SLIPPAGE_BPS ?? 0) + + Number(config.RISK_MARKET_IMPACT_BPS ?? 0), }); if (!qty || !Number.isFinite(qty) || qty <= 0) { diff --git a/src/TrendFollow/strategy.ts b/src/TrendFollow/strategy.ts index ffe8ba3..2c39782 100644 --- a/src/TrendFollow/strategy.ts +++ b/src/TrendFollow/strategy.ts @@ -1,4 +1,4 @@ -import { createStrategyConfigParser } from "@tradejs/strategy-kit/config"; +import { createCostIsolatedStrategyConfigParser } from "@tradejs/strategy-kit/config"; import type { ValidatedStrategyRegistryEntry } from "@tradejs/strategy-kit/config"; import { config as DEFAULT_CONFIG, TrendFollowConfig } from "./config"; import { createTrendFollowCore } from "./core"; @@ -7,7 +7,7 @@ import { trendFollowManifest } from "./manifest"; export const TrendFollowStrategyDefinition: ValidatedStrategyRegistryEntry = { defaults: DEFAULT_CONFIG, - parseConfig: createStrategyConfigParser({ + parseConfig: createCostIsolatedStrategyConfigParser({ strategyName: "TrendFollow", defaults: DEFAULT_CONFIG, }), diff --git a/src/__tests__/configContract.test.ts b/src/__tests__/configContract.test.ts index e251253..8e8ae53 100644 --- a/src/__tests__/configContract.test.ts +++ b/src/__tests__/configContract.test.ts @@ -3,6 +3,27 @@ import path from "node:path"; import { strategyEntries } from "../index"; describe("strategy config contract", () => { + it.each(strategyEntries)( + "keeps decision costs explicit for $manifest.name", + (entry) => { + const config = entry.parseConfig({ + RISK_FEE_RATE: 0.002, + RISK_SLIPPAGE_BPS: 15, + }); + expect(config).toMatchObject({ + RISK_FEE_RATE: 0.002, + RISK_SLIPPAGE_BPS: 15, + }); + expect(() => entry.parseConfig({ SLIPPAGE_BASE_BPS: 10 })).toThrow( + "SLIPPAGE_BASE_BPS", + ); + expect(entry.defaults).not.toHaveProperty("FEE_PERCENT"); + expect(entry.defaults).not.toHaveProperty("SLIPPAGE_BASE_BPS"); + expect(() => entry.parseConfig({ FEE_PERCENT: 0.001 })).toThrow( + "FEE_PERCENT", + ); + }, + ); it.each(strategyEntries)( "materializes defaults and rejects unknown fields for $manifest.name", (entry) => { From 0a3a0139b1618d63e4e9e08e5ab66da69a14a3f0 Mon Sep 17 00:00:00 2001 From: aleksnick Date: Tue, 8 Sep 2026 12:03:45 +0300 Subject: [PATCH 2/2] fix: require Strategy Kit 3.0.5 --- package.json | 4 ++-- yarn.lock | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 5d3f2a5..b9b1bc3 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "sideEffects": false, "devDependencies": { "@tradejs/core": "^3.0.1", - "@tradejs/strategy-kit": "^3.0.1", + "@tradejs/strategy-kit": "^3.0.5", "@tradejs/types": "^3.0.1", "@types/jest": "^29.5.14", "jest": "^29.7.0", @@ -70,7 +70,7 @@ "author": "aleksnick (https://github.com/aleksnick)", "peerDependencies": { "@tradejs/core": "^3.0.1", - "@tradejs/strategy-kit": "^3.0.1", + "@tradejs/strategy-kit": "^3.0.5", "@tradejs/types": "^3.0.1" } } diff --git a/yarn.lock b/yarn.lock index 02e8c35..5d78599 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1086,13 +1086,13 @@ __metadata: languageName: node linkType: hard -"@tradejs/strategy-kit@npm:^3.0.1": - version: 3.0.1 - resolution: "@tradejs/strategy-kit@npm:3.0.1" - dependencies: - "@tradejs/core": "npm:^3.0.1" - "@tradejs/types": "npm:^3.0.1" - checksum: 10c0/425e4e97e5cd1995c9ad32cd6e61bdb098da4b0dde069e90438081e92e0852a2b4757ebf1bd06733b009359dc365c8756155793d1287642cc2f2b8eaa022eef2 +"@tradejs/strategy-kit@npm:^3.0.5": + version: 3.0.5 + resolution: "@tradejs/strategy-kit@npm:3.0.5" + peerDependencies: + "@tradejs/core": ^3.0.1 + "@tradejs/types": ^3.0.1 + checksum: 10c0/9ddef5586ab48515419e7e8563802156fa98597e8809d760ae78f064637013d5c23a4edd8bfa949225aab503f21e03236cde816d23a5ba75d3b7765c8f6bad75 languageName: node linkType: hard @@ -1101,7 +1101,7 @@ __metadata: resolution: "@tradejs/strategy-trend-follow@workspace:." dependencies: "@tradejs/core": "npm:^3.0.1" - "@tradejs/strategy-kit": "npm:^3.0.1" + "@tradejs/strategy-kit": "npm:^3.0.5" "@tradejs/types": "npm:^3.0.1" "@types/jest": "npm:^29.5.14" jest: "npm:^29.7.0" @@ -1111,7 +1111,7 @@ __metadata: typescript: "npm:^5.9.2" peerDependencies: "@tradejs/core": ^3.0.1 - "@tradejs/strategy-kit": ^3.0.1 + "@tradejs/strategy-kit": ^3.0.5 "@tradejs/types": ^3.0.1 languageName: unknown linkType: soft