@ebowwa/daemons 0.5.0
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 +264 -0
- package/dist/bin/discord-cli.js +124118 -0
- package/dist/bin/manager.js +143 -0
- package/dist/bin/telegram-cli.js +124114 -0
- package/dist/index.js +125340 -0
- package/package.json +94 -0
- package/src/agent.ts +111 -0
- package/src/channels/base.ts +573 -0
- package/src/channels/discord.ts +306 -0
- package/src/channels/index.ts +169 -0
- package/src/channels/telegram.ts +315 -0
- package/src/daemon.ts +534 -0
- package/src/hooks.ts +97 -0
- package/src/index.ts +111 -0
- package/src/memory.ts +369 -0
- package/src/skills/coding/commit.ts +202 -0
- package/src/skills/coding/execute-subtask.ts +136 -0
- package/src/skills/coding/fix-issues.ts +126 -0
- package/src/skills/coding/index.ts +26 -0
- package/src/skills/coding/plan-task.ts +158 -0
- package/src/skills/coding/quality-check.ts +155 -0
- package/src/skills/index.ts +65 -0
- package/src/skills/registry.ts +380 -0
- package/src/skills/shared/index.ts +21 -0
- package/src/skills/shared/reflect.ts +156 -0
- package/src/skills/shared/review.ts +201 -0
- package/src/skills/shared/trajectory.ts +319 -0
- package/src/skills/trading/analyze-market.ts +144 -0
- package/src/skills/trading/check-risk.ts +176 -0
- package/src/skills/trading/execute-trade.ts +185 -0
- package/src/skills/trading/generate-signal.ts +160 -0
- package/src/skills/trading/index.ts +26 -0
- package/src/skills/trading/monitor-position.ts +179 -0
- package/src/skills/types.ts +235 -0
- package/src/skills/workflows.ts +340 -0
- package/src/state.ts +77 -0
- package/src/tools.ts +134 -0
- package/src/types.ts +314 -0
- package/src/workflow.ts +341 -0
- package/src/workflows/coding.ts +580 -0
- package/src/workflows/index.ts +61 -0
- package/src/workflows/trading.ts +608 -0
|
@@ -0,0 +1,608 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GLM Daemon - Trading Workflow
|
|
3
|
+
*
|
|
4
|
+
* Trading workflow for automated market analysis and execution.
|
|
5
|
+
* Phases: analyzing → signaling → risk_checking → executing → monitoring → complete
|
|
6
|
+
*
|
|
7
|
+
* Key differences from coding workflow:
|
|
8
|
+
* - No git state (trading doesn't need commits/PRs)
|
|
9
|
+
* - Focus on market signals and risk management
|
|
10
|
+
* - Real-time monitoring loops
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import {
|
|
14
|
+
BaseWorkflow,
|
|
15
|
+
type GLMWorkflowConfig,
|
|
16
|
+
type GLMWorkflowContext,
|
|
17
|
+
type GLMWorkflowPhaseResult,
|
|
18
|
+
type GLMWorkflowPhase,
|
|
19
|
+
type GLMWorkflowTransition,
|
|
20
|
+
} from "../workflow.js";
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Trading workflow phases
|
|
24
|
+
*/
|
|
25
|
+
export type TradingPhase =
|
|
26
|
+
| "analyzing"
|
|
27
|
+
| "signaling"
|
|
28
|
+
| "risk_checking"
|
|
29
|
+
| "executing"
|
|
30
|
+
| "monitoring"
|
|
31
|
+
| "reflecting"
|
|
32
|
+
| "complete";
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Trading workflow phases definition
|
|
36
|
+
*/
|
|
37
|
+
export const TRADING_PHASES: GLMWorkflowPhase<TradingPhase>[] = [
|
|
38
|
+
{
|
|
39
|
+
name: "analyzing",
|
|
40
|
+
label: "Analyzing",
|
|
41
|
+
description: "Analyze market conditions and identify opportunities",
|
|
42
|
+
skippable: false,
|
|
43
|
+
timeout: 120000, // 2 minutes for analysis
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
name: "signaling",
|
|
47
|
+
label: "Signaling",
|
|
48
|
+
description: "Generate trading signals based on analysis",
|
|
49
|
+
skippable: false,
|
|
50
|
+
timeout: 60000,
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: "risk_checking",
|
|
54
|
+
label: "Risk Checking",
|
|
55
|
+
description: "Evaluate risk and validate signal before execution",
|
|
56
|
+
skippable: false,
|
|
57
|
+
timeout: 30000,
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
name: "executing",
|
|
61
|
+
label: "Executing",
|
|
62
|
+
description: "Execute trades according to validated signals",
|
|
63
|
+
skippable: false,
|
|
64
|
+
timeout: 30000, // Quick execution needed
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
name: "monitoring",
|
|
68
|
+
label: "Monitoring",
|
|
69
|
+
description: "Monitor open positions and market conditions",
|
|
70
|
+
skippable: false,
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
name: "reflecting",
|
|
74
|
+
label: "Reflecting",
|
|
75
|
+
description: "Review performance and lessons learned",
|
|
76
|
+
skippable: true,
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
name: "complete",
|
|
80
|
+
label: "Complete",
|
|
81
|
+
description: "Trading session finished",
|
|
82
|
+
skippable: false,
|
|
83
|
+
},
|
|
84
|
+
];
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Trading workflow transition rules
|
|
88
|
+
*/
|
|
89
|
+
export const TRADING_TRANSITIONS: GLMWorkflowTransition<TradingPhase>[] = [
|
|
90
|
+
// Analyzing -> Signaling (always)
|
|
91
|
+
{
|
|
92
|
+
from: "analyzing",
|
|
93
|
+
to: "signaling",
|
|
94
|
+
priority: 100,
|
|
95
|
+
},
|
|
96
|
+
// Signaling -> Risk Checking (always)
|
|
97
|
+
{
|
|
98
|
+
from: "signaling",
|
|
99
|
+
to: "risk_checking",
|
|
100
|
+
priority: 100,
|
|
101
|
+
},
|
|
102
|
+
// Risk Checking -> Executing (if risk approved)
|
|
103
|
+
{
|
|
104
|
+
from: "risk_checking",
|
|
105
|
+
to: "executing",
|
|
106
|
+
priority: 100,
|
|
107
|
+
condition: async (ctx) => {
|
|
108
|
+
return ctx.custom.riskApproved === true;
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
// Risk Checking -> Analyzing (if risk rejected - re-analyze)
|
|
112
|
+
{
|
|
113
|
+
from: "risk_checking",
|
|
114
|
+
to: "analyzing",
|
|
115
|
+
priority: 90,
|
|
116
|
+
condition: async (ctx) => {
|
|
117
|
+
return ctx.custom.riskApproved === false;
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
// Executing -> Monitoring (always)
|
|
121
|
+
{
|
|
122
|
+
from: "executing",
|
|
123
|
+
to: "monitoring",
|
|
124
|
+
priority: 100,
|
|
125
|
+
},
|
|
126
|
+
// Monitoring -> Complete (if target reached or stop loss)
|
|
127
|
+
{
|
|
128
|
+
from: "monitoring",
|
|
129
|
+
to: "complete",
|
|
130
|
+
priority: 100,
|
|
131
|
+
condition: async (ctx) => {
|
|
132
|
+
return ctx.custom.targetReached === true || ctx.custom.stopLoss === true;
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
// Monitoring -> Analyzing (if position closed - look for new opportunities)
|
|
136
|
+
{
|
|
137
|
+
from: "monitoring",
|
|
138
|
+
to: "analyzing",
|
|
139
|
+
priority: 90,
|
|
140
|
+
condition: async (ctx) => {
|
|
141
|
+
return ctx.custom.positionClosed === true;
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
// Monitoring -> Reflecting (periodic checkpoint)
|
|
145
|
+
{
|
|
146
|
+
from: "monitoring",
|
|
147
|
+
to: "reflecting",
|
|
148
|
+
priority: 80,
|
|
149
|
+
condition: async (ctx) => {
|
|
150
|
+
// Reflect every N iterations
|
|
151
|
+
return ctx.state.iteration % 10 === 0;
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
// Monitoring -> Monitoring (continue monitoring)
|
|
155
|
+
{
|
|
156
|
+
from: "monitoring",
|
|
157
|
+
to: "monitoring",
|
|
158
|
+
priority: 60,
|
|
159
|
+
},
|
|
160
|
+
// Reflecting -> Monitoring
|
|
161
|
+
{
|
|
162
|
+
from: "reflecting",
|
|
163
|
+
to: "monitoring",
|
|
164
|
+
priority: 100,
|
|
165
|
+
},
|
|
166
|
+
];
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Trading workflow configuration
|
|
170
|
+
*/
|
|
171
|
+
export const TRADING_WORKFLOW_CONFIG: GLMWorkflowConfig<TradingPhase> = {
|
|
172
|
+
id: "trading",
|
|
173
|
+
name: "Trading Workflow",
|
|
174
|
+
description: "Trading workflow for automated market analysis and execution",
|
|
175
|
+
phases: TRADING_PHASES,
|
|
176
|
+
initialPhase: "analyzing",
|
|
177
|
+
terminalPhases: ["complete"],
|
|
178
|
+
transitions: TRADING_TRANSITIONS,
|
|
179
|
+
defaultOrder: ["analyzing", "signaling", "risk_checking", "executing", "monitoring", "complete"],
|
|
180
|
+
reflectionPhase: "reflecting",
|
|
181
|
+
systemPromptExtensions: `You are a trading assistant.
|
|
182
|
+
Follow risk management rules strictly.
|
|
183
|
+
Never exceed position size limits.
|
|
184
|
+
Always use stop-loss orders.
|
|
185
|
+
No git operations are needed - focus on market execution.`,
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Trading Workflow implementation
|
|
190
|
+
*/
|
|
191
|
+
export class TradingWorkflow extends BaseWorkflow<TradingPhase> {
|
|
192
|
+
constructor() {
|
|
193
|
+
super(TRADING_WORKFLOW_CONFIG);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Build system prompt for trading context
|
|
198
|
+
*/
|
|
199
|
+
buildSystemPrompt(context: GLMWorkflowContext): string {
|
|
200
|
+
const basePrompt = super.buildSystemPrompt(context);
|
|
201
|
+
|
|
202
|
+
// Add trading-specific context
|
|
203
|
+
const tradingContext = `
|
|
204
|
+
Trading Context:
|
|
205
|
+
- Risk Level: ${context.custom.riskLevel || "medium"}
|
|
206
|
+
- Position Limit: ${context.custom.positionLimit || 1}
|
|
207
|
+
- Current P&L: ${context.custom.currentPnL || "N/A"}
|
|
208
|
+
`;
|
|
209
|
+
|
|
210
|
+
return basePrompt + tradingContext;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Execute a trading phase
|
|
215
|
+
*/
|
|
216
|
+
async executePhase(phase: string, context: GLMWorkflowContext): Promise<GLMWorkflowPhaseResult> {
|
|
217
|
+
switch (phase as TradingPhase) {
|
|
218
|
+
case "analyzing":
|
|
219
|
+
return this.phaseAnalyzing(context);
|
|
220
|
+
case "signaling":
|
|
221
|
+
return this.phaseSignaling(context);
|
|
222
|
+
case "risk_checking":
|
|
223
|
+
return this.phaseRiskChecking(context);
|
|
224
|
+
case "executing":
|
|
225
|
+
return this.phaseExecuting(context);
|
|
226
|
+
case "monitoring":
|
|
227
|
+
return this.phaseMonitoring(context);
|
|
228
|
+
case "reflecting":
|
|
229
|
+
return this.phaseReflecting(context);
|
|
230
|
+
case "complete":
|
|
231
|
+
return this.phaseComplete(context);
|
|
232
|
+
default:
|
|
233
|
+
throw new Error(`Unknown phase: ${phase}`);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Analyzing phase - analyze market conditions
|
|
239
|
+
*/
|
|
240
|
+
private async phaseAnalyzing(context: GLMWorkflowContext): Promise<GLMWorkflowPhaseResult> {
|
|
241
|
+
console.log("[TradingWorkflow] Phase: Analyzing market conditions");
|
|
242
|
+
|
|
243
|
+
const prompt = `Analyze current market conditions for trading.
|
|
244
|
+
|
|
245
|
+
Task: ${context.state.prompt}
|
|
246
|
+
|
|
247
|
+
Consider:
|
|
248
|
+
- Price action and trends
|
|
249
|
+
- Volume analysis
|
|
250
|
+
- Technical indicators (RSI, MACD, Moving Averages)
|
|
251
|
+
- Market sentiment
|
|
252
|
+
- News and events
|
|
253
|
+
- Support and resistance levels
|
|
254
|
+
|
|
255
|
+
Provide a structured analysis in JSON format:
|
|
256
|
+
{
|
|
257
|
+
"trend": "bullish|bearish|sideways",
|
|
258
|
+
"confidence": 0-100,
|
|
259
|
+
"keyLevels": {
|
|
260
|
+
"support": ["price levels"],
|
|
261
|
+
"resistance": ["price levels"]
|
|
262
|
+
},
|
|
263
|
+
"indicators": {
|
|
264
|
+
"rsi": number,
|
|
265
|
+
"macd": "bullish|bearish|neutral",
|
|
266
|
+
"volume": "high|medium|low"
|
|
267
|
+
},
|
|
268
|
+
"signals": ["list of trading signals"],
|
|
269
|
+
"riskLevel": "low|medium|high",
|
|
270
|
+
"marketCondition": "volatile|ranging|trending"
|
|
271
|
+
}
|
|
272
|
+
`;
|
|
273
|
+
|
|
274
|
+
const response = await context.agent.execute(prompt);
|
|
275
|
+
|
|
276
|
+
// Parse and store analysis
|
|
277
|
+
try {
|
|
278
|
+
const jsonMatch = response.match(/\{[\s\S]*\}/);
|
|
279
|
+
if (jsonMatch) {
|
|
280
|
+
const analysis = JSON.parse(jsonMatch[0]);
|
|
281
|
+
context.custom.analysis = analysis;
|
|
282
|
+
context.custom.riskLevel = analysis.riskLevel || "medium";
|
|
283
|
+
}
|
|
284
|
+
} catch {
|
|
285
|
+
context.custom.analysis = { raw: response };
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
return {
|
|
289
|
+
nextPhase: "signaling",
|
|
290
|
+
continue: true,
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Signaling phase - generate trading signals
|
|
296
|
+
*/
|
|
297
|
+
private async phaseSignaling(context: GLMWorkflowContext): Promise<GLMWorkflowPhaseResult> {
|
|
298
|
+
console.log("[TradingWorkflow] Phase: Generating signals");
|
|
299
|
+
|
|
300
|
+
const analysis = context.custom.analysis || {};
|
|
301
|
+
|
|
302
|
+
const prompt = `Generate trading signals based on the market analysis.
|
|
303
|
+
|
|
304
|
+
Analysis: ${JSON.stringify(analysis, null, 2)}
|
|
305
|
+
|
|
306
|
+
Generate a trading signal with:
|
|
307
|
+
- Direction (long/short)
|
|
308
|
+
- Entry price zone
|
|
309
|
+
- Stop loss level
|
|
310
|
+
- Take profit targets (1, 2, 3)
|
|
311
|
+
- Position size recommendation
|
|
312
|
+
- Risk/reward ratio
|
|
313
|
+
- Confidence level
|
|
314
|
+
|
|
315
|
+
Provide the signal in JSON format:
|
|
316
|
+
{
|
|
317
|
+
"direction": "long|short",
|
|
318
|
+
"entryZone": { "min": number, "max": number },
|
|
319
|
+
"stopLoss": number,
|
|
320
|
+
"takeProfits": {
|
|
321
|
+
"tp1": { "price": number, "size": "percentage of position" },
|
|
322
|
+
"tp2": { "price": number, "size": "percentage of position" },
|
|
323
|
+
"tp3": { "price": number, "size": "percentage of position" }
|
|
324
|
+
},
|
|
325
|
+
"positionSize": { "percentage": number, "reason": "string" },
|
|
326
|
+
"riskReward": number,
|
|
327
|
+
"confidence": 0-100,
|
|
328
|
+
"rationale": "explanation for the signal"
|
|
329
|
+
}
|
|
330
|
+
`;
|
|
331
|
+
|
|
332
|
+
const response = await context.agent.execute(prompt);
|
|
333
|
+
|
|
334
|
+
// Parse and store signal
|
|
335
|
+
try {
|
|
336
|
+
const jsonMatch = response.match(/\{[\s\S]*\}/);
|
|
337
|
+
if (jsonMatch) {
|
|
338
|
+
context.custom.signal = JSON.parse(jsonMatch[0]);
|
|
339
|
+
}
|
|
340
|
+
} catch {
|
|
341
|
+
context.custom.signal = { raw: response };
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
return {
|
|
345
|
+
nextPhase: "risk_checking",
|
|
346
|
+
continue: true,
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Risk Checking phase - evaluate risk before execution
|
|
352
|
+
*/
|
|
353
|
+
private async phaseRiskChecking(context: GLMWorkflowContext): Promise<GLMWorkflowPhaseResult> {
|
|
354
|
+
console.log("[TradingWorkflow] Phase: Risk checking");
|
|
355
|
+
|
|
356
|
+
const analysis = context.custom.analysis || {};
|
|
357
|
+
const signal = context.custom.signal || {};
|
|
358
|
+
|
|
359
|
+
const prompt = `Perform risk assessment for the proposed trade.
|
|
360
|
+
|
|
361
|
+
Analysis: ${JSON.stringify(analysis, null, 2)}
|
|
362
|
+
Signal: ${JSON.stringify(signal, null, 2)}
|
|
363
|
+
|
|
364
|
+
Evaluate:
|
|
365
|
+
1. Risk/reward ratio (minimum 1:2)
|
|
366
|
+
2. Position size vs account risk (max 2% per trade)
|
|
367
|
+
3. Market conditions (avoid high volatility if conservative)
|
|
368
|
+
4. Correlation with existing positions
|
|
369
|
+
5. Stop loss placement validity
|
|
370
|
+
|
|
371
|
+
Respond with risk assessment in JSON format:
|
|
372
|
+
{
|
|
373
|
+
"approved": true|false,
|
|
374
|
+
"riskScore": 0-100,
|
|
375
|
+
"concerns": ["list of concerns"],
|
|
376
|
+
"adjustments": ["suggested adjustments"],
|
|
377
|
+
"maxPositionSize": number,
|
|
378
|
+
"reasoning": "detailed explanation"
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
If approved is false, explain why and what conditions would make it acceptable.
|
|
382
|
+
`;
|
|
383
|
+
|
|
384
|
+
const response = await context.agent.execute(prompt);
|
|
385
|
+
|
|
386
|
+
// Parse risk assessment
|
|
387
|
+
try {
|
|
388
|
+
const jsonMatch = response.match(/\{[\s\S]*\}/);
|
|
389
|
+
if (jsonMatch) {
|
|
390
|
+
const riskAssessment = JSON.parse(jsonMatch[0]);
|
|
391
|
+
context.custom.riskAssessment = riskAssessment;
|
|
392
|
+
context.custom.riskApproved = riskAssessment.approved === true;
|
|
393
|
+
|
|
394
|
+
// Adjust position size if suggested
|
|
395
|
+
if (riskAssessment.maxPositionSize && context.custom.signal) {
|
|
396
|
+
(context.custom.signal as any).positionSize = { percentage: riskAssessment.maxPositionSize };
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
} catch {
|
|
400
|
+
// Default to not approved on parse failure
|
|
401
|
+
context.custom.riskApproved = false;
|
|
402
|
+
context.custom.riskAssessment = { raw: response, approved: false };
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
const nextPhase = context.custom.riskApproved ? "executing" : "analyzing";
|
|
406
|
+
|
|
407
|
+
return {
|
|
408
|
+
nextPhase,
|
|
409
|
+
continue: true,
|
|
410
|
+
data: { riskApproved: context.custom.riskApproved },
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Executing phase - execute trades
|
|
416
|
+
*/
|
|
417
|
+
private async phaseExecuting(context: GLMWorkflowContext): Promise<GLMWorkflowPhaseResult> {
|
|
418
|
+
console.log("[TradingWorkflow] Phase: Executing trade");
|
|
419
|
+
|
|
420
|
+
const signal = context.custom.signal || {};
|
|
421
|
+
const riskAssessment = context.custom.riskAssessment || {};
|
|
422
|
+
|
|
423
|
+
const prompt = `Execute the approved trade signal.
|
|
424
|
+
|
|
425
|
+
Signal: ${JSON.stringify(signal, null, 2)}
|
|
426
|
+
Risk Assessment: ${JSON.stringify(riskAssessment, null, 2)}
|
|
427
|
+
|
|
428
|
+
Use the available trading tools to:
|
|
429
|
+
1. Place the entry order (limit or market based on conditions)
|
|
430
|
+
2. Set stop loss order
|
|
431
|
+
3. Set take profit orders (tp1, tp2, tp3)
|
|
432
|
+
4. Confirm all orders are placed correctly
|
|
433
|
+
|
|
434
|
+
Report the execution status with order IDs.
|
|
435
|
+
`;
|
|
436
|
+
|
|
437
|
+
const response = await context.agent.execute(prompt);
|
|
438
|
+
context.custom.executionResult = response;
|
|
439
|
+
context.custom.tradeStartTime = new Date().toISOString();
|
|
440
|
+
|
|
441
|
+
return {
|
|
442
|
+
nextPhase: "monitoring",
|
|
443
|
+
continue: true,
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* Monitoring phase - monitor positions
|
|
449
|
+
*/
|
|
450
|
+
private async phaseMonitoring(context: GLMWorkflowContext): Promise<GLMWorkflowPhaseResult> {
|
|
451
|
+
console.log("[TradingWorkflow] Phase: Monitoring position");
|
|
452
|
+
|
|
453
|
+
const signal = context.custom.signal || {};
|
|
454
|
+
const executionResult = context.custom.executionResult || "";
|
|
455
|
+
|
|
456
|
+
const prompt = `Monitor the current position.
|
|
457
|
+
|
|
458
|
+
Signal: ${JSON.stringify(signal, null, 2)}
|
|
459
|
+
Execution: ${executionResult}
|
|
460
|
+
Trade Start: ${context.custom.tradeStartTime || "unknown"}
|
|
461
|
+
|
|
462
|
+
Check:
|
|
463
|
+
- Current price vs entry
|
|
464
|
+
- Unrealized P&L
|
|
465
|
+
- Distance to take profit levels
|
|
466
|
+
- Distance to stop loss
|
|
467
|
+
- Market conditions changes
|
|
468
|
+
- Time in trade
|
|
469
|
+
|
|
470
|
+
Report status and current state in JSON format:
|
|
471
|
+
{
|
|
472
|
+
"currentPrice": number,
|
|
473
|
+
"unrealizedPnL": number,
|
|
474
|
+
"pnlPercent": number,
|
|
475
|
+
"tp1Hit": boolean,
|
|
476
|
+
"tp2Hit": boolean,
|
|
477
|
+
"tp3Hit": boolean,
|
|
478
|
+
"stopLossHit": boolean,
|
|
479
|
+
"targetReached": boolean,
|
|
480
|
+
"positionClosed": boolean,
|
|
481
|
+
"status": "open|closed|stopped_out|taken_profit",
|
|
482
|
+
"recommendation": "hold|close|adjust"
|
|
483
|
+
}
|
|
484
|
+
`;
|
|
485
|
+
|
|
486
|
+
const response = await context.agent.execute(prompt);
|
|
487
|
+
|
|
488
|
+
// Parse monitoring result
|
|
489
|
+
try {
|
|
490
|
+
const jsonMatch = response.match(/\{[\s\S]*\}/);
|
|
491
|
+
if (jsonMatch) {
|
|
492
|
+
const monitorStatus = JSON.parse(jsonMatch[0]);
|
|
493
|
+
context.custom.monitorStatus = monitorStatus;
|
|
494
|
+
context.custom.targetReached = monitorStatus.targetReached === true;
|
|
495
|
+
context.custom.stopLoss = monitorStatus.stopLossHit === true;
|
|
496
|
+
context.custom.positionClosed = monitorStatus.positionClosed === true;
|
|
497
|
+
context.custom.currentPnL = monitorStatus.unrealizedPnL;
|
|
498
|
+
}
|
|
499
|
+
} catch {
|
|
500
|
+
// Fallback detection
|
|
501
|
+
const lowerResponse = response.toLowerCase();
|
|
502
|
+
context.custom.targetReached = lowerResponse.includes("target") && lowerResponse.includes("reached");
|
|
503
|
+
context.custom.stopLoss = lowerResponse.includes("stop loss") && lowerResponse.includes("hit");
|
|
504
|
+
context.custom.positionClosed = lowerResponse.includes("position closed");
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
// Determine next phase
|
|
508
|
+
let nextPhase: TradingPhase = "monitoring";
|
|
509
|
+
if (context.custom.targetReached || context.custom.stopLoss) {
|
|
510
|
+
nextPhase = "complete";
|
|
511
|
+
} else if (context.custom.positionClosed) {
|
|
512
|
+
nextPhase = "analyzing"; // Look for new opportunities
|
|
513
|
+
} else if (context.state.iteration % 10 === 0 && context.state.iteration > 0) {
|
|
514
|
+
nextPhase = "reflecting";
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
return {
|
|
518
|
+
nextPhase,
|
|
519
|
+
continue: true,
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
/**
|
|
524
|
+
* Reflecting phase - review performance
|
|
525
|
+
*/
|
|
526
|
+
private async phaseReflecting(context: GLMWorkflowContext): Promise<GLMWorkflowPhaseResult> {
|
|
527
|
+
console.log(`[TradingWorkflow] Phase: Reflecting (checkpoint #${context.state.reflection.checkpointCount + 1})`);
|
|
528
|
+
|
|
529
|
+
const prompt = `Reflect on trading performance so far.
|
|
530
|
+
|
|
531
|
+
Iteration: ${context.state.iteration}
|
|
532
|
+
Current P&L: ${context.custom.currentPnL || "unknown"}
|
|
533
|
+
Risk Level: ${context.custom.riskLevel || "medium"}
|
|
534
|
+
|
|
535
|
+
Review:
|
|
536
|
+
- What trades were taken?
|
|
537
|
+
- What signals were generated but not executed?
|
|
538
|
+
- What's the win rate?
|
|
539
|
+
- Are risk parameters being followed?
|
|
540
|
+
|
|
541
|
+
Provide a brief performance summary:
|
|
542
|
+
{
|
|
543
|
+
"totalSignals": number,
|
|
544
|
+
"signalsExecuted": number,
|
|
545
|
+
"winRate": number,
|
|
546
|
+
"currentDrawdown": number,
|
|
547
|
+
"lessonsLearned": ["insights"],
|
|
548
|
+
"adjustmentsNeeded": ["suggested adjustments"]
|
|
549
|
+
}
|
|
550
|
+
`;
|
|
551
|
+
|
|
552
|
+
const response = await context.agent.execute(prompt);
|
|
553
|
+
|
|
554
|
+
// Parse reflection
|
|
555
|
+
try {
|
|
556
|
+
const jsonMatch = response.match(/\{[\s\S]*\}/);
|
|
557
|
+
if (jsonMatch) {
|
|
558
|
+
context.custom.reflection = JSON.parse(jsonMatch[0]);
|
|
559
|
+
}
|
|
560
|
+
} catch {
|
|
561
|
+
context.custom.reflection = { raw: response };
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
return {
|
|
565
|
+
nextPhase: "monitoring",
|
|
566
|
+
continue: true,
|
|
567
|
+
};
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
/**
|
|
571
|
+
* Complete phase - trading session finished
|
|
572
|
+
*/
|
|
573
|
+
private async phaseComplete(context: GLMWorkflowContext): Promise<GLMWorkflowPhaseResult> {
|
|
574
|
+
console.log("[TradingWorkflow] Trading session complete!");
|
|
575
|
+
|
|
576
|
+
const prompt = `Final summary of trading session.
|
|
577
|
+
|
|
578
|
+
Session Summary:
|
|
579
|
+
- Total Iterations: ${context.state.iteration}
|
|
580
|
+
- Final P&L: ${context.custom.currentPnL || "unknown"}
|
|
581
|
+
- Target Reached: ${context.custom.targetReached ? "Yes" : "No"}
|
|
582
|
+
- Stop Loss Hit: ${context.custom.stopLoss ? "Yes" : "No"}
|
|
583
|
+
|
|
584
|
+
Report:
|
|
585
|
+
- Total signals generated
|
|
586
|
+
- Trades executed
|
|
587
|
+
- Win/loss ratio
|
|
588
|
+
- Total P&L
|
|
589
|
+
- Maximum drawdown
|
|
590
|
+
- Key lessons learned
|
|
591
|
+
- Recommendations for future sessions
|
|
592
|
+
|
|
593
|
+
Format as a trading journal entry.
|
|
594
|
+
`;
|
|
595
|
+
|
|
596
|
+
await context.agent.execute(prompt);
|
|
597
|
+
|
|
598
|
+
await context.executeHook("onSessionEnd", context.state);
|
|
599
|
+
|
|
600
|
+
return {
|
|
601
|
+
nextPhase: "complete",
|
|
602
|
+
continue: false,
|
|
603
|
+
};
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
// Export singleton instance
|
|
608
|
+
export const tradingWorkflow = new TradingWorkflow();
|