@senpi/runtime 1.0.95-dev.feat-dsl-backend-int.20260416023008 → 1.0.95-dev.runtime-phase-2.20260416194608
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 +72 -0
- package/dist/actions/action-runtime-module.d.ts +55 -0
- package/dist/actions/action-runtime-module.d.ts.map +1 -0
- package/dist/actions/action-runtime-module.js +444 -0
- package/dist/actions/action-runtime-module.js.map +1 -0
- package/dist/actions/close-position/close-position.action.d.ts +1 -0
- package/dist/actions/close-position/close-position.action.d.ts.map +1 -1
- package/dist/actions/close-position/close-position.action.js +55 -20
- package/dist/actions/close-position/close-position.action.js.map +1 -1
- package/dist/actions/decision-engine.d.ts.map +1 -1
- package/dist/actions/decision-engine.js +5 -0
- package/dist/actions/decision-engine.js.map +1 -1
- package/dist/actions/llm-decision/shared.d.ts +1 -1
- package/dist/actions/llm-decision/shared.d.ts.map +1 -1
- package/dist/actions/llm-decision/shared.js +1 -1
- package/dist/actions/llm-decision/shared.js.map +1 -1
- package/dist/actions/notifications/formatter.d.ts +39 -0
- package/dist/actions/notifications/formatter.d.ts.map +1 -0
- package/dist/actions/notifications/formatter.js +68 -0
- package/dist/actions/notifications/formatter.js.map +1 -0
- package/dist/actions/notifications/index.d.ts +37 -0
- package/dist/actions/notifications/index.d.ts.map +1 -0
- package/dist/actions/notifications/index.js +89 -0
- package/dist/actions/notifications/index.js.map +1 -0
- package/dist/actions/open-position/open-position.action.d.ts +1 -0
- package/dist/actions/open-position/open-position.action.d.ts.map +1 -1
- package/dist/actions/open-position/open-position.action.js +132 -27
- package/dist/actions/open-position/open-position.action.js.map +1 -1
- package/dist/actions/open-position/resolve-margin.d.ts +22 -0
- package/dist/actions/open-position/resolve-margin.d.ts.map +1 -0
- package/dist/actions/open-position/resolve-margin.js +30 -0
- package/dist/actions/open-position/resolve-margin.js.map +1 -0
- package/dist/actions/position-tracker/position-tracker.action.d.ts.map +1 -1
- package/dist/actions/position-tracker/position-tracker.action.js +4 -1
- package/dist/actions/position-tracker/position-tracker.action.js.map +1 -1
- package/dist/actions/store/action-store.d.ts +45 -0
- package/dist/actions/store/action-store.d.ts.map +1 -0
- package/dist/actions/store/action-store.js +127 -0
- package/dist/actions/store/action-store.js.map +1 -0
- package/dist/actions/store/index.d.ts +11 -0
- package/dist/actions/store/index.d.ts.map +1 -0
- package/dist/actions/store/index.js +9 -0
- package/dist/actions/store/index.js.map +1 -0
- package/dist/actions/store/paths.d.ts +15 -0
- package/dist/actions/store/paths.d.ts.map +1 -0
- package/dist/actions/store/paths.js +29 -0
- package/dist/actions/store/paths.js.map +1 -0
- package/dist/actions/store/types.d.ts +114 -0
- package/dist/actions/store/types.d.ts.map +1 -0
- package/dist/actions/store/types.js +48 -0
- package/dist/actions/store/types.js.map +1 -0
- package/dist/actions/tracking-helpers.d.ts +13 -0
- package/dist/actions/tracking-helpers.d.ts.map +1 -0
- package/dist/actions/tracking-helpers.js +47 -0
- package/dist/actions/tracking-helpers.js.map +1 -0
- package/dist/actions/types.d.ts +8 -0
- package/dist/actions/types.d.ts.map +1 -1
- package/dist/cli/guide-commands.d.ts.map +1 -1
- package/dist/cli/guide-commands.js +105 -3
- package/dist/cli/guide-commands.js.map +1 -1
- package/dist/cli/senpi-commands.d.ts.map +1 -1
- package/dist/cli/senpi-commands.js +428 -1
- package/dist/cli/senpi-commands.js.map +1 -1
- package/dist/constants/order-types.d.ts +7 -0
- package/dist/constants/order-types.d.ts.map +1 -0
- package/dist/constants/order-types.js +6 -0
- package/dist/constants/order-types.js.map +1 -0
- package/dist/context/interpolate.d.ts +6 -2
- package/dist/context/interpolate.d.ts.map +1 -1
- package/dist/context/interpolate.js +6 -2
- package/dist/context/interpolate.js.map +1 -1
- package/dist/context/types.d.ts +8 -1
- package/dist/context/types.d.ts.map +1 -1
- package/dist/context/types.js +8 -1
- package/dist/context/types.js.map +1 -1
- package/dist/dsl/config/exit-block.d.ts +7 -0
- package/dist/dsl/config/exit-block.d.ts.map +1 -1
- package/dist/dsl/config/parse-plugin-config.d.ts.map +1 -1
- package/dist/dsl/config/parse-plugin-config.js +27 -1
- package/dist/dsl/config/parse-plugin-config.js.map +1 -1
- package/dist/dsl/config/unknown-keys.d.ts.map +1 -1
- package/dist/dsl/config/unknown-keys.js +3 -1
- package/dist/dsl/config/unknown-keys.js.map +1 -1
- package/dist/dsl/monitor/create-monitor.d.ts +4 -0
- package/dist/dsl/monitor/create-monitor.d.ts.map +1 -1
- package/dist/dsl/monitor/create-monitor.js +8 -5
- package/dist/dsl/monitor/create-monitor.js.map +1 -1
- package/dist/dsl/monitor/process-one-position.d.ts +4 -0
- package/dist/dsl/monitor/process-one-position.d.ts.map +1 -1
- package/dist/dsl/monitor/process-one-position.js +8 -2
- package/dist/dsl/monitor/process-one-position.js.map +1 -1
- package/dist/dsl/plugin/index.d.ts.map +1 -1
- package/dist/dsl/plugin/index.js +3 -1
- package/dist/dsl/plugin/index.js.map +1 -1
- package/dist/health/index.d.ts +5 -2
- package/dist/health/index.d.ts.map +1 -1
- package/dist/health/index.js +106 -6
- package/dist/health/index.js.map +1 -1
- package/dist/health/types.d.ts +102 -0
- package/dist/health/types.d.ts.map +1 -1
- package/dist/health/types.js +7 -1
- package/dist/health/types.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +98 -1
- package/dist/index.js.map +1 -1
- package/dist/risk/guardrail.types.d.ts +53 -0
- package/dist/risk/guardrail.types.d.ts.map +1 -0
- package/dist/risk/guardrail.types.js +5 -0
- package/dist/risk/guardrail.types.js.map +1 -0
- package/dist/risk/index.d.ts +2 -4
- package/dist/risk/index.d.ts.map +1 -1
- package/dist/risk/index.js +2 -6
- package/dist/risk/index.js.map +1 -1
- package/dist/risk/risk-audit-log.d.ts +25 -0
- package/dist/risk/risk-audit-log.d.ts.map +1 -0
- package/dist/risk/risk-audit-log.js +30 -0
- package/dist/risk/risk-audit-log.js.map +1 -0
- package/dist/runtime/__tests__/helpers/runtime-gateway-harness.d.ts +162 -0
- package/dist/runtime/__tests__/helpers/runtime-gateway-harness.d.ts.map +1 -0
- package/dist/runtime/__tests__/helpers/runtime-gateway-harness.js +285 -0
- package/dist/runtime/__tests__/helpers/runtime-gateway-harness.js.map +1 -0
- package/dist/runtime/create-actions.d.ts +6 -2
- package/dist/runtime/create-actions.d.ts.map +1 -1
- package/dist/runtime/create-actions.js +18 -7
- package/dist/runtime/create-actions.js.map +1 -1
- package/dist/runtime/create-scanner-module.d.ts +5 -0
- package/dist/runtime/create-scanner-module.d.ts.map +1 -1
- package/dist/runtime/create-scanner-module.js +12 -1
- package/dist/runtime/create-scanner-module.js.map +1 -1
- package/dist/runtime/load-runtime-config.d.ts +1 -1
- package/dist/runtime/load-runtime-config.d.ts.map +1 -1
- package/dist/runtime/load-runtime-config.js +37 -1
- package/dist/runtime/load-runtime-config.js.map +1 -1
- package/dist/runtime/map-strategies.d.ts +1 -1
- package/dist/runtime/map-strategies.d.ts.map +1 -1
- package/dist/runtime/map-strategies.js +38 -1
- package/dist/runtime/map-strategies.js.map +1 -1
- package/dist/runtime/risk-guard.d.ts +23 -2
- package/dist/runtime/risk-guard.d.ts.map +1 -1
- package/dist/runtime/risk-guard.js +441 -5
- package/dist/runtime/risk-guard.js.map +1 -1
- package/dist/runtime/run.d.ts +7 -0
- package/dist/runtime/run.d.ts.map +1 -1
- package/dist/runtime/run.js +3 -0
- package/dist/runtime/run.js.map +1 -1
- package/dist/runtime/runtime-schema.d.ts +1169 -24
- package/dist/runtime/runtime-schema.d.ts.map +1 -1
- package/dist/runtime/runtime-schema.js +105 -2
- package/dist/runtime/runtime-schema.js.map +1 -1
- package/dist/runtime/runtime.d.ts +26 -0
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +192 -6
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/runtime/scanner-composition.d.ts +10 -0
- package/dist/runtime/scanner-composition.d.ts.map +1 -1
- package/dist/runtime/scanner-composition.js +10 -0
- package/dist/runtime/scanner-composition.js.map +1 -1
- package/dist/runtime/scanner-registry.d.ts +39 -1
- package/dist/runtime/scanner-registry.d.ts.map +1 -1
- package/dist/runtime/scanner-registry.js +105 -2
- package/dist/runtime/scanner-registry.js.map +1 -1
- package/dist/runtime/state-layout.d.ts +2 -0
- package/dist/runtime/state-layout.d.ts.map +1 -1
- package/dist/runtime/state-layout.js +1 -0
- package/dist/runtime/state-layout.js.map +1 -1
- package/dist/runtime/validate-action-prompts.d.ts +30 -0
- package/dist/runtime/validate-action-prompts.d.ts.map +1 -0
- package/dist/runtime/validate-action-prompts.js +110 -0
- package/dist/runtime/validate-action-prompts.js.map +1 -0
- package/dist/scanners/__tests__/test-helpers.d.ts +10 -0
- package/dist/scanners/__tests__/test-helpers.d.ts.map +1 -1
- package/dist/scanners/__tests__/test-helpers.js +52 -0
- package/dist/scanners/__tests__/test-helpers.js.map +1 -1
- package/dist/scanners/engine/engine.d.ts +37 -0
- package/dist/scanners/engine/engine.d.ts.map +1 -1
- package/dist/scanners/engine/engine.js +132 -14
- package/dist/scanners/engine/engine.js.map +1 -1
- package/dist/scanners/engine/result-builder.d.ts +16 -0
- package/dist/scanners/engine/result-builder.d.ts.map +1 -1
- package/dist/scanners/engine/result-builder.js +22 -0
- package/dist/scanners/engine/result-builder.js.map +1 -1
- package/dist/scanners/engine/strategy-registry.d.ts +2 -0
- package/dist/scanners/engine/strategy-registry.d.ts.map +1 -1
- package/dist/scanners/engine/strategy-registry.js +5 -1
- package/dist/scanners/engine/strategy-registry.js.map +1 -1
- package/dist/scanners/external-scanner-receiver.d.ts +118 -0
- package/dist/scanners/external-scanner-receiver.d.ts.map +1 -0
- package/dist/scanners/external-scanner-receiver.js +266 -0
- package/dist/scanners/external-scanner-receiver.js.map +1 -0
- package/dist/scanners/implementations/external-scanner.d.ts +17 -0
- package/dist/scanners/implementations/external-scanner.d.ts.map +1 -0
- package/dist/scanners/implementations/external-scanner.js +51 -0
- package/dist/scanners/implementations/external-scanner.js.map +1 -0
- package/dist/scanners/implementations/index.d.ts +1 -0
- package/dist/scanners/implementations/index.d.ts.map +1 -1
- package/dist/scanners/implementations/index.js +1 -0
- package/dist/scanners/implementations/index.js.map +1 -1
- package/dist/scanners/implementations/position-tracker.d.ts.map +1 -1
- package/dist/scanners/implementations/position-tracker.js +3 -1
- package/dist/scanners/implementations/position-tracker.js.map +1 -1
- package/dist/scanners/index.d.ts +4 -1
- package/dist/scanners/index.d.ts.map +1 -1
- package/dist/scanners/index.js +2 -0
- package/dist/scanners/index.js.map +1 -1
- package/dist/scanners/protocol/scanner.d.ts +3 -1
- package/dist/scanners/protocol/scanner.d.ts.map +1 -1
- package/dist/scanners/providers/client.d.ts.map +1 -1
- package/dist/scanners/providers/client.js +0 -8
- package/dist/scanners/providers/client.js.map +1 -1
- package/dist/scanners/runtime-module.d.ts +10 -0
- package/dist/scanners/runtime-module.d.ts.map +1 -1
- package/dist/scanners/runtime-module.js +19 -3
- package/dist/scanners/runtime-module.js.map +1 -1
- package/dist/scanners/scanner-definition.d.ts +12 -1
- package/dist/scanners/scanner-definition.d.ts.map +1 -1
- package/dist/scanners/types.d.ts +3 -0
- package/dist/scanners/types.d.ts.map +1 -1
- package/dist/scanners/types.js.map +1 -1
- package/dist/scripts/run-dsl-standalone-live.js +1 -1
- package/dist/scripts/run-dsl-standalone-live.js.map +1 -1
- package/dist/scripts/run-dsl-standalone-mock.js +1 -1
- package/dist/scripts/run-dsl-standalone-mock.js.map +1 -1
- package/dist/senpi/client.d.ts +27 -2
- package/dist/senpi/client.d.ts.map +1 -1
- package/dist/senpi/client.js +74 -1
- package/dist/senpi/client.js.map +1 -1
- package/dist/senpi/index.d.ts +1 -1
- package/dist/senpi/index.d.ts.map +1 -1
- package/dist/senpi/types.d.ts +68 -0
- package/dist/senpi/types.d.ts.map +1 -1
- package/dist/strategy/strategy-state.d.ts +4 -1
- package/dist/strategy/strategy-state.d.ts.map +1 -1
- package/dist/strategy/strategy-state.js +7 -2
- package/dist/strategy/strategy-state.js.map +1 -1
- package/dist/tracking/constants.d.ts +24 -0
- package/dist/tracking/constants.d.ts.map +1 -0
- package/dist/tracking/constants.js +46 -0
- package/dist/tracking/constants.js.map +1 -0
- package/dist/tracking/index.d.ts +12 -0
- package/dist/tracking/index.d.ts.map +1 -0
- package/dist/tracking/index.js +8 -0
- package/dist/tracking/index.js.map +1 -0
- package/dist/tracking/tracker.d.ts +22 -0
- package/dist/tracking/tracker.d.ts.map +1 -0
- package/dist/tracking/tracker.js +44 -0
- package/dist/tracking/tracker.js.map +1 -0
- package/dist/tracking/tracking-handler.d.ts +12 -0
- package/dist/tracking/tracking-handler.d.ts.map +1 -0
- package/dist/tracking/tracking-handler.js +148 -0
- package/dist/tracking/tracking-handler.js.map +1 -0
- package/dist/tracking/transport.d.ts +35 -0
- package/dist/tracking/transport.d.ts.map +1 -0
- package/dist/tracking/transport.js +117 -0
- package/dist/tracking/transport.js.map +1 -0
- package/dist/tracking/types.d.ts +21 -0
- package/dist/tracking/types.d.ts.map +1 -0
- package/dist/tracking/types.js +6 -0
- package/dist/tracking/types.js.map +1 -0
- package/dist/types/action.d.ts +13 -2
- package/dist/types/action.d.ts.map +1 -1
- package/dist/types/dsl/index.d.ts +3 -0
- package/dist/types/dsl/index.d.ts.map +1 -1
- package/dist/types/strategy.d.ts +9 -3
- package/dist/types/strategy.d.ts.map +1 -1
- package/dist/utils/logger.d.ts +1 -0
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +19 -1
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/resolve-order-type.d.ts +5 -0
- package/dist/utils/resolve-order-type.d.ts.map +1 -0
- package/dist/utils/resolve-order-type.js +29 -0
- package/dist/utils/resolve-order-type.js.map +1 -0
- package/examples/strategies/dsl-showcase.yaml +7 -2
- package/examples/strategies/dsl.yaml +5 -1
- package/examples/strategies/fox-minimal-loosened.yaml +18 -3
- package/examples/strategies/fox-minimal.yaml +25 -3
- package/examples/strategies/minimal.yaml +4 -2
- package/examples/strategies/momentum/how-it-works.md +47 -0
- package/examples/strategies/momentum/momentum-guarded.yaml +161 -0
- package/examples/strategies/risk-showcase.yaml +93 -0
- package/examples/strategies/viper.yaml +11 -3
- package/examples/strategies/wolf.yaml +11 -3
- package/examples/yamls/sample-with-dsl-and-emerging-movers.yaml +12 -4
- package/package.json +4 -4
package/dist/utils/logger.js
CHANGED
|
@@ -7,12 +7,30 @@ const levelOrder = {
|
|
|
7
7
|
warn: 2,
|
|
8
8
|
error: 3,
|
|
9
9
|
};
|
|
10
|
-
|
|
10
|
+
const DEFAULT_LEVEL = "info";
|
|
11
|
+
function resolveInitialLevel() {
|
|
12
|
+
const raw = process.env.SENPI_LOG_LEVEL;
|
|
13
|
+
if (raw == null || raw === "")
|
|
14
|
+
return DEFAULT_LEVEL;
|
|
15
|
+
const normalized = raw.toLowerCase();
|
|
16
|
+
if (normalized === "debug" ||
|
|
17
|
+
normalized === "info" ||
|
|
18
|
+
normalized === "warn" ||
|
|
19
|
+
normalized === "error") {
|
|
20
|
+
return normalized;
|
|
21
|
+
}
|
|
22
|
+
console.warn(`[logger] Unknown SENPI_LOG_LEVEL="${raw}"; falling back to "${DEFAULT_LEVEL}"`);
|
|
23
|
+
return DEFAULT_LEVEL;
|
|
24
|
+
}
|
|
25
|
+
let minLevel = resolveInitialLevel();
|
|
11
26
|
let errorNotifier = null;
|
|
12
27
|
let notifyingError = false;
|
|
13
28
|
export function setLogLevel(level) {
|
|
14
29
|
minLevel = level;
|
|
15
30
|
}
|
|
31
|
+
export function getLogLevel() {
|
|
32
|
+
return minLevel;
|
|
33
|
+
}
|
|
16
34
|
export function setErrorNotifier(notifier) {
|
|
17
35
|
errorNotifier = notifier;
|
|
18
36
|
}
|
package/dist/utils/logger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,MAAM,UAAU,GAA6B;IAC3C,KAAK,EAAE,CAAC;IACR,IAAI,EAAE,CAAC;IACP,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,CAAC;CACT,CAAC;AAEF,IAAI,QAAQ,GAAa,
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { OrderType, CloseOrderType, FeeOptimizedLimitOptions } from '../senpi/types.js';
|
|
2
|
+
export declare function resolveOpenOrderType(raw: unknown): OrderType;
|
|
3
|
+
export declare function resolveCloseOrderType(raw: unknown): CloseOrderType;
|
|
4
|
+
export declare function resolveFeeOptimizedLimitOptions(raw: unknown): FeeOptimizedLimitOptions | undefined;
|
|
5
|
+
//# sourceMappingURL=resolve-order-type.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-order-type.d.ts","sourceRoot":"","sources":["../../src/utils/resolve-order-type.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAM7F,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,OAAO,GAAG,SAAS,CAI5D;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,cAAc,CAIlE;AAED,wBAAgB,+BAA+B,CAAC,GAAG,EAAE,OAAO,GAAG,wBAAwB,GAAG,SAAS,CAOlG"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { createLogger } from './logger.js';
|
|
2
|
+
import { VALID_OPEN_ORDER_TYPES, VALID_CLOSE_ORDER_TYPES } from '../constants/order-types.js';
|
|
3
|
+
const logger = createLogger('[order-type]');
|
|
4
|
+
export function resolveOpenOrderType(raw) {
|
|
5
|
+
if (typeof raw === 'string' && VALID_OPEN_ORDER_TYPES.has(raw))
|
|
6
|
+
return raw;
|
|
7
|
+
if (raw != null)
|
|
8
|
+
logger.warn('invalid order_type for open, falling back to MARKET', { value: raw });
|
|
9
|
+
return 'MARKET';
|
|
10
|
+
}
|
|
11
|
+
export function resolveCloseOrderType(raw) {
|
|
12
|
+
if (typeof raw === 'string' && VALID_CLOSE_ORDER_TYPES.has(raw))
|
|
13
|
+
return raw;
|
|
14
|
+
if (raw != null)
|
|
15
|
+
logger.warn('invalid order_type for close, falling back to MARKET', { value: raw });
|
|
16
|
+
return 'MARKET';
|
|
17
|
+
}
|
|
18
|
+
export function resolveFeeOptimizedLimitOptions(raw) {
|
|
19
|
+
if (raw == null || typeof raw !== 'object' || Array.isArray(raw))
|
|
20
|
+
return undefined;
|
|
21
|
+
const obj = raw;
|
|
22
|
+
const result = {};
|
|
23
|
+
if (typeof obj.ensure_execution_as_taker === 'boolean')
|
|
24
|
+
result.ensureExecutionAsTaker = obj.ensure_execution_as_taker;
|
|
25
|
+
if (typeof obj.execution_timeout_seconds === 'number')
|
|
26
|
+
result.executionTimeoutSeconds = obj.execution_timeout_seconds;
|
|
27
|
+
return Object.keys(result).length > 0 ? result : undefined;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=resolve-order-type.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-order-type.js","sourceRoot":"","sources":["../../src/utils/resolve-order-type.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AAE9F,MAAM,MAAM,GAAG,YAAY,CAAC,cAAc,CAAC,CAAC;AAE5C,MAAM,UAAU,oBAAoB,CAAC,GAAY;IAC/C,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,sBAAsB,CAAC,GAAG,CAAC,GAAgB,CAAC;QAAE,OAAO,GAAgB,CAAC;IACrG,IAAI,GAAG,IAAI,IAAI;QAAE,MAAM,CAAC,IAAI,CAAC,qDAAqD,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;IACpG,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,GAAY;IAChD,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,uBAAuB,CAAC,GAAG,CAAC,GAAqB,CAAC;QAAE,OAAO,GAAqB,CAAC;IAChH,IAAI,GAAG,IAAI,IAAI;QAAE,MAAM,CAAC,IAAI,CAAC,sDAAsD,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;IACrG,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,+BAA+B,CAAC,GAAY;IAC1D,IAAI,GAAG,IAAI,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC;IACnF,MAAM,GAAG,GAAG,GAA8B,CAAC;IAC3C,MAAM,MAAM,GAA6B,EAAE,CAAC;IAC5C,IAAI,OAAO,GAAG,CAAC,yBAAyB,KAAK,SAAS;QAAE,MAAM,CAAC,sBAAsB,GAAG,GAAG,CAAC,yBAAyB,CAAC;IACtH,IAAI,OAAO,GAAG,CAAC,yBAAyB,KAAK,QAAQ;QAAE,MAAM,CAAC,uBAAuB,GAAG,GAAG,CAAC,yBAAyB,CAAC;IACtH,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;AAC7D,CAAC"}
|
|
@@ -14,9 +14,8 @@ notifications:
|
|
|
14
14
|
|
|
15
15
|
strategy:
|
|
16
16
|
wallet: "${WALLET_ADDRESS}"
|
|
17
|
-
budget: 500
|
|
18
17
|
slots: 2
|
|
19
|
-
|
|
18
|
+
margin_pct: 15
|
|
20
19
|
trading_risk: conservative
|
|
21
20
|
enabled: true
|
|
22
21
|
|
|
@@ -37,6 +36,12 @@ exit:
|
|
|
37
36
|
engine: dsl
|
|
38
37
|
# interval_seconds — how often the price monitor runs
|
|
39
38
|
interval_seconds: 30
|
|
39
|
+
# order_type — execution method for DSL exit closes: MARKET (default) or FEE_OPTIMIZED_LIMIT
|
|
40
|
+
order_type: FEE_OPTIMIZED_LIMIT
|
|
41
|
+
# fee_optimized_limit_options — only used when order_type is FEE_OPTIMIZED_LIMIT
|
|
42
|
+
fee_optimized_limit_options:
|
|
43
|
+
ensure_execution_as_taker: true # fall back to market if maker doesn't fill
|
|
44
|
+
execution_timeout_seconds: 15 # seconds to wait for maker fill (default 45)
|
|
40
45
|
# dsl_preset — single exit profile (required for DslPlugin).
|
|
41
46
|
dsl_preset:
|
|
42
47
|
hard_timeout:
|
|
@@ -6,7 +6,7 @@ description: >
|
|
|
6
6
|
into the DSL exit engine for automated trailing stop-loss management.
|
|
7
7
|
|
|
8
8
|
# ── STRATEGY ──
|
|
9
|
-
# Minimal: only wallet address + optional fields (no
|
|
9
|
+
# Minimal: only wallet address + optional fields (no slots/margin needed for watch-only)
|
|
10
10
|
strategy:
|
|
11
11
|
wallet: "${WALLET_ADDRESS}"
|
|
12
12
|
enabled: true
|
|
@@ -28,6 +28,10 @@ actions:
|
|
|
28
28
|
exit:
|
|
29
29
|
engine: dsl
|
|
30
30
|
interval_seconds: 30
|
|
31
|
+
order_type: FEE_OPTIMIZED_LIMIT
|
|
32
|
+
fee_optimized_limit_options:
|
|
33
|
+
ensure_execution_as_taker: true
|
|
34
|
+
execution_timeout_seconds: 15
|
|
31
35
|
dsl_preset:
|
|
32
36
|
phase1:
|
|
33
37
|
enabled: true
|
|
@@ -10,9 +10,8 @@ notifications:
|
|
|
10
10
|
|
|
11
11
|
strategy:
|
|
12
12
|
wallet: "${FOX_WALLET}"
|
|
13
|
-
budget: "100"
|
|
14
13
|
slots: 3
|
|
15
|
-
|
|
14
|
+
margin_pct: 10
|
|
16
15
|
trading_risk: aggressive
|
|
17
16
|
enabled: true
|
|
18
17
|
|
|
@@ -111,6 +110,11 @@ actions:
|
|
|
111
110
|
decision_model: ${DECISION_MODEL}
|
|
112
111
|
scanners: [emerging_movers]
|
|
113
112
|
min_confidence: 4
|
|
113
|
+
params:
|
|
114
|
+
order_type: FEE_OPTIMIZED_LIMIT
|
|
115
|
+
fee_optimized_limit_options:
|
|
116
|
+
ensure_execution_as_taker: true
|
|
117
|
+
execution_timeout_seconds: 15
|
|
114
118
|
context:
|
|
115
119
|
- type: signal
|
|
116
120
|
scanner: emerging_movers
|
|
@@ -177,7 +181,7 @@ actions:
|
|
|
177
181
|
"reasoning": "one sentence",
|
|
178
182
|
"payload": {
|
|
179
183
|
"signals": [
|
|
180
|
-
{ "asset": "<ticker>", "direction": "LONG" or "SHORT", "reason": "one sentence", "rotate_out": "<asset_to_cut>" }
|
|
184
|
+
{ "asset": "<ticker>", "direction": "LONG" or "SHORT", "reason": "one sentence", "rotate_out": "<asset_to_cut>", "leverage": "<optional number>", "margin": "<optional $ amount>" }
|
|
181
185
|
]
|
|
182
186
|
}
|
|
183
187
|
}
|
|
@@ -188,6 +192,11 @@ actions:
|
|
|
188
192
|
decision_mode: rule
|
|
189
193
|
scanners: [sm_flip]
|
|
190
194
|
min_confidence: 1
|
|
195
|
+
params:
|
|
196
|
+
order_type: FEE_OPTIMIZED_LIMIT
|
|
197
|
+
fee_optimized_limit_options:
|
|
198
|
+
ensure_execution_as_taker: true
|
|
199
|
+
execution_timeout_seconds: 10
|
|
191
200
|
|
|
192
201
|
# ── Watchdog: emergency close on margin danger ──
|
|
193
202
|
- name: watchdog_close
|
|
@@ -195,11 +204,17 @@ actions:
|
|
|
195
204
|
decision_mode: rule
|
|
196
205
|
scanners: [watchdog]
|
|
197
206
|
min_confidence: 1
|
|
207
|
+
params:
|
|
208
|
+
order_type: MARKET
|
|
198
209
|
|
|
199
210
|
# ── DSL — trailing exit
|
|
200
211
|
exit:
|
|
201
212
|
engine: dsl
|
|
202
213
|
interval_seconds: 30
|
|
214
|
+
order_type: FEE_OPTIMIZED_LIMIT
|
|
215
|
+
fee_optimized_limit_options:
|
|
216
|
+
ensure_execution_as_taker: true
|
|
217
|
+
execution_timeout_seconds: 15
|
|
203
218
|
dsl_preset:
|
|
204
219
|
hard_timeout:
|
|
205
220
|
enabled: false
|
|
@@ -8,7 +8,6 @@ description: >
|
|
|
8
8
|
|
|
9
9
|
strategy:
|
|
10
10
|
wallet: "${FOX_WALLET}"
|
|
11
|
-
budget: "500"
|
|
12
11
|
slots: 1
|
|
13
12
|
margin_per_slot: 100
|
|
14
13
|
trading_risk: aggressive
|
|
@@ -109,6 +108,11 @@ actions:
|
|
|
109
108
|
decision_model: claude-sonnet-4-6
|
|
110
109
|
scanners: [emerging_movers]
|
|
111
110
|
min_confidence: 7
|
|
111
|
+
params:
|
|
112
|
+
order_type: FEE_OPTIMIZED_LIMIT
|
|
113
|
+
fee_optimized_limit_options:
|
|
114
|
+
ensure_execution_as_taker: true
|
|
115
|
+
execution_timeout_seconds: 15
|
|
112
116
|
context:
|
|
113
117
|
- type: signal
|
|
114
118
|
scanner: emerging_movers
|
|
@@ -182,7 +186,14 @@ actions:
|
|
|
182
186
|
"reasoning": "one sentence",
|
|
183
187
|
"payload": {
|
|
184
188
|
"signals": [
|
|
185
|
-
{
|
|
189
|
+
{
|
|
190
|
+
"asset": "<ticker>",
|
|
191
|
+
"direction": "LONG" or "SHORT",
|
|
192
|
+
"reason": "one sentence",
|
|
193
|
+
"rotate_out": "<asset_to_cut>",
|
|
194
|
+
"leverage": <number, optional — your recommended leverage>,
|
|
195
|
+
"margin": <number, optional — $ margin amount>
|
|
196
|
+
}
|
|
186
197
|
]
|
|
187
198
|
}
|
|
188
199
|
}
|
|
@@ -193,6 +204,11 @@ actions:
|
|
|
193
204
|
decision_mode: rule
|
|
194
205
|
scanners: [sm_flip]
|
|
195
206
|
min_confidence: 1
|
|
207
|
+
params:
|
|
208
|
+
order_type: FEE_OPTIMIZED_LIMIT
|
|
209
|
+
fee_optimized_limit_options:
|
|
210
|
+
ensure_execution_as_taker: true
|
|
211
|
+
execution_timeout_seconds: 10
|
|
196
212
|
|
|
197
213
|
# ── Watchdog: emergency close on margin danger ──
|
|
198
214
|
- name: watchdog_close
|
|
@@ -200,11 +216,17 @@ actions:
|
|
|
200
216
|
decision_mode: rule
|
|
201
217
|
scanners: [watchdog]
|
|
202
218
|
min_confidence: 1
|
|
219
|
+
params:
|
|
220
|
+
order_type: MARKET
|
|
203
221
|
|
|
204
|
-
# ── DSL — trailing exit
|
|
222
|
+
# ── DSL — trailing exit
|
|
205
223
|
exit:
|
|
206
224
|
engine: dsl
|
|
207
225
|
interval_seconds: 30
|
|
226
|
+
order_type: FEE_OPTIMIZED_LIMIT
|
|
227
|
+
fee_optimized_limit_options:
|
|
228
|
+
ensure_execution_as_taker: true
|
|
229
|
+
execution_timeout_seconds: 15
|
|
208
230
|
dsl_preset:
|
|
209
231
|
phase1:
|
|
210
232
|
enabled: true
|
|
@@ -4,9 +4,7 @@ description: Watch-only strategy — logs signals, opens no positions.
|
|
|
4
4
|
|
|
5
5
|
strategy:
|
|
6
6
|
wallet: "${WALLET_ADDRESS}"
|
|
7
|
-
budget: "0"
|
|
8
7
|
slots: 1
|
|
9
|
-
margin_per_slot: 0
|
|
10
8
|
trading_risk: conservative
|
|
11
9
|
enabled: true
|
|
12
10
|
|
|
@@ -29,6 +27,10 @@ actions:
|
|
|
29
27
|
exit:
|
|
30
28
|
engine: dsl
|
|
31
29
|
interval_seconds: 60
|
|
30
|
+
order_type: FEE_OPTIMIZED_LIMIT
|
|
31
|
+
fee_optimized_limit_options:
|
|
32
|
+
ensure_execution_as_taker: true
|
|
33
|
+
execution_timeout_seconds: 30
|
|
32
34
|
dsl_preset:
|
|
33
35
|
phase1:
|
|
34
36
|
enabled: true
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# `momentum-guarded` — How it works
|
|
2
|
+
|
|
3
|
+
Companion notes for [`examples/strategies/momentum-guarded.yaml`](../momentum-guarded.yaml).
|
|
4
|
+
|
|
5
|
+
## The trading thesis
|
|
6
|
+
|
|
7
|
+
Catch **short-horizon directional breakouts** on liquid Hyperliquid perps the moment a 1h candle prints an outsized move vs. the prior close — but only when the move passes both an LLM sanity check and a real-time risk gauntlet, and only with a trailing-exit playbook strict enough to survive momentum reversals.
|
|
8
|
+
|
|
9
|
+
## Signal flow (entry side)
|
|
10
|
+
|
|
11
|
+
1. **External producer** ([`src/scanners/external/momentum/producer.mjs`](../../../src/scanners/external/momentum/producer.mjs)) runs out-of-process — pulls instruments + 1h candles from Senpi MCP, computes last-vs-prev close % move, and ingests `MOMENTUM_BREAKOUT` signals via `senpi.ingestExternalScannerData`. Re-run on a cron / `watch`.
|
|
12
|
+
2. The runtime's `external_momentum` scanner of type `external_scanner` accepts the push, validates the payload schema (`sourceMeta`, `sourceFactors`, …), and emits a `scanner:run:complete` event carrying the signals.
|
|
13
|
+
3. `momentum_entry` (an `OPEN_POSITION` action with `decision_mode: llm`) consumes the signals, runs each through a 6-step gauntlet (move magnitude ≥1.5%, direction matches sign, day notional ≥1M, max leverage ≥5, producer score ≥0.4, pick highest-score), and returns at most one trade. `min_confidence: 7` blocks lukewarm LLM verdicts.
|
|
14
|
+
4. **Risk gates** fire before the position opens. With `slots: 3` and `margin_per_slot: 300` (~$900 deployed of a $5k budget), the gauntlet of guardrails is:
|
|
15
|
+
- `daily_loss_limit_pct: 4` — closes the gate if today's PnL drops 4% of day-open account value.
|
|
16
|
+
- `drawdown_halt_pct: 20` — closes the gate at 20% PnL drawdown from peak (peak carries ~24h, not reset at midnight).
|
|
17
|
+
- `max_entries_per_day: 6` — caps churn on noisy breakout days.
|
|
18
|
+
- `max_consecutive_losses: 3` + `cooldown_minutes: 90` — three losers in a row pauses entries for 90 min so the strategy doesn't tilt.
|
|
19
|
+
- `per_asset_cooldown_minutes: 45` — no re-entry on the same ticker for 45 min after a close (avoids whipsaw fills).
|
|
20
|
+
|
|
21
|
+
Order matters: **CLOSED beats COOLDOWN beats OPEN**; the first non-OPEN gate short-circuits.
|
|
22
|
+
5. If everything passes, `FEE_OPTIMIZED_LIMIT` posts the order with a 15s execution timeout (taker fallback guaranteed).
|
|
23
|
+
|
|
24
|
+
## Position management (exit side)
|
|
25
|
+
|
|
26
|
+
Once filled, the **DSL exit engine** owns the position (`position_tracker` keeps it in sync even for manually-opened positions on the same wallet):
|
|
27
|
+
|
|
28
|
+
- **Phase 1** — fixed stop at `-2.5%` plus a `7%` retrace floor; needs `3` consecutive breaches before firing (debounce against single-tick spikes).
|
|
29
|
+
- **Phase 2** — once price advances, trailing floors lock in profit on a four-tier ladder:
|
|
30
|
+
- +6% → lock 35% of high-water
|
|
31
|
+
- +10% → lock 55%
|
|
32
|
+
- +15% → lock 70%
|
|
33
|
+
- +20% → lock 85%
|
|
34
|
+
- **Time-based cuts** — momentum that fails to develop is the silent killer:
|
|
35
|
+
- `dead_weight_cut` after 30 min flat → close.
|
|
36
|
+
- `weak_peak_cut` after 45 min if peak < +2% → close.
|
|
37
|
+
- `hard_timeout` at 2 hours → close regardless.
|
|
38
|
+
|
|
39
|
+
## What this looks like in practice
|
|
40
|
+
|
|
41
|
+
- A trader runs the producer every minute via cron.
|
|
42
|
+
- 90% of producer ticks emit zero signals; the runtime stays idle.
|
|
43
|
+
- When BTC prints a +2% 1h candle on healthy volume, the LLM accepts, the risk gauntlet checks daily PnL/drawdown/entries/cooldowns, and one slot fires a long.
|
|
44
|
+
- DSL trails the move. If BTC stalls, time-cuts close it within ~30–45 min instead of bleeding margin. If BTC runs to +12%, the +10% tier locks in 55% of the high-water, so a retrace to +5% still books profit.
|
|
45
|
+
- A bad day (3 stop-outs) trips the consecutive-loss cooldown — the runtime stops trying for 90 min and resumes fresh.
|
|
46
|
+
|
|
47
|
+
Net effect: **a small, slot-bounded, risk-gated breakout sniper** with strict trailing protection — appropriate for a $5k moderate-risk wallet that wants asymmetric upside without unsupervised drawdown.
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
name: momentum-guarded
|
|
2
|
+
version: 1.0.0
|
|
3
|
+
description: >
|
|
4
|
+
Risk-managed external momentum strategy. An out-of-process producer
|
|
5
|
+
(src/scanners/external/momentum/producer.mjs) pushes MOMENTUM_BREAKOUT
|
|
6
|
+
signals into the runtime; an LLM gauntlet decides which breakouts deserve
|
|
7
|
+
capital; the risk component gates every entry against daily loss, drawdown,
|
|
8
|
+
per-day entry count, consecutive-loss cooldown, and per-asset cooldown;
|
|
9
|
+
the DSL exit engine manages trailing exits on accepted fills.
|
|
10
|
+
|
|
11
|
+
notifications:
|
|
12
|
+
telegram_chat_id: "${TELEGRAM_CHAT_ID}"
|
|
13
|
+
|
|
14
|
+
strategy:
|
|
15
|
+
wallet: "${WALLET_ADDRESS}"
|
|
16
|
+
budget: 5000
|
|
17
|
+
slots: 3
|
|
18
|
+
margin_per_slot: 300
|
|
19
|
+
trading_risk: moderate
|
|
20
|
+
enabled: true
|
|
21
|
+
|
|
22
|
+
# ── RISK ──
|
|
23
|
+
# Real-time gates enforced on every OPEN_POSITION attempt. Any non-OPEN gate
|
|
24
|
+
# short-circuits and skips the entry. See docs/risk-component.md.
|
|
25
|
+
risk:
|
|
26
|
+
data_retention_hours: 72
|
|
27
|
+
|
|
28
|
+
guard_rails:
|
|
29
|
+
# Daily loss halt — stop trading if daily PnL drops > 4% of day-open account value.
|
|
30
|
+
daily_loss_limit_pct: 4
|
|
31
|
+
|
|
32
|
+
# Cap entries per UTC day so a noisy producer day can't churn the wallet.
|
|
33
|
+
max_entries_per_day: 6
|
|
34
|
+
bypass_max_entries_per_day_on_profit: false
|
|
35
|
+
|
|
36
|
+
# Consecutive-loss cooldown — three losers in a row pauses entries for 90 min.
|
|
37
|
+
max_consecutive_losses: 3
|
|
38
|
+
cooldown_minutes: 90
|
|
39
|
+
|
|
40
|
+
# Drawdown halt — 20% PnL drawdown from peak halts entries; peak carries ~24h.
|
|
41
|
+
drawdown_halt_pct: 20
|
|
42
|
+
drawdown_reset_on_day_rollover: false
|
|
43
|
+
|
|
44
|
+
# Per-asset cooldown — no re-entry on the same asset for 45 min after a close.
|
|
45
|
+
per_asset_cooldown_minutes: 45
|
|
46
|
+
|
|
47
|
+
# ── SCANNERS ──
|
|
48
|
+
scanners:
|
|
49
|
+
# Onchain position tracker — emits position lifecycle events into the DSL exit engine.
|
|
50
|
+
- name: position_tracker
|
|
51
|
+
type: position_tracker
|
|
52
|
+
interval: 10s
|
|
53
|
+
|
|
54
|
+
# External producer feed — schema for inbound MOMENTUM_BREAKOUT signals
|
|
55
|
+
# delivered via senpi.ingestExternalScannerData.
|
|
56
|
+
- name: external_momentum
|
|
57
|
+
type: external_scanner
|
|
58
|
+
outputs:
|
|
59
|
+
signals: true
|
|
60
|
+
context: false
|
|
61
|
+
config:
|
|
62
|
+
fields:
|
|
63
|
+
sourceScannerId: { type: string, required: true }
|
|
64
|
+
sourceSignalType: { type: string, required: true }
|
|
65
|
+
sourceTimestamp: { type: number, required: true }
|
|
66
|
+
sourceFactors: { type: object, required: true }
|
|
67
|
+
sourceMeta: { type: object, required: true }
|
|
68
|
+
|
|
69
|
+
# ── ACTIONS ──
|
|
70
|
+
actions:
|
|
71
|
+
# Position lifecycle tracking — feeds the DSL exit engine.
|
|
72
|
+
- name: position_tracker_action
|
|
73
|
+
action_type: POSITION_TRACKER
|
|
74
|
+
decision_mode: rule
|
|
75
|
+
scanners: [position_tracker]
|
|
76
|
+
|
|
77
|
+
# Entry: LLM gauntlet on momentum breakout signals.
|
|
78
|
+
- name: momentum_entry
|
|
79
|
+
action_type: OPEN_POSITION
|
|
80
|
+
decision_mode: llm
|
|
81
|
+
decision_model: claude-sonnet-4-20250514
|
|
82
|
+
scanners: [external_momentum]
|
|
83
|
+
min_confidence: 7
|
|
84
|
+
params:
|
|
85
|
+
order_type: FEE_OPTIMIZED_LIMIT
|
|
86
|
+
fee_optimized_limit_options:
|
|
87
|
+
ensure_execution_as_taker: true
|
|
88
|
+
execution_timeout_seconds: 15
|
|
89
|
+
context:
|
|
90
|
+
- type: signal
|
|
91
|
+
scanner: external_momentum
|
|
92
|
+
decision_prompt: |
|
|
93
|
+
You are a trade-decisioning evaluator. Given a MOMENTUM_BREAKOUT
|
|
94
|
+
signal pushed by the external momentum producer, decide whether to
|
|
95
|
+
open a position on it or skip.
|
|
96
|
+
|
|
97
|
+
A MOMENTUM_BREAKOUT fires when an asset's latest closed candle moves
|
|
98
|
+
by at least the producer's threshold vs. the previous close on the
|
|
99
|
+
signal's timeframe — i.e. a short-term directional breakout in price.
|
|
100
|
+
`meta.movePct` carries the signed % change (positive = LONG bias,
|
|
101
|
+
negative = SHORT bias); `score` (0..1) scales with the move's
|
|
102
|
+
magnitude; `meta.dayNtlVlm` and `meta.maxLeverage` describe the
|
|
103
|
+
instrument's liquidity and leverage headroom.
|
|
104
|
+
|
|
105
|
+
SIGNAL DATA:
|
|
106
|
+
{{signal_external_momentum}}
|
|
107
|
+
|
|
108
|
+
═══ GAUNTLET ═══
|
|
109
|
+
1. movePct magnitude — require |movePct| >= 1.5; reject sub-threshold noise.
|
|
110
|
+
2. Direction sanity — LONG only if movePct > 0, SHORT only if movePct < 0.
|
|
111
|
+
3. Liquidity — meta.dayNtlVlm must be >= 1_000_000.
|
|
112
|
+
4. Leverage — meta.maxLeverage must be >= 5; skip otherwise.
|
|
113
|
+
5. Score — use the producer score (0..1) as a proxy for strength; require >= 0.4.
|
|
114
|
+
6. One signal at a time — pick the highest-score eligible signal; skip the rest.
|
|
115
|
+
|
|
116
|
+
Respond with a single JSON object:
|
|
117
|
+
{
|
|
118
|
+
"execute": true|false,
|
|
119
|
+
"actionType": "OPEN_POSITION",
|
|
120
|
+
"confidence": 1-10,
|
|
121
|
+
"reasoning": "one sentence",
|
|
122
|
+
"payload": {
|
|
123
|
+
"signals": [
|
|
124
|
+
{ "asset": "<ticker>", "direction": "LONG"|"SHORT", "reason": "one sentence" }
|
|
125
|
+
]
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
# ── EXIT (DSL) ──
|
|
130
|
+
# Trailing stop-loss tuned for short-horizon momentum entries.
|
|
131
|
+
# Time-based cuts catch stalled trades that never deliver follow-through.
|
|
132
|
+
exit:
|
|
133
|
+
engine: dsl
|
|
134
|
+
interval_seconds: 30
|
|
135
|
+
order_type: FEE_OPTIMIZED_LIMIT
|
|
136
|
+
fee_optimized_limit_options:
|
|
137
|
+
ensure_execution_as_taker: true
|
|
138
|
+
execution_timeout_seconds: 15
|
|
139
|
+
dsl_preset:
|
|
140
|
+
hard_timeout:
|
|
141
|
+
enabled: true
|
|
142
|
+
interval_in_minutes: 120
|
|
143
|
+
weak_peak_cut:
|
|
144
|
+
enabled: true
|
|
145
|
+
interval_in_minutes: 45
|
|
146
|
+
min_value: 2
|
|
147
|
+
dead_weight_cut:
|
|
148
|
+
enabled: true
|
|
149
|
+
interval_in_minutes: 30
|
|
150
|
+
phase1:
|
|
151
|
+
enabled: true
|
|
152
|
+
max_loss_pct: 2.5
|
|
153
|
+
retrace_threshold: 7
|
|
154
|
+
consecutive_breaches_required: 3
|
|
155
|
+
phase2:
|
|
156
|
+
enabled: true
|
|
157
|
+
tiers:
|
|
158
|
+
- { trigger_pct: 6, lock_hw_pct: 35 }
|
|
159
|
+
- { trigger_pct: 10, lock_hw_pct: 55 }
|
|
160
|
+
- { trigger_pct: 15, lock_hw_pct: 70 }
|
|
161
|
+
- { trigger_pct: 20, lock_hw_pct: 85 }
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# Risk showcase — every risk guardrail field annotated for reference.
|
|
2
|
+
# Use as a copy-paste reference when configuring risk management.
|
|
3
|
+
name: risk-showcase
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
description: >
|
|
6
|
+
Annotated risk guardrails config reference.
|
|
7
|
+
Uses position_tracker scanner with DSL exit engine.
|
|
8
|
+
Lists explicit example values for each field (not implicit runtime defaults).
|
|
9
|
+
|
|
10
|
+
notifications:
|
|
11
|
+
telegram_chat_id: "${TELEGRAM_CHAT_ID}"
|
|
12
|
+
|
|
13
|
+
strategy:
|
|
14
|
+
wallet: "${WALLET_ADDRESS}"
|
|
15
|
+
budget: 10000
|
|
16
|
+
slots: 3
|
|
17
|
+
margin_per_slot: 250
|
|
18
|
+
trading_risk: moderate
|
|
19
|
+
enabled: true
|
|
20
|
+
|
|
21
|
+
# ── RISK ──
|
|
22
|
+
# Optional. Without this block, all gates are OPEN (no risk management).
|
|
23
|
+
risk:
|
|
24
|
+
# How long to keep audit log files (JSONL + daily snapshots), in hours.
|
|
25
|
+
# Range: 1–168 (1 hour to 7 days). Default: 48.
|
|
26
|
+
data_retention_hours: 48
|
|
27
|
+
|
|
28
|
+
guard_rails:
|
|
29
|
+
# ── Daily Loss Halt ──
|
|
30
|
+
# Gate CLOSED when daily trading PnL drop exceeds this % of account value at day open.
|
|
31
|
+
# Uses Hyperliquid portfolio PnL (realized + unrealized + funding, excludes deposits/withdrawals).
|
|
32
|
+
# Resets at UTC midnight.
|
|
33
|
+
daily_loss_limit_pct: 5 # 5% of account value at day open
|
|
34
|
+
|
|
35
|
+
# ── Max Entries Per Day ──
|
|
36
|
+
# Gate CLOSED when position entries today >= max_entries_per_day.
|
|
37
|
+
# Counts open positions opened today (startTime) + closed trades opened today (openTime).
|
|
38
|
+
# Resets at UTC midnight.
|
|
39
|
+
max_entries_per_day: 8
|
|
40
|
+
# When true, max_entries_per_day limit is bypassed if daily realized PnL > 0.
|
|
41
|
+
# Default: false (limit enforced strictly unless explicitly opted in).
|
|
42
|
+
# Not yet evaluated — reserved for future use.
|
|
43
|
+
bypass_max_entries_per_day_on_profit: false
|
|
44
|
+
|
|
45
|
+
# ── Consecutive Loss Cooldown ──
|
|
46
|
+
# Gate COOLDOWN when the last N closed trades all have negative realizedPnl.
|
|
47
|
+
# Stateless: derived from trade history API on every tick, no persisted streak.
|
|
48
|
+
# Streak carries across days. Cooldown window starts from the most recent
|
|
49
|
+
# loss's close time and expires cooldown_minutes later.
|
|
50
|
+
max_consecutive_losses: 3
|
|
51
|
+
cooldown_minutes: 60
|
|
52
|
+
|
|
53
|
+
# ── Drawdown Halt ──
|
|
54
|
+
# Gate CLOSED when PnL drawdown from peak >= drawdown_halt_pct %.
|
|
55
|
+
# PnL-based: immune to deposits and withdrawals.
|
|
56
|
+
# Drawdown = (peak_pnl - current_pnl) / account_value_at_day_open * 100.
|
|
57
|
+
drawdown_halt_pct: 30 # 30% PnL drawdown from peak triggers halt
|
|
58
|
+
# When true, PnL peak resets at UTC midnight (intraday drawdown only).
|
|
59
|
+
# When false (default), PnL peak carries from prior ~24h (perpDay window).
|
|
60
|
+
drawdown_reset_on_day_rollover: false
|
|
61
|
+
|
|
62
|
+
# ── Per-Asset Cooldown ──
|
|
63
|
+
# Gate COOLDOWN for a specific asset when it was closed within the last N minutes.
|
|
64
|
+
# Checked on each entry attempt. Only evaluated when all other gates are OPEN.
|
|
65
|
+
# Minimum: 5 minutes (backend latency floor).
|
|
66
|
+
per_asset_cooldown_minutes: 30 # 30 min cooldown after closing any asset
|
|
67
|
+
|
|
68
|
+
# ── SCANNERS ──
|
|
69
|
+
scanners:
|
|
70
|
+
- name: position_tracker
|
|
71
|
+
type: position_tracker
|
|
72
|
+
interval: 10s
|
|
73
|
+
|
|
74
|
+
# ── ACTIONS ──
|
|
75
|
+
actions:
|
|
76
|
+
- name: position_tracker_action
|
|
77
|
+
action_type: POSITION_TRACKER
|
|
78
|
+
decision_mode: rule
|
|
79
|
+
scanners: [position_tracker]
|
|
80
|
+
|
|
81
|
+
# ── EXIT ──
|
|
82
|
+
exit:
|
|
83
|
+
engine: dsl
|
|
84
|
+
interval_seconds: 30
|
|
85
|
+
dsl_preset:
|
|
86
|
+
phase1:
|
|
87
|
+
max_loss_pct: 5.0
|
|
88
|
+
retrace_threshold: 10
|
|
89
|
+
consecutive_breaches_required: 2
|
|
90
|
+
phase2:
|
|
91
|
+
tiers:
|
|
92
|
+
- { trigger_pct: 10, lock_hw_pct: 50 }
|
|
93
|
+
- { trigger_pct: 20, lock_hw_pct: 70 }
|
|
@@ -4,9 +4,8 @@ description: Moderate — candle-based breakouts via prescreener + momentum.
|
|
|
4
4
|
|
|
5
5
|
strategy:
|
|
6
6
|
wallet: "${WALLET_ADDRESS}"
|
|
7
|
-
budget: 2000
|
|
8
7
|
slots: 4
|
|
9
|
-
|
|
8
|
+
margin_pct: 10
|
|
10
9
|
trading_risk: moderate
|
|
11
10
|
enabled: true
|
|
12
11
|
|
|
@@ -37,13 +36,22 @@ actions:
|
|
|
37
36
|
decision_model: claude-sonnet-4-20250514
|
|
38
37
|
scanners: [momentum]
|
|
39
38
|
min_confidence: 6
|
|
39
|
+
params:
|
|
40
|
+
order_type: FEE_OPTIMIZED_LIMIT
|
|
41
|
+
fee_optimized_limit_options:
|
|
42
|
+
ensure_execution_as_taker: true
|
|
43
|
+
execution_timeout_seconds: 15
|
|
40
44
|
context: [signal]
|
|
41
45
|
decision_prompt: |
|
|
42
|
-
Evaluate the momentum breakout signal. Reply with JSON: {"execute": true|false, "actionType": "OPEN_POSITION", "confidence": 1-10, "reasoning": "...", "payload": {"signals": [{"asset": "SYMBOL", "direction": "LONG"|"SHORT", "reason": "..."}]}}.
|
|
46
|
+
Evaluate the momentum breakout signal. Reply with JSON: {"execute": true|false, "actionType": "OPEN_POSITION", "confidence": 1-10, "reasoning": "...", "payload": {"signals": [{"asset": "SYMBOL", "direction": "LONG"|"SHORT", "reason": "...", "leverage": <optional number>, "margin": <optional $ amount>}]}}.
|
|
43
47
|
|
|
44
48
|
exit:
|
|
45
49
|
engine: dsl
|
|
46
50
|
interval_seconds: 30
|
|
51
|
+
order_type: FEE_OPTIMIZED_LIMIT
|
|
52
|
+
fee_optimized_limit_options:
|
|
53
|
+
ensure_execution_as_taker: true
|
|
54
|
+
execution_timeout_seconds: 15
|
|
47
55
|
dsl_preset:
|
|
48
56
|
phase1:
|
|
49
57
|
enabled: true
|
|
@@ -4,9 +4,8 @@ description: Aggressive — early entry on FIRST_JUMP from emerging_movers.
|
|
|
4
4
|
|
|
5
5
|
strategy:
|
|
6
6
|
wallet: "${WALLET_ADDRESS}"
|
|
7
|
-
budget: 1000
|
|
8
7
|
slots: 3
|
|
9
|
-
|
|
8
|
+
margin_pct: 15
|
|
10
9
|
trading_risk: aggressive
|
|
11
10
|
enabled: true
|
|
12
11
|
|
|
@@ -32,13 +31,22 @@ actions:
|
|
|
32
31
|
decision_model: claude-sonnet-4-20250514
|
|
33
32
|
scanners: [emerging_movers]
|
|
34
33
|
min_confidence: 6
|
|
34
|
+
params:
|
|
35
|
+
order_type: FEE_OPTIMIZED_LIMIT
|
|
36
|
+
fee_optimized_limit_options:
|
|
37
|
+
ensure_execution_as_taker: true
|
|
38
|
+
execution_timeout_seconds: 10
|
|
35
39
|
context: [signal]
|
|
36
40
|
decision_prompt: |
|
|
37
|
-
Evaluate the signal. Reply with JSON: {"execute": true|false, "actionType": "OPEN_POSITION", "confidence": 1-10, "reasoning": "...", "payload": {"signals": [{"asset": "SYMBOL", "direction": "LONG"|"SHORT", "reason": "..."}]}}.
|
|
41
|
+
Evaluate the signal. Reply with JSON: {"execute": true|false, "actionType": "OPEN_POSITION", "confidence": 1-10, "reasoning": "...", "payload": {"signals": [{"asset": "SYMBOL", "direction": "LONG"|"SHORT", "reason": "...", "leverage": <optional number>, "margin": <optional $ amount>}]}}.
|
|
38
42
|
|
|
39
43
|
exit:
|
|
40
44
|
engine: dsl
|
|
41
45
|
interval_seconds: 30
|
|
46
|
+
order_type: FEE_OPTIMIZED_LIMIT
|
|
47
|
+
fee_optimized_limit_options:
|
|
48
|
+
ensure_execution_as_taker: true
|
|
49
|
+
execution_timeout_seconds: 10
|
|
42
50
|
dsl_preset:
|
|
43
51
|
hard_timeout:
|
|
44
52
|
enabled: true
|