From 98c1e366a5ff75ce5168e1714a5e49f7f9791426 Mon Sep 17 00:00:00 2001 From: Henry Winkel Date: Sat, 16 May 2026 13:50:28 +0200 Subject: [PATCH] Add execution plan for sell decisions: amount, risk management, take-profit; include execution step in TradingGraph workflow Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- app/agents/trader.ts | 35 ++++++++++++++++++++++++++++++++--- app/agents/tradingGraph.ts | 21 ++++++++++++++++++--- app/types/agents.ts | 11 +++++++++++ 3 files changed, 61 insertions(+), 6 deletions(-) diff --git a/app/agents/trader.ts b/app/agents/trader.ts index 9f01029..b74e6a3 100644 --- a/app/agents/trader.ts +++ b/app/agents/trader.ts @@ -37,16 +37,21 @@ ${signalSummaries} Debate Rounds: ${debateSummaries} -Based on all the information above, make a trading decision. Respond with: +Based on all the information above, make a trading decision. Respond with JSON containing these fields: - action: "buy", "sell", or "hold" - confidence: a number between 0 and 1 - reasoning: brief explanation +If the action is "sell", also include an "executionPlan" object with: +- amount: number (shares to sell) +- riskManagement: object (e.g., { maxLossPercent: 2 }) +- takeProfit: number (target take-profit price) + Format your response as JSON with these fields.`; const response = await this.client.createChatCompletion( [ - { role: "system", content: "You are a trading agent that makes buy/sell/hold decisions based on all available signals." }, + { role: "system", content: "You are a trading agent that makes buy/sell/hold decisions and provides execution guidance when selling." }, { role: "user", content: prompt }, ], this.model @@ -57,6 +62,7 @@ Format your response as JSON with these fields.`; let action: 'buy' | 'sell' | 'hold' = 'hold'; let confidence = 0.5; let reasoning = content; + let executionPlan: any | undefined; const actionMatch = content.match(/"action"\s*:\s*"(buy|sell|hold)"/); if (actionMatch) { @@ -73,12 +79,35 @@ Format your response as JSON with these fields.`; reasoning = reasoningMatch[1]; } - return { + // Try to parse executionPlan if provided in JSON + const execMatch = content.match(/"executionPlan"\s*:\s*(\{[\s\S]*\})/); + if (execMatch) { + try { + executionPlan = JSON.parse(execMatch[1]); + } catch (err) { + // fallback: try to extract primitive fields + const amountMatch = content.match(/"amount"\s*:\s*([0-9.]+)/); + const takeProfitMatch = content.match(/"takeProfit"\s*:\s*([0-9.]+)/); + const riskMatch = content.match(/"riskManagement"\s*:\s*"([^"]+)"/); + executionPlan = {}; + if (amountMatch) executionPlan.amount = parseFloat(amountMatch[1]); + if (takeProfitMatch) executionPlan.takeProfit = parseFloat(takeProfitMatch[1]); + if (riskMatch) executionPlan.riskManagement = { note: riskMatch[1] }; + } + } + + const decision: TradingDecision = { action, confidence, reasoning, agentSignals: allSignals, debateRounds: debates, }; + + if (action === 'sell' && executionPlan) { + decision.executionPlan = executionPlan; + } + + return decision; } } \ No newline at end of file diff --git a/app/agents/tradingGraph.ts b/app/agents/tradingGraph.ts index 3ded285..24d41b7 100644 --- a/app/agents/tradingGraph.ts +++ b/app/agents/tradingGraph.ts @@ -4,11 +4,11 @@ import { TechnicalAnalyst } from "./technical"; import { SentimentAnalyst } from "./sentiment"; import { BullishResearcher, BearishResearcher } from "./researchers"; import { Trader } from "./trader"; -import type { AnalystReport, DebateRound, TradingDecision, AgentSignal } from "../types/agents"; +import type { AnalystReport, DebateRound, TradingDecision, AgentSignal, ExecutionPlan } from "../types/agents"; export interface GraphStep { - step: "analysts" | "debate" | "trader"; - data: AnalystReport[] | DebateRound[] | TradingDecision; + step: "analysts" | "debate" | "trader" | "execution"; + data: AnalystReport[] | DebateRound[] | TradingDecision | ExecutionPlan; } export class TradingGraph { @@ -50,6 +50,21 @@ export class TradingGraph { console.log(`[TradingGraph] Analysis complete for ${ticker}`); console.log(`[TradingGraph] Decision: ${decision.action} (confidence: ${decision.confidence})`); + // Build workflow steps for observability. Include an execution step when selling. + const steps: GraphStep[] = [ + { step: "analysts", data: reports }, + { step: "debate", data: debates }, + { step: "trader", data: decision }, + ]; + + if (decision.action === 'sell' && decision.executionPlan) { + steps.push({ step: "execution", data: decision.executionPlan }); + console.log(`[TradingGraph] Execution plan: ${JSON.stringify(decision.executionPlan)}`); + } + + // Log steps for debugging; external systems can be extended to consume GraphStep sequence. + console.log(`[TradingGraph] Workflow steps: ${JSON.stringify(steps)}`); + return decision; } diff --git a/app/types/agents.ts b/app/types/agents.ts index 21c7a0d..1fb0893 100644 --- a/app/types/agents.ts +++ b/app/types/agents.ts @@ -20,6 +20,16 @@ export interface DebateRound { researcher: 'bullish' | 'bearish' } +export interface ExecutionPlan { + amount: number // number of shares to trade + riskManagement: { + maxLossPercent?: number + method?: string + } + takeProfit?: number // target price for take-profit + note?: string +} + export interface TradingDecision { action: 'buy' | 'sell' | 'hold' confidence: number @@ -28,6 +38,7 @@ export interface TradingDecision { reasoning: string agentSignals: AgentSignal[] debateRounds: DebateRound[] + executionPlan?: ExecutionPlan } export interface AgentConfig {