@timmeck/trading-brain 1.0.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 +306 -0
- package/dist/api/server.d.ts +21 -0
- package/dist/api/server.js +157 -0
- package/dist/api/server.js.map +1 -0
- package/dist/cli/colors.d.ts +46 -0
- package/dist/cli/colors.js +70 -0
- package/dist/cli/colors.js.map +1 -0
- package/dist/cli/commands/config.d.ts +2 -0
- package/dist/cli/commands/config.js +70 -0
- package/dist/cli/commands/config.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +2 -0
- package/dist/cli/commands/doctor.js +61 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/export.d.ts +2 -0
- package/dist/cli/commands/export.js +23 -0
- package/dist/cli/commands/export.js.map +1 -0
- package/dist/cli/commands/import.d.ts +2 -0
- package/dist/cli/commands/import.js +42 -0
- package/dist/cli/commands/import.js.map +1 -0
- package/dist/cli/commands/insights.d.ts +2 -0
- package/dist/cli/commands/insights.js +29 -0
- package/dist/cli/commands/insights.js.map +1 -0
- package/dist/cli/commands/network.d.ts +2 -0
- package/dist/cli/commands/network.js +43 -0
- package/dist/cli/commands/network.js.map +1 -0
- package/dist/cli/commands/query.d.ts +2 -0
- package/dist/cli/commands/query.js +27 -0
- package/dist/cli/commands/query.js.map +1 -0
- package/dist/cli/commands/rules.d.ts +2 -0
- package/dist/cli/commands/rules.js +26 -0
- package/dist/cli/commands/rules.js.map +1 -0
- package/dist/cli/commands/start.d.ts +2 -0
- package/dist/cli/commands/start.js +86 -0
- package/dist/cli/commands/start.js.map +1 -0
- package/dist/cli/commands/status.d.ts +2 -0
- package/dist/cli/commands/status.js +58 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/commands/stop.d.ts +2 -0
- package/dist/cli/commands/stop.js +34 -0
- package/dist/cli/commands/stop.js.map +1 -0
- package/dist/cli/ipc-helper.d.ts +2 -0
- package/dist/cli/ipc-helper.js +26 -0
- package/dist/cli/ipc-helper.js.map +1 -0
- package/dist/config.d.ts +2 -0
- package/dist/config.js +107 -0
- package/dist/config.js.map +1 -0
- package/dist/db/connection.d.ts +2 -0
- package/dist/db/connection.js +19 -0
- package/dist/db/connection.js.map +1 -0
- package/dist/db/migrations/001_core.d.ts +2 -0
- package/dist/db/migrations/001_core.js +42 -0
- package/dist/db/migrations/001_core.js.map +1 -0
- package/dist/db/migrations/002_synapses.d.ts +2 -0
- package/dist/db/migrations/002_synapses.js +43 -0
- package/dist/db/migrations/002_synapses.js.map +1 -0
- package/dist/db/migrations/003_learning.d.ts +2 -0
- package/dist/db/migrations/003_learning.js +48 -0
- package/dist/db/migrations/003_learning.js.map +1 -0
- package/dist/db/migrations/004_research.d.ts +2 -0
- package/dist/db/migrations/004_research.js +29 -0
- package/dist/db/migrations/004_research.js.map +1 -0
- package/dist/db/migrations/index.d.ts +2 -0
- package/dist/db/migrations/index.js +45 -0
- package/dist/db/migrations/index.js.map +1 -0
- package/dist/db/repositories/calibration.repository.d.ts +25 -0
- package/dist/db/repositories/calibration.repository.js +66 -0
- package/dist/db/repositories/calibration.repository.js.map +1 -0
- package/dist/db/repositories/chain.repository.d.ts +28 -0
- package/dist/db/repositories/chain.repository.js +52 -0
- package/dist/db/repositories/chain.repository.js.map +1 -0
- package/dist/db/repositories/graph.repository.d.ts +33 -0
- package/dist/db/repositories/graph.repository.js +73 -0
- package/dist/db/repositories/graph.repository.js.map +1 -0
- package/dist/db/repositories/insight.repository.d.ts +30 -0
- package/dist/db/repositories/insight.repository.js +60 -0
- package/dist/db/repositories/insight.repository.js.map +1 -0
- package/dist/db/repositories/rule.repository.d.ts +35 -0
- package/dist/db/repositories/rule.repository.js +48 -0
- package/dist/db/repositories/rule.repository.js.map +1 -0
- package/dist/db/repositories/signal.repository.d.ts +17 -0
- package/dist/db/repositories/signal.repository.js +35 -0
- package/dist/db/repositories/signal.repository.js.map +1 -0
- package/dist/db/repositories/synapse.repository.d.ts +25 -0
- package/dist/db/repositories/synapse.repository.js +50 -0
- package/dist/db/repositories/synapse.repository.js.map +1 -0
- package/dist/db/repositories/trade.repository.d.ts +36 -0
- package/dist/db/repositories/trade.repository.js +64 -0
- package/dist/db/repositories/trade.repository.js.map +1 -0
- package/dist/graph/weighted-graph.d.ts +58 -0
- package/dist/graph/weighted-graph.js +149 -0
- package/dist/graph/weighted-graph.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +49 -0
- package/dist/index.js.map +1 -0
- package/dist/ipc/client.d.ts +16 -0
- package/dist/ipc/client.js +95 -0
- package/dist/ipc/client.js.map +1 -0
- package/dist/ipc/protocol.d.ts +8 -0
- package/dist/ipc/protocol.js +29 -0
- package/dist/ipc/protocol.js.map +1 -0
- package/dist/ipc/router.d.ts +32 -0
- package/dist/ipc/router.js +70 -0
- package/dist/ipc/router.js.map +1 -0
- package/dist/ipc/server.d.ts +18 -0
- package/dist/ipc/server.js +142 -0
- package/dist/ipc/server.js.map +1 -0
- package/dist/learning/calibrator.d.ts +6 -0
- package/dist/learning/calibrator.js +57 -0
- package/dist/learning/calibrator.js.map +1 -0
- package/dist/learning/chain-detector.d.ts +17 -0
- package/dist/learning/chain-detector.js +29 -0
- package/dist/learning/chain-detector.js.map +1 -0
- package/dist/learning/learning-engine.d.ts +31 -0
- package/dist/learning/learning-engine.js +85 -0
- package/dist/learning/learning-engine.js.map +1 -0
- package/dist/learning/pattern-extractor.d.ts +14 -0
- package/dist/learning/pattern-extractor.js +40 -0
- package/dist/learning/pattern-extractor.js.map +1 -0
- package/dist/mcp/http-server.d.ts +14 -0
- package/dist/mcp/http-server.js +117 -0
- package/dist/mcp/http-server.js.map +1 -0
- package/dist/mcp/server.d.ts +1 -0
- package/dist/mcp/server.js +67 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools.d.ts +7 -0
- package/dist/mcp/tools.js +158 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/research/research-engine.d.ts +21 -0
- package/dist/research/research-engine.js +204 -0
- package/dist/research/research-engine.js.map +1 -0
- package/dist/services/analytics.service.d.ts +16 -0
- package/dist/services/analytics.service.js +64 -0
- package/dist/services/analytics.service.js.map +1 -0
- package/dist/services/insight.service.d.ts +11 -0
- package/dist/services/insight.service.js +25 -0
- package/dist/services/insight.service.js.map +1 -0
- package/dist/services/signal.service.d.ts +22 -0
- package/dist/services/signal.service.js +96 -0
- package/dist/services/signal.service.js.map +1 -0
- package/dist/services/strategy.service.d.ts +29 -0
- package/dist/services/strategy.service.js +115 -0
- package/dist/services/strategy.service.js.map +1 -0
- package/dist/services/synapse.service.d.ts +20 -0
- package/dist/services/synapse.service.js +48 -0
- package/dist/services/synapse.service.js.map +1 -0
- package/dist/services/trade.service.d.ts +37 -0
- package/dist/services/trade.service.js +114 -0
- package/dist/services/trade.service.js.map +1 -0
- package/dist/signals/fingerprint.d.ts +29 -0
- package/dist/signals/fingerprint.js +98 -0
- package/dist/signals/fingerprint.js.map +1 -0
- package/dist/signals/wilson-score.d.ts +10 -0
- package/dist/signals/wilson-score.js +19 -0
- package/dist/signals/wilson-score.js.map +1 -0
- package/dist/synapses/decay.d.ts +6 -0
- package/dist/synapses/decay.js +17 -0
- package/dist/synapses/decay.js.map +1 -0
- package/dist/synapses/hebbian.d.ts +11 -0
- package/dist/synapses/hebbian.js +21 -0
- package/dist/synapses/hebbian.js.map +1 -0
- package/dist/synapses/synapse-manager.d.ts +22 -0
- package/dist/synapses/synapse-manager.js +99 -0
- package/dist/synapses/synapse-manager.js.map +1 -0
- package/dist/trading-core.d.ts +17 -0
- package/dist/trading-core.js +235 -0
- package/dist/trading-core.js.map +1 -0
- package/dist/types/config.types.d.ts +52 -0
- package/dist/types/config.types.js +2 -0
- package/dist/types/config.types.js.map +1 -0
- package/dist/types/ipc.types.d.ts +11 -0
- package/dist/types/ipc.types.js +2 -0
- package/dist/types/ipc.types.js.map +1 -0
- package/dist/utils/events.d.ts +48 -0
- package/dist/utils/events.js +23 -0
- package/dist/utils/events.js.map +1 -0
- package/dist/utils/hash.d.ts +1 -0
- package/dist/utils/hash.js +5 -0
- package/dist/utils/hash.js.map +1 -0
- package/dist/utils/logger.d.ts +8 -0
- package/dist/utils/logger.js +39 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/paths.d.ts +3 -0
- package/dist/utils/paths.js +18 -0
- package/dist/utils/paths.js.map +1 -0
- package/package.json +47 -0
- package/src/api/server.ts +160 -0
- package/src/cli/colors.ts +80 -0
- package/src/cli/commands/config.ts +76 -0
- package/src/cli/commands/doctor.ts +62 -0
- package/src/cli/commands/export.ts +24 -0
- package/src/cli/commands/import.ts +44 -0
- package/src/cli/commands/insights.ts +30 -0
- package/src/cli/commands/network.ts +43 -0
- package/src/cli/commands/query.ts +28 -0
- package/src/cli/commands/rules.ts +27 -0
- package/src/cli/commands/start.ts +93 -0
- package/src/cli/commands/status.ts +64 -0
- package/src/cli/commands/stop.ts +33 -0
- package/src/cli/ipc-helper.ts +22 -0
- package/src/config.ts +103 -0
- package/src/db/connection.ts +22 -0
- package/src/db/migrations/001_core.ts +43 -0
- package/src/db/migrations/002_synapses.ts +44 -0
- package/src/db/migrations/003_learning.ts +49 -0
- package/src/db/migrations/004_research.ts +30 -0
- package/src/db/migrations/index.ts +60 -0
- package/src/db/repositories/calibration.repository.ts +86 -0
- package/src/db/repositories/chain.repository.ts +70 -0
- package/src/db/repositories/graph.repository.ts +103 -0
- package/src/db/repositories/insight.repository.ts +80 -0
- package/src/db/repositories/rule.repository.ts +67 -0
- package/src/db/repositories/signal.repository.ts +48 -0
- package/src/db/repositories/synapse.repository.ts +71 -0
- package/src/db/repositories/trade.repository.ts +97 -0
- package/src/graph/weighted-graph.ts +194 -0
- package/src/index.ts +55 -0
- package/src/ipc/client.ts +112 -0
- package/src/ipc/protocol.ts +35 -0
- package/src/ipc/router.ts +113 -0
- package/src/ipc/server.ts +150 -0
- package/src/learning/calibrator.ts +57 -0
- package/src/learning/chain-detector.ts +43 -0
- package/src/learning/learning-engine.ts +94 -0
- package/src/learning/pattern-extractor.ts +53 -0
- package/src/mcp/http-server.ts +118 -0
- package/src/mcp/server.ts +72 -0
- package/src/mcp/tools.ts +256 -0
- package/src/research/research-engine.ts +223 -0
- package/src/services/analytics.service.ts +68 -0
- package/src/services/insight.service.ts +29 -0
- package/src/services/signal.service.ts +109 -0
- package/src/services/strategy.service.ts +130 -0
- package/src/services/synapse.service.ts +58 -0
- package/src/services/trade.service.ts +139 -0
- package/src/signals/fingerprint.ts +93 -0
- package/src/signals/wilson-score.ts +17 -0
- package/src/synapses/decay.ts +19 -0
- package/src/synapses/hebbian.ts +23 -0
- package/src/synapses/synapse-manager.ts +112 -0
- package/src/trading-core.ts +285 -0
- package/src/types/config.types.ts +60 -0
- package/src/types/ipc.types.ts +8 -0
- package/src/utils/events.ts +42 -0
- package/src/utils/hash.ts +5 -0
- package/src/utils/logger.ts +48 -0
- package/src/utils/paths.ts +19 -0
- package/tsconfig.json +18 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import net from 'node:net';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import { randomUUID } from 'node:crypto';
|
|
4
|
+
import { getLogger } from '../utils/logger.js';
|
|
5
|
+
import { encodeMessage, MessageDecoder } from './protocol.js';
|
|
6
|
+
export class IpcServer {
|
|
7
|
+
router;
|
|
8
|
+
pipeName;
|
|
9
|
+
server = null;
|
|
10
|
+
clients = new Map();
|
|
11
|
+
logger = getLogger();
|
|
12
|
+
constructor(router, pipeName) {
|
|
13
|
+
this.router = router;
|
|
14
|
+
this.pipeName = pipeName;
|
|
15
|
+
}
|
|
16
|
+
start() {
|
|
17
|
+
this.createServer();
|
|
18
|
+
this.listen();
|
|
19
|
+
}
|
|
20
|
+
createServer() {
|
|
21
|
+
this.server = net.createServer((socket) => {
|
|
22
|
+
const clientId = randomUUID();
|
|
23
|
+
this.clients.set(clientId, socket);
|
|
24
|
+
const decoder = new MessageDecoder();
|
|
25
|
+
this.logger.info(`IPC client connected: ${clientId}`);
|
|
26
|
+
socket.on('data', (chunk) => {
|
|
27
|
+
const messages = decoder.feed(chunk);
|
|
28
|
+
for (const msg of messages) {
|
|
29
|
+
this.handleMessage(clientId, msg, socket);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
socket.on('close', () => {
|
|
33
|
+
this.logger.info(`IPC client disconnected: ${clientId}`);
|
|
34
|
+
this.clients.delete(clientId);
|
|
35
|
+
});
|
|
36
|
+
socket.on('error', (err) => {
|
|
37
|
+
this.logger.error(`IPC client ${clientId} error:`, err);
|
|
38
|
+
this.clients.delete(clientId);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
listen(retried = false) {
|
|
43
|
+
if (!this.server)
|
|
44
|
+
return;
|
|
45
|
+
this.server.on('error', (err) => {
|
|
46
|
+
if (err.code === 'EADDRINUSE' && !retried) {
|
|
47
|
+
this.logger.warn(`IPC pipe in use, attempting to recover stale pipe: ${this.pipeName}`);
|
|
48
|
+
this.recoverStalePipe();
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
this.logger.error('IPC server error:', err);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
this.server.listen(this.pipeName, () => {
|
|
55
|
+
this.logger.info(`IPC server listening on ${this.pipeName}`);
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
recoverStalePipe() {
|
|
59
|
+
const probe = net.createConnection(this.pipeName);
|
|
60
|
+
probe.on('connect', () => {
|
|
61
|
+
probe.destroy();
|
|
62
|
+
this.logger.error('IPC pipe is held by another running daemon. Stop it first with: trading stop');
|
|
63
|
+
});
|
|
64
|
+
probe.on('error', () => {
|
|
65
|
+
probe.destroy();
|
|
66
|
+
this.logger.info('Stale IPC pipe detected, reclaiming...');
|
|
67
|
+
if (process.platform !== 'win32') {
|
|
68
|
+
try {
|
|
69
|
+
fs.unlinkSync(this.pipeName);
|
|
70
|
+
}
|
|
71
|
+
catch { /* ignore */ }
|
|
72
|
+
}
|
|
73
|
+
this.createServer();
|
|
74
|
+
this.server.on('error', (err) => {
|
|
75
|
+
this.logger.error('IPC server error after recovery:', err);
|
|
76
|
+
});
|
|
77
|
+
this.server.listen(this.pipeName, () => {
|
|
78
|
+
this.logger.info(`IPC server recovered and listening on ${this.pipeName}`);
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
probe.setTimeout(2000, () => {
|
|
82
|
+
probe.destroy();
|
|
83
|
+
this.logger.warn('IPC pipe probe timed out, treating as stale');
|
|
84
|
+
if (process.platform !== 'win32') {
|
|
85
|
+
try {
|
|
86
|
+
fs.unlinkSync(this.pipeName);
|
|
87
|
+
}
|
|
88
|
+
catch { /* ignore */ }
|
|
89
|
+
}
|
|
90
|
+
this.createServer();
|
|
91
|
+
this.server.on('error', (err) => {
|
|
92
|
+
this.logger.error('IPC server error after timeout recovery:', err);
|
|
93
|
+
});
|
|
94
|
+
this.server.listen(this.pipeName, () => {
|
|
95
|
+
this.logger.info(`IPC server recovered (timeout) and listening on ${this.pipeName}`);
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
handleMessage(clientId, msg, socket) {
|
|
100
|
+
if (msg.type !== 'request' || !msg.method)
|
|
101
|
+
return;
|
|
102
|
+
try {
|
|
103
|
+
const result = this.router.handle(msg.method, msg.params);
|
|
104
|
+
const response = { id: msg.id, type: 'response', result };
|
|
105
|
+
socket.write(encodeMessage(response));
|
|
106
|
+
}
|
|
107
|
+
catch (err) {
|
|
108
|
+
const response = {
|
|
109
|
+
id: msg.id, type: 'response',
|
|
110
|
+
error: { code: -1, message: err instanceof Error ? err.message : String(err) },
|
|
111
|
+
};
|
|
112
|
+
socket.write(encodeMessage(response));
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
notify(clientId, notification) {
|
|
116
|
+
const msg = { id: randomUUID(), type: 'notification', ...notification };
|
|
117
|
+
const encoded = encodeMessage(msg);
|
|
118
|
+
if (clientId) {
|
|
119
|
+
const socket = this.clients.get(clientId);
|
|
120
|
+
if (socket && !socket.destroyed)
|
|
121
|
+
socket.write(encoded);
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
for (const socket of this.clients.values()) {
|
|
125
|
+
if (!socket.destroyed)
|
|
126
|
+
socket.write(encoded);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
getClientCount() {
|
|
131
|
+
return this.clients.size;
|
|
132
|
+
}
|
|
133
|
+
stop() {
|
|
134
|
+
for (const socket of this.clients.values())
|
|
135
|
+
socket.destroy();
|
|
136
|
+
this.clients.clear();
|
|
137
|
+
this.server?.close();
|
|
138
|
+
this.server = null;
|
|
139
|
+
this.logger.info('IPC server stopped');
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/ipc/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { CalibrationConfig } from '../types/config.types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Adaptive Calibration — dynamically adjust learning parameters based on data volume.
|
|
4
|
+
* Ported from tradingBrain.js calibrate() function.
|
|
5
|
+
*/
|
|
6
|
+
export declare function calibrate(current: CalibrationConfig, outcomeCount: number, synapseCount: number): CalibrationConfig;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adaptive Calibration — dynamically adjust learning parameters based on data volume.
|
|
3
|
+
* Ported from tradingBrain.js calibrate() function.
|
|
4
|
+
*/
|
|
5
|
+
export function calibrate(current, outcomeCount, synapseCount) {
|
|
6
|
+
const cal = { ...current };
|
|
7
|
+
if (outcomeCount < 20) {
|
|
8
|
+
// Very early: conservative, wide thresholds
|
|
9
|
+
cal.learningRate = 0.08;
|
|
10
|
+
cal.weakenPenalty = 0.8;
|
|
11
|
+
cal.patternMinSamples = 5;
|
|
12
|
+
cal.patternWilsonThreshold = 0.3;
|
|
13
|
+
cal.wilsonZ = 1.64; // 90% CI
|
|
14
|
+
cal.minActivationsForWeight = 2;
|
|
15
|
+
cal.minOutcomesForWeights = 3;
|
|
16
|
+
}
|
|
17
|
+
else if (outcomeCount < 100) {
|
|
18
|
+
// Growing: moderate
|
|
19
|
+
cal.learningRate = 0.12;
|
|
20
|
+
cal.weakenPenalty = 0.75;
|
|
21
|
+
cal.patternMinSamples = 8;
|
|
22
|
+
cal.patternWilsonThreshold = 0.4;
|
|
23
|
+
cal.wilsonZ = 1.80;
|
|
24
|
+
cal.minActivationsForWeight = 3;
|
|
25
|
+
cal.minOutcomesForWeights = 5;
|
|
26
|
+
}
|
|
27
|
+
else if (outcomeCount < 500) {
|
|
28
|
+
// Mature: standard
|
|
29
|
+
cal.learningRate = 0.15;
|
|
30
|
+
cal.weakenPenalty = 0.7;
|
|
31
|
+
cal.patternMinSamples = 10;
|
|
32
|
+
cal.patternWilsonThreshold = 0.5;
|
|
33
|
+
cal.wilsonZ = 1.96; // 95% CI
|
|
34
|
+
cal.minActivationsForWeight = 3;
|
|
35
|
+
cal.minOutcomesForWeights = 5;
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
// Large dataset: high confidence, fine-grained
|
|
39
|
+
cal.learningRate = 0.10;
|
|
40
|
+
cal.weakenPenalty = 0.75;
|
|
41
|
+
cal.patternMinSamples = 15;
|
|
42
|
+
cal.patternWilsonThreshold = 0.55;
|
|
43
|
+
cal.wilsonZ = 2.33; // 99% CI
|
|
44
|
+
cal.minActivationsForWeight = 5;
|
|
45
|
+
cal.minOutcomesForWeights = 8;
|
|
46
|
+
cal.patternExtractionInterval = 30;
|
|
47
|
+
}
|
|
48
|
+
// Adjust decay based on synapse density
|
|
49
|
+
if (synapseCount > 100) {
|
|
50
|
+
cal.decayHalfLifeDays = 10; // faster cleanup
|
|
51
|
+
}
|
|
52
|
+
else if (synapseCount < 10) {
|
|
53
|
+
cal.decayHalfLifeDays = 21; // preserve early knowledge
|
|
54
|
+
}
|
|
55
|
+
return cal;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=calibrator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"calibrator.js","sourceRoot":"","sources":["../../src/learning/calibrator.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,OAA0B,EAAE,YAAoB,EAAE,YAAoB;IAC9F,MAAM,GAAG,GAAG,EAAE,GAAG,OAAO,EAAE,CAAC;IAE3B,IAAI,YAAY,GAAG,EAAE,EAAE,CAAC;QACtB,4CAA4C;QAC5C,GAAG,CAAC,YAAY,GAAG,IAAI,CAAC;QACxB,GAAG,CAAC,aAAa,GAAG,GAAG,CAAC;QACxB,GAAG,CAAC,iBAAiB,GAAG,CAAC,CAAC;QAC1B,GAAG,CAAC,sBAAsB,GAAG,GAAG,CAAC;QACjC,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC,SAAS;QAC7B,GAAG,CAAC,uBAAuB,GAAG,CAAC,CAAC;QAChC,GAAG,CAAC,qBAAqB,GAAG,CAAC,CAAC;IAChC,CAAC;SAAM,IAAI,YAAY,GAAG,GAAG,EAAE,CAAC;QAC9B,oBAAoB;QACpB,GAAG,CAAC,YAAY,GAAG,IAAI,CAAC;QACxB,GAAG,CAAC,aAAa,GAAG,IAAI,CAAC;QACzB,GAAG,CAAC,iBAAiB,GAAG,CAAC,CAAC;QAC1B,GAAG,CAAC,sBAAsB,GAAG,GAAG,CAAC;QACjC,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC;QACnB,GAAG,CAAC,uBAAuB,GAAG,CAAC,CAAC;QAChC,GAAG,CAAC,qBAAqB,GAAG,CAAC,CAAC;IAChC,CAAC;SAAM,IAAI,YAAY,GAAG,GAAG,EAAE,CAAC;QAC9B,mBAAmB;QACnB,GAAG,CAAC,YAAY,GAAG,IAAI,CAAC;QACxB,GAAG,CAAC,aAAa,GAAG,GAAG,CAAC;QACxB,GAAG,CAAC,iBAAiB,GAAG,EAAE,CAAC;QAC3B,GAAG,CAAC,sBAAsB,GAAG,GAAG,CAAC;QACjC,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC,SAAS;QAC7B,GAAG,CAAC,uBAAuB,GAAG,CAAC,CAAC;QAChC,GAAG,CAAC,qBAAqB,GAAG,CAAC,CAAC;IAChC,CAAC;SAAM,CAAC;QACN,+CAA+C;QAC/C,GAAG,CAAC,YAAY,GAAG,IAAI,CAAC;QACxB,GAAG,CAAC,aAAa,GAAG,IAAI,CAAC;QACzB,GAAG,CAAC,iBAAiB,GAAG,EAAE,CAAC;QAC3B,GAAG,CAAC,sBAAsB,GAAG,IAAI,CAAC;QAClC,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC,SAAS;QAC7B,GAAG,CAAC,uBAAuB,GAAG,CAAC,CAAC;QAChC,GAAG,CAAC,qBAAqB,GAAG,CAAC,CAAC;QAC9B,GAAG,CAAC,yBAAyB,GAAG,EAAE,CAAC;IACrC,CAAC;IAED,wCAAwC;IACxC,IAAI,YAAY,GAAG,GAAG,EAAE,CAAC;QACvB,GAAG,CAAC,iBAAiB,GAAG,EAAE,CAAC,CAAC,iBAAiB;IAC/C,CAAC;SAAM,IAAI,YAAY,GAAG,EAAE,EAAE,CAAC;QAC7B,GAAG,CAAC,iBAAiB,GAAG,EAAE,CAAC,CAAC,2BAA2B;IACzD,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { TradeRecord } from '../db/repositories/trade.repository.js';
|
|
2
|
+
export interface DetectedChain {
|
|
3
|
+
pair: string;
|
|
4
|
+
type: 'winning_streak' | 'losing_streak';
|
|
5
|
+
length: number;
|
|
6
|
+
fingerprints: string[];
|
|
7
|
+
total_profit: number;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Detect winning/losing streaks from recent trade outcomes.
|
|
11
|
+
* Ported from tradingBrain.js _detectChain().
|
|
12
|
+
*
|
|
13
|
+
* @param recentTrades - Last N trades (should be ~10)
|
|
14
|
+
* @param latestTrade - The most recent trade
|
|
15
|
+
* @param minLength - Minimum consecutive trades for a chain (default: 3)
|
|
16
|
+
*/
|
|
17
|
+
export declare function detectChain(recentTrades: TradeRecord[], latestTrade: TradeRecord, minLength?: number): DetectedChain | null;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detect winning/losing streaks from recent trade outcomes.
|
|
3
|
+
* Ported from tradingBrain.js _detectChain().
|
|
4
|
+
*
|
|
5
|
+
* @param recentTrades - Last N trades (should be ~10)
|
|
6
|
+
* @param latestTrade - The most recent trade
|
|
7
|
+
* @param minLength - Minimum consecutive trades for a chain (default: 3)
|
|
8
|
+
*/
|
|
9
|
+
export function detectChain(recentTrades, latestTrade, minLength = 3) {
|
|
10
|
+
if (recentTrades.length < minLength)
|
|
11
|
+
return null;
|
|
12
|
+
const recent = recentTrades.slice(-5);
|
|
13
|
+
const samePair = recent.filter(o => o.pair === latestTrade.pair);
|
|
14
|
+
if (samePair.length < minLength)
|
|
15
|
+
return null;
|
|
16
|
+
const lastThree = samePair.slice(-minLength);
|
|
17
|
+
const allLosses = lastThree.every(o => o.win === 0);
|
|
18
|
+
const allWins = lastThree.every(o => o.win === 1);
|
|
19
|
+
if (!allLosses && !allWins)
|
|
20
|
+
return null;
|
|
21
|
+
return {
|
|
22
|
+
pair: latestTrade.pair,
|
|
23
|
+
type: allLosses ? 'losing_streak' : 'winning_streak',
|
|
24
|
+
length: lastThree.length,
|
|
25
|
+
fingerprints: lastThree.map(o => o.fingerprint),
|
|
26
|
+
total_profit: lastThree.reduce((s, o) => s + o.profit_pct, 0),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=chain-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chain-detector.js","sourceRoot":"","sources":["../../src/learning/chain-detector.ts"],"names":[],"mappings":"AAUA;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CACzB,YAA2B,EAC3B,WAAwB,EACxB,YAAoB,CAAC;IAErB,IAAI,YAAY,CAAC,MAAM,GAAG,SAAS;QAAE,OAAO,IAAI,CAAC;IAEjD,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACtC,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,IAAI,CAAC,CAAC;IACjE,IAAI,QAAQ,CAAC,MAAM,GAAG,SAAS;QAAE,OAAO,IAAI,CAAC;IAE7C,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC;IAC7C,MAAM,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;IACpD,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;IAElD,IAAI,CAAC,SAAS,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAExC,OAAO;QACL,IAAI,EAAE,WAAW,CAAC,IAAI;QACtB,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,gBAAgB;QACpD,MAAM,EAAE,SAAS,CAAC,MAAM;QACxB,YAAY,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC;QAC/C,YAAY,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC;KAC9D,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { TradeRepository } from '../db/repositories/trade.repository.js';
|
|
2
|
+
import type { RuleRepository } from '../db/repositories/rule.repository.js';
|
|
3
|
+
import type { ChainRepository } from '../db/repositories/chain.repository.js';
|
|
4
|
+
import type { CalibrationRepository } from '../db/repositories/calibration.repository.js';
|
|
5
|
+
import type { SynapseManager } from '../synapses/synapse-manager.js';
|
|
6
|
+
import type { WeightedGraph } from '../graph/weighted-graph.js';
|
|
7
|
+
import type { CalibrationConfig, LearningConfig } from '../types/config.types.js';
|
|
8
|
+
export declare class LearningEngine {
|
|
9
|
+
private learningConfig;
|
|
10
|
+
private cal;
|
|
11
|
+
private tradeRepo;
|
|
12
|
+
private ruleRepo;
|
|
13
|
+
private chainRepo;
|
|
14
|
+
private calRepo;
|
|
15
|
+
private synapseManager;
|
|
16
|
+
private graph;
|
|
17
|
+
private timer;
|
|
18
|
+
private lastPatternExtraction;
|
|
19
|
+
private lastDecay;
|
|
20
|
+
private logger;
|
|
21
|
+
constructor(learningConfig: LearningConfig, cal: CalibrationConfig, tradeRepo: TradeRepository, ruleRepo: RuleRepository, chainRepo: ChainRepository, calRepo: CalibrationRepository, synapseManager: SynapseManager, graph: WeightedGraph);
|
|
22
|
+
start(): void;
|
|
23
|
+
stop(): void;
|
|
24
|
+
getCalibration(): CalibrationConfig;
|
|
25
|
+
runCycle(): void;
|
|
26
|
+
/** Manual trigger for a full learning cycle */
|
|
27
|
+
runManual(): {
|
|
28
|
+
rules: number;
|
|
29
|
+
calibration: CalibrationConfig;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { extractPatterns } from './pattern-extractor.js';
|
|
2
|
+
import { calibrate } from './calibrator.js';
|
|
3
|
+
import { getLogger } from '../utils/logger.js';
|
|
4
|
+
import { getEventBus } from '../utils/events.js';
|
|
5
|
+
export class LearningEngine {
|
|
6
|
+
learningConfig;
|
|
7
|
+
cal;
|
|
8
|
+
tradeRepo;
|
|
9
|
+
ruleRepo;
|
|
10
|
+
chainRepo;
|
|
11
|
+
calRepo;
|
|
12
|
+
synapseManager;
|
|
13
|
+
graph;
|
|
14
|
+
timer = null;
|
|
15
|
+
lastPatternExtraction = 0;
|
|
16
|
+
lastDecay = 0;
|
|
17
|
+
logger = getLogger();
|
|
18
|
+
constructor(learningConfig, cal, tradeRepo, ruleRepo, chainRepo, calRepo, synapseManager, graph) {
|
|
19
|
+
this.learningConfig = learningConfig;
|
|
20
|
+
this.cal = cal;
|
|
21
|
+
this.tradeRepo = tradeRepo;
|
|
22
|
+
this.ruleRepo = ruleRepo;
|
|
23
|
+
this.chainRepo = chainRepo;
|
|
24
|
+
this.calRepo = calRepo;
|
|
25
|
+
this.synapseManager = synapseManager;
|
|
26
|
+
this.graph = graph;
|
|
27
|
+
}
|
|
28
|
+
start() {
|
|
29
|
+
this.timer = setInterval(() => this.runCycle(), this.learningConfig.intervalMs);
|
|
30
|
+
this.logger.info(`Learning engine started (interval: ${this.learningConfig.intervalMs}ms)`);
|
|
31
|
+
}
|
|
32
|
+
stop() {
|
|
33
|
+
if (this.timer) {
|
|
34
|
+
clearInterval(this.timer);
|
|
35
|
+
this.timer = null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
getCalibration() {
|
|
39
|
+
return { ...this.cal };
|
|
40
|
+
}
|
|
41
|
+
runCycle() {
|
|
42
|
+
const bus = getEventBus();
|
|
43
|
+
const outcomeCount = this.tradeRepo.count();
|
|
44
|
+
// Pattern extraction
|
|
45
|
+
if (outcomeCount - this.lastPatternExtraction >= this.cal.patternExtractionInterval) {
|
|
46
|
+
const trades = this.tradeRepo.getAll();
|
|
47
|
+
const rules = extractPatterns(trades, this.cal);
|
|
48
|
+
if (rules.length > 0) {
|
|
49
|
+
this.ruleRepo.replaceAll(rules);
|
|
50
|
+
this.lastPatternExtraction = outcomeCount;
|
|
51
|
+
this.logger.info(`Extracted ${rules.length} rules from ${trades.length} trades`);
|
|
52
|
+
bus.emit('patterns:extracted', { ruleCount: rules.length });
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// Recalibrate every 25 trades
|
|
56
|
+
if (outcomeCount > 0 && outcomeCount % 25 === 0) {
|
|
57
|
+
const newCal = calibrate(this.cal, outcomeCount, this.synapseManager.count());
|
|
58
|
+
this.cal = newCal;
|
|
59
|
+
this.synapseManager.updateCalibration(newCal);
|
|
60
|
+
this.calRepo.save(newCal);
|
|
61
|
+
this.logger.info(`Recalibrated — lr: ${newCal.learningRate}, z: ${newCal.wilsonZ}, halfLife: ${newCal.decayHalfLifeDays}d`);
|
|
62
|
+
bus.emit('calibration:updated', { outcomeCount, learningRate: newCal.learningRate });
|
|
63
|
+
}
|
|
64
|
+
// Daily decay
|
|
65
|
+
const now = Date.now();
|
|
66
|
+
const dayMs = 86400000;
|
|
67
|
+
if (now - this.lastDecay > dayMs) {
|
|
68
|
+
const halfLifeMs = this.cal.decayHalfLifeDays * dayMs;
|
|
69
|
+
const synDecayed = this.synapseManager.runDecay();
|
|
70
|
+
this.graph.decayEdges(halfLifeMs);
|
|
71
|
+
this.lastDecay = now;
|
|
72
|
+
this.logger.info(`Decay applied — ${synDecayed} synapses, ${this.graph.getEdgeCount()} edges`);
|
|
73
|
+
bus.emit('decay:applied', { synapseCount: synDecayed, edgeCount: this.graph.getEdgeCount() });
|
|
74
|
+
}
|
|
75
|
+
// Prune old chains
|
|
76
|
+
this.chainRepo.pruneOldest(this.learningConfig.maxChains);
|
|
77
|
+
}
|
|
78
|
+
/** Manual trigger for a full learning cycle */
|
|
79
|
+
runManual() {
|
|
80
|
+
this.runCycle();
|
|
81
|
+
const rules = this.ruleRepo.getAll();
|
|
82
|
+
return { rules: rules.length, calibration: this.getCalibration() };
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=learning-engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"learning-engine.js","sourceRoot":"","sources":["../../src/learning/learning-engine.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,MAAM,OAAO,cAAc;IAOf;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IAbF,KAAK,GAA0C,IAAI,CAAC;IACpD,qBAAqB,GAAG,CAAC,CAAC;IAC1B,SAAS,GAAG,CAAC,CAAC;IACd,MAAM,GAAG,SAAS,EAAE,CAAC;IAE7B,YACU,cAA8B,EAC9B,GAAsB,EACtB,SAA0B,EAC1B,QAAwB,EACxB,SAA0B,EAC1B,OAA8B,EAC9B,cAA8B,EAC9B,KAAoB;QAPpB,mBAAc,GAAd,cAAc,CAAgB;QAC9B,QAAG,GAAH,GAAG,CAAmB;QACtB,cAAS,GAAT,SAAS,CAAiB;QAC1B,aAAQ,GAAR,QAAQ,CAAgB;QACxB,cAAS,GAAT,SAAS,CAAiB;QAC1B,YAAO,GAAP,OAAO,CAAuB;QAC9B,mBAAc,GAAd,cAAc,CAAgB;QAC9B,UAAK,GAAL,KAAK,CAAe;IAC3B,CAAC;IAEJ,KAAK;QACH,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;QAChF,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,sCAAsC,IAAI,CAAC,cAAc,CAAC,UAAU,KAAK,CAAC,CAAC;IAC9F,CAAC;IAED,IAAI;QACF,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC1B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QACpB,CAAC;IACH,CAAC;IAED,cAAc;QACZ,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACzB,CAAC;IAED,QAAQ;QACN,MAAM,GAAG,GAAG,WAAW,EAAE,CAAC;QAC1B,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;QAE5C,qBAAqB;QACrB,IAAI,YAAY,GAAG,IAAI,CAAC,qBAAqB,IAAI,IAAI,CAAC,GAAG,CAAC,yBAAyB,EAAE,CAAC;YACpF,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;YACvC,MAAM,KAAK,GAAG,eAAe,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;YAChD,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACrB,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;gBAChC,IAAI,CAAC,qBAAqB,GAAG,YAAY,CAAC;gBAC1C,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,aAAa,KAAK,CAAC,MAAM,eAAe,MAAM,CAAC,MAAM,SAAS,CAAC,CAAC;gBACjF,GAAG,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,SAAS,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;YAC9D,CAAC;QACH,CAAC;QAED,8BAA8B;QAC9B,IAAI,YAAY,GAAG,CAAC,IAAI,YAAY,GAAG,EAAE,KAAK,CAAC,EAAE,CAAC;YAChD,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,YAAY,EAAE,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC,CAAC;YAC9E,IAAI,CAAC,GAAG,GAAG,MAAM,CAAC;YAClB,IAAI,CAAC,cAAc,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;YAC9C,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC1B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,sBAAsB,MAAM,CAAC,YAAY,QAAQ,MAAM,CAAC,OAAO,eAAe,MAAM,CAAC,iBAAiB,GAAG,CAAC,CAAC;YAC5H,GAAG,CAAC,IAAI,CAAC,qBAAqB,EAAE,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC;QACvF,CAAC;QAED,cAAc;QACd,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,QAAQ,CAAC;QACvB,IAAI,GAAG,GAAG,IAAI,CAAC,SAAS,GAAG,KAAK,EAAE,CAAC;YACjC,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,iBAAiB,GAAG,KAAK,CAAC;YACtD,MAAM,UAAU,GAAG,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,CAAC;YAClD,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;YAClC,IAAI,CAAC,SAAS,GAAG,GAAG,CAAC;YACrB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,mBAAmB,UAAU,cAAc,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;YAC/F,GAAG,CAAC,IAAI,CAAC,eAAe,EAAE,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;QAChG,CAAC;QAED,mBAAmB;QACnB,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;IAC5D,CAAC;IAED,+CAA+C;IAC/C,SAAS;QACP,IAAI,CAAC,QAAQ,EAAE,CAAC;QAChB,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;QACrC,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;IACrE,CAAC;CACF"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { TradeRecord } from '../db/repositories/trade.repository.js';
|
|
2
|
+
import type { CalibrationConfig } from '../types/config.types.js';
|
|
3
|
+
export interface ExtractedRule {
|
|
4
|
+
pattern: string;
|
|
5
|
+
confidence: number;
|
|
6
|
+
sample_count: number;
|
|
7
|
+
win_rate: number;
|
|
8
|
+
avg_profit: number;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Extract trading rules from outcome data using fingerprint grouping + Wilson Score.
|
|
12
|
+
* Ported from tradingBrain.js _extractPatterns().
|
|
13
|
+
*/
|
|
14
|
+
export declare function extractPatterns(trades: TradeRecord[], cal: CalibrationConfig): ExtractedRule[];
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { fingerprintSimilarity } from '../signals/fingerprint.js';
|
|
2
|
+
import { wilsonScore } from '../signals/wilson-score.js';
|
|
3
|
+
/**
|
|
4
|
+
* Extract trading rules from outcome data using fingerprint grouping + Wilson Score.
|
|
5
|
+
* Ported from tradingBrain.js _extractPatterns().
|
|
6
|
+
*/
|
|
7
|
+
export function extractPatterns(trades, cal) {
|
|
8
|
+
if (trades.length < cal.patternMinSamples)
|
|
9
|
+
return [];
|
|
10
|
+
// Group by similar fingerprints (threshold: 0.7)
|
|
11
|
+
const groups = {};
|
|
12
|
+
for (const trade of trades) {
|
|
13
|
+
let assigned = false;
|
|
14
|
+
for (const key of Object.keys(groups)) {
|
|
15
|
+
if (fingerprintSimilarity(trade.fingerprint, key) >= 0.7) {
|
|
16
|
+
groups[key].push(trade);
|
|
17
|
+
assigned = true;
|
|
18
|
+
break;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
if (!assigned) {
|
|
22
|
+
groups[trade.fingerprint] = [trade];
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
const rules = [];
|
|
26
|
+
for (const [pattern, group] of Object.entries(groups)) {
|
|
27
|
+
if (group.length < cal.patternMinSamples)
|
|
28
|
+
continue;
|
|
29
|
+
const wins = group.filter(o => o.win === 1).length;
|
|
30
|
+
const total = group.length;
|
|
31
|
+
const winRate = wins / total;
|
|
32
|
+
const confidence = wilsonScore(wins, total, cal.wilsonZ);
|
|
33
|
+
if (confidence > cal.patternWilsonThreshold) {
|
|
34
|
+
const avgProfit = group.reduce((s, o) => s + o.profit_pct, 0) / total;
|
|
35
|
+
rules.push({ pattern, confidence, sample_count: total, win_rate: winRate, avg_profit: avgProfit });
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return rules.sort((a, b) => b.confidence - a.confidence);
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=pattern-extractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pattern-extractor.js","sourceRoot":"","sources":["../../src/learning/pattern-extractor.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAWzD;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,MAAqB,EAAE,GAAsB;IAC3E,IAAI,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,iBAAiB;QAAE,OAAO,EAAE,CAAC;IAErD,iDAAiD;IACjD,MAAM,MAAM,GAAkC,EAAE,CAAC;IACjD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,QAAQ,GAAG,KAAK,CAAC;QACrB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YACtC,IAAI,qBAAqB,CAAC,KAAK,CAAC,WAAW,EAAE,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC;gBACzD,MAAM,CAAC,GAAG,CAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBACzB,QAAQ,GAAG,IAAI,CAAC;gBAChB,MAAM;YACR,CAAC;QACH,CAAC;QACD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IAED,MAAM,KAAK,GAAoB,EAAE,CAAC;IAClC,KAAK,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACtD,IAAI,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC,iBAAiB;YAAE,SAAS;QAEnD,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;QACnD,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC;QAC3B,MAAM,OAAO,GAAG,IAAI,GAAG,KAAK,CAAC;QAC7B,MAAM,UAAU,GAAG,WAAW,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;QAEzD,IAAI,UAAU,GAAG,GAAG,CAAC,sBAAsB,EAAE,CAAC;YAC5C,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC;YACtE,KAAK,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC,CAAC;QACrG,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC;AAC3D,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { IpcRouter } from '../ipc/router.js';
|
|
2
|
+
export declare class McpHttpServer {
|
|
3
|
+
private port;
|
|
4
|
+
private router;
|
|
5
|
+
private server;
|
|
6
|
+
private transports;
|
|
7
|
+
private logger;
|
|
8
|
+
constructor(port: number, router: IpcRouter);
|
|
9
|
+
start(): void;
|
|
10
|
+
stop(): void;
|
|
11
|
+
getClientCount(): number;
|
|
12
|
+
private handleSSE;
|
|
13
|
+
private handleMessage;
|
|
14
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import http from 'node:http';
|
|
2
|
+
import { randomUUID } from 'node:crypto';
|
|
3
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
4
|
+
import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
|
|
5
|
+
import { getLogger } from '../utils/logger.js';
|
|
6
|
+
import { registerToolsDirect } from './tools.js';
|
|
7
|
+
export class McpHttpServer {
|
|
8
|
+
port;
|
|
9
|
+
router;
|
|
10
|
+
server = null;
|
|
11
|
+
transports = new Map();
|
|
12
|
+
logger = getLogger();
|
|
13
|
+
constructor(port, router) {
|
|
14
|
+
this.port = port;
|
|
15
|
+
this.router = router;
|
|
16
|
+
}
|
|
17
|
+
start() {
|
|
18
|
+
this.server = http.createServer((req, res) => {
|
|
19
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
20
|
+
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS');
|
|
21
|
+
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
|
|
22
|
+
if (req.method === 'OPTIONS') {
|
|
23
|
+
res.writeHead(204);
|
|
24
|
+
res.end();
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const url = new URL(req.url ?? '/', `http://localhost:${this.port}`);
|
|
28
|
+
if (url.pathname === '/sse' && req.method === 'GET') {
|
|
29
|
+
this.handleSSE(res);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
if (url.pathname === '/messages' && req.method === 'POST') {
|
|
33
|
+
this.handleMessage(req, res, url);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (url.pathname === '/' && req.method === 'GET') {
|
|
37
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
38
|
+
res.end(JSON.stringify({
|
|
39
|
+
name: 'trading-brain',
|
|
40
|
+
version: '1.0.0',
|
|
41
|
+
protocol: 'MCP',
|
|
42
|
+
transport: 'sse',
|
|
43
|
+
endpoints: { sse: '/sse', messages: '/messages' },
|
|
44
|
+
clients: this.transports.size,
|
|
45
|
+
}));
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
res.writeHead(404, { 'Content-Type': 'text/plain' });
|
|
49
|
+
res.end('Not Found');
|
|
50
|
+
});
|
|
51
|
+
this.server.listen(this.port, () => {
|
|
52
|
+
this.logger.info(`MCP HTTP server (SSE) started on http://localhost:${this.port}`);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
stop() {
|
|
56
|
+
for (const transport of this.transports.values()) {
|
|
57
|
+
try {
|
|
58
|
+
transport.close?.();
|
|
59
|
+
}
|
|
60
|
+
catch { /* ignore */ }
|
|
61
|
+
}
|
|
62
|
+
this.transports.clear();
|
|
63
|
+
this.server?.close();
|
|
64
|
+
this.server = null;
|
|
65
|
+
this.logger.info('MCP HTTP server stopped');
|
|
66
|
+
}
|
|
67
|
+
getClientCount() {
|
|
68
|
+
return this.transports.size;
|
|
69
|
+
}
|
|
70
|
+
async handleSSE(res) {
|
|
71
|
+
try {
|
|
72
|
+
const transport = new SSEServerTransport('/messages', res);
|
|
73
|
+
const sessionId = transport.sessionId ?? randomUUID();
|
|
74
|
+
this.transports.set(sessionId, transport);
|
|
75
|
+
const server = new McpServer({ name: 'trading-brain', version: '1.0.0' });
|
|
76
|
+
registerToolsDirect(server, this.router);
|
|
77
|
+
res.on('close', () => {
|
|
78
|
+
this.transports.delete(sessionId);
|
|
79
|
+
this.logger.debug(`MCP SSE client disconnected: ${sessionId}`);
|
|
80
|
+
});
|
|
81
|
+
await server.connect(transport);
|
|
82
|
+
this.logger.info(`MCP SSE client connected: ${sessionId}`);
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
this.logger.error('MCP SSE connection error:', err);
|
|
86
|
+
if (!res.headersSent) {
|
|
87
|
+
res.writeHead(500, { 'Content-Type': 'text/plain' });
|
|
88
|
+
res.end('Internal Server Error');
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
async handleMessage(req, res, url) {
|
|
93
|
+
try {
|
|
94
|
+
const sessionId = url.searchParams.get('sessionId');
|
|
95
|
+
if (!sessionId) {
|
|
96
|
+
res.writeHead(400, { 'Content-Type': 'text/plain' });
|
|
97
|
+
res.end('Missing sessionId parameter');
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
const transport = this.transports.get(sessionId);
|
|
101
|
+
if (!transport) {
|
|
102
|
+
res.writeHead(404, { 'Content-Type': 'text/plain' });
|
|
103
|
+
res.end('Session not found. Connect to /sse first.');
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
await transport.handlePostMessage(req, res);
|
|
107
|
+
}
|
|
108
|
+
catch (err) {
|
|
109
|
+
this.logger.error('MCP message error:', err);
|
|
110
|
+
if (!res.headersSent) {
|
|
111
|
+
res.writeHead(500, { 'Content-Type': 'text/plain' });
|
|
112
|
+
res.end('Internal Server Error');
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=http-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-server.js","sourceRoot":"","sources":["../../src/mcp/http-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function startMcpServer(): Promise<void>;
|