import { describe, it, expect, beforeEach, afterEach } from "vitest"; import { enrichExecutionPlan } from "../execution"; describe("enrichExecutionPlan edge cases", () => { beforeEach(() => { process.env.DEFAULT_ACCOUNT_EQUITY = "10000"; }); afterEach(() => { delete process.env.DEFAULT_ACCOUNT_EQUITY; }); it("handles very small/zero ATR (flat prices) without crashing and uses percent fallback", () => { const decision: any = { action: "buy" }; const input = { technicalData: { prices: [100, 100, 100] } }; const out = enrichExecutionPlan(decision, input); expect(out.executionPlan).toBeDefined(); // ATR ~ 0, so stopDistance should fall back to percent-based (1% of entry = 1) expect(out.executionPlan.stopLoss).toBeCloseTo(99, 2); // entry 100 + rr*stopDistance (2*1) => 102 expect(out.executionPlan.takeProfit).toBeCloseTo(102, 2); expect(out.executionPlan.amount).toBeGreaterThanOrEqual(1); }); it("honors percent-based riskManagement from LLM (0.5%) and computes amount accordingly", () => { const decision: any = { action: "buy", executionPlan: { riskManagement: { maxLossPercent: 0.5 } } }; const input = { technicalData: { prices: [200, 202] } }; const out = enrichExecutionPlan(decision, input); expect(out.executionPlan).toBeDefined(); expect(out.executionPlan.riskManagement).toBeDefined(); expect(out.executionPlan.riskManagement.maxLossPercent).toBeCloseTo(0.5, 6); // entryPrice = 202, rr/default: atr ~2, stopDistance = max(2*1.5=3, 202*0.005=1.01) => 3 // riskAmount = 10000 * 0.005 = 50 -> shares = floor(50/3) = 16 expect(out.executionPlan.amount).toBe(16); }); it("handles missing price data by producing a finite amount and no absolute stops", () => { const decision: any = { action: "buy" }; const input = { technicalData: { prices: [] } }; const out = enrichExecutionPlan(decision, input); expect(out.executionPlan).toBeDefined(); // No entry price -> cannot compute absolute stopLoss/takeProfit expect(out.executionPlan.stopLoss).toBeUndefined(); expect(out.executionPlan.takeProfit).toBeUndefined(); // Amount should still be computed (uses small fallback stopDistance 0.0001) -> large but finite expect(typeof out.executionPlan.amount).toBe("number"); expect(Number.isFinite(out.executionPlan.amount)).toBe(true); expect(out.executionPlan.amount).toBeGreaterThanOrEqual(1); }); });