@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.
Files changed (247) hide show
  1. package/README.md +306 -0
  2. package/dist/api/server.d.ts +21 -0
  3. package/dist/api/server.js +157 -0
  4. package/dist/api/server.js.map +1 -0
  5. package/dist/cli/colors.d.ts +46 -0
  6. package/dist/cli/colors.js +70 -0
  7. package/dist/cli/colors.js.map +1 -0
  8. package/dist/cli/commands/config.d.ts +2 -0
  9. package/dist/cli/commands/config.js +70 -0
  10. package/dist/cli/commands/config.js.map +1 -0
  11. package/dist/cli/commands/doctor.d.ts +2 -0
  12. package/dist/cli/commands/doctor.js +61 -0
  13. package/dist/cli/commands/doctor.js.map +1 -0
  14. package/dist/cli/commands/export.d.ts +2 -0
  15. package/dist/cli/commands/export.js +23 -0
  16. package/dist/cli/commands/export.js.map +1 -0
  17. package/dist/cli/commands/import.d.ts +2 -0
  18. package/dist/cli/commands/import.js +42 -0
  19. package/dist/cli/commands/import.js.map +1 -0
  20. package/dist/cli/commands/insights.d.ts +2 -0
  21. package/dist/cli/commands/insights.js +29 -0
  22. package/dist/cli/commands/insights.js.map +1 -0
  23. package/dist/cli/commands/network.d.ts +2 -0
  24. package/dist/cli/commands/network.js +43 -0
  25. package/dist/cli/commands/network.js.map +1 -0
  26. package/dist/cli/commands/query.d.ts +2 -0
  27. package/dist/cli/commands/query.js +27 -0
  28. package/dist/cli/commands/query.js.map +1 -0
  29. package/dist/cli/commands/rules.d.ts +2 -0
  30. package/dist/cli/commands/rules.js +26 -0
  31. package/dist/cli/commands/rules.js.map +1 -0
  32. package/dist/cli/commands/start.d.ts +2 -0
  33. package/dist/cli/commands/start.js +86 -0
  34. package/dist/cli/commands/start.js.map +1 -0
  35. package/dist/cli/commands/status.d.ts +2 -0
  36. package/dist/cli/commands/status.js +58 -0
  37. package/dist/cli/commands/status.js.map +1 -0
  38. package/dist/cli/commands/stop.d.ts +2 -0
  39. package/dist/cli/commands/stop.js +34 -0
  40. package/dist/cli/commands/stop.js.map +1 -0
  41. package/dist/cli/ipc-helper.d.ts +2 -0
  42. package/dist/cli/ipc-helper.js +26 -0
  43. package/dist/cli/ipc-helper.js.map +1 -0
  44. package/dist/config.d.ts +2 -0
  45. package/dist/config.js +107 -0
  46. package/dist/config.js.map +1 -0
  47. package/dist/db/connection.d.ts +2 -0
  48. package/dist/db/connection.js +19 -0
  49. package/dist/db/connection.js.map +1 -0
  50. package/dist/db/migrations/001_core.d.ts +2 -0
  51. package/dist/db/migrations/001_core.js +42 -0
  52. package/dist/db/migrations/001_core.js.map +1 -0
  53. package/dist/db/migrations/002_synapses.d.ts +2 -0
  54. package/dist/db/migrations/002_synapses.js +43 -0
  55. package/dist/db/migrations/002_synapses.js.map +1 -0
  56. package/dist/db/migrations/003_learning.d.ts +2 -0
  57. package/dist/db/migrations/003_learning.js +48 -0
  58. package/dist/db/migrations/003_learning.js.map +1 -0
  59. package/dist/db/migrations/004_research.d.ts +2 -0
  60. package/dist/db/migrations/004_research.js +29 -0
  61. package/dist/db/migrations/004_research.js.map +1 -0
  62. package/dist/db/migrations/index.d.ts +2 -0
  63. package/dist/db/migrations/index.js +45 -0
  64. package/dist/db/migrations/index.js.map +1 -0
  65. package/dist/db/repositories/calibration.repository.d.ts +25 -0
  66. package/dist/db/repositories/calibration.repository.js +66 -0
  67. package/dist/db/repositories/calibration.repository.js.map +1 -0
  68. package/dist/db/repositories/chain.repository.d.ts +28 -0
  69. package/dist/db/repositories/chain.repository.js +52 -0
  70. package/dist/db/repositories/chain.repository.js.map +1 -0
  71. package/dist/db/repositories/graph.repository.d.ts +33 -0
  72. package/dist/db/repositories/graph.repository.js +73 -0
  73. package/dist/db/repositories/graph.repository.js.map +1 -0
  74. package/dist/db/repositories/insight.repository.d.ts +30 -0
  75. package/dist/db/repositories/insight.repository.js +60 -0
  76. package/dist/db/repositories/insight.repository.js.map +1 -0
  77. package/dist/db/repositories/rule.repository.d.ts +35 -0
  78. package/dist/db/repositories/rule.repository.js +48 -0
  79. package/dist/db/repositories/rule.repository.js.map +1 -0
  80. package/dist/db/repositories/signal.repository.d.ts +17 -0
  81. package/dist/db/repositories/signal.repository.js +35 -0
  82. package/dist/db/repositories/signal.repository.js.map +1 -0
  83. package/dist/db/repositories/synapse.repository.d.ts +25 -0
  84. package/dist/db/repositories/synapse.repository.js +50 -0
  85. package/dist/db/repositories/synapse.repository.js.map +1 -0
  86. package/dist/db/repositories/trade.repository.d.ts +36 -0
  87. package/dist/db/repositories/trade.repository.js +64 -0
  88. package/dist/db/repositories/trade.repository.js.map +1 -0
  89. package/dist/graph/weighted-graph.d.ts +58 -0
  90. package/dist/graph/weighted-graph.js +149 -0
  91. package/dist/graph/weighted-graph.js.map +1 -0
  92. package/dist/index.d.ts +2 -0
  93. package/dist/index.js +49 -0
  94. package/dist/index.js.map +1 -0
  95. package/dist/ipc/client.d.ts +16 -0
  96. package/dist/ipc/client.js +95 -0
  97. package/dist/ipc/client.js.map +1 -0
  98. package/dist/ipc/protocol.d.ts +8 -0
  99. package/dist/ipc/protocol.js +29 -0
  100. package/dist/ipc/protocol.js.map +1 -0
  101. package/dist/ipc/router.d.ts +32 -0
  102. package/dist/ipc/router.js +70 -0
  103. package/dist/ipc/router.js.map +1 -0
  104. package/dist/ipc/server.d.ts +18 -0
  105. package/dist/ipc/server.js +142 -0
  106. package/dist/ipc/server.js.map +1 -0
  107. package/dist/learning/calibrator.d.ts +6 -0
  108. package/dist/learning/calibrator.js +57 -0
  109. package/dist/learning/calibrator.js.map +1 -0
  110. package/dist/learning/chain-detector.d.ts +17 -0
  111. package/dist/learning/chain-detector.js +29 -0
  112. package/dist/learning/chain-detector.js.map +1 -0
  113. package/dist/learning/learning-engine.d.ts +31 -0
  114. package/dist/learning/learning-engine.js +85 -0
  115. package/dist/learning/learning-engine.js.map +1 -0
  116. package/dist/learning/pattern-extractor.d.ts +14 -0
  117. package/dist/learning/pattern-extractor.js +40 -0
  118. package/dist/learning/pattern-extractor.js.map +1 -0
  119. package/dist/mcp/http-server.d.ts +14 -0
  120. package/dist/mcp/http-server.js +117 -0
  121. package/dist/mcp/http-server.js.map +1 -0
  122. package/dist/mcp/server.d.ts +1 -0
  123. package/dist/mcp/server.js +67 -0
  124. package/dist/mcp/server.js.map +1 -0
  125. package/dist/mcp/tools.d.ts +7 -0
  126. package/dist/mcp/tools.js +158 -0
  127. package/dist/mcp/tools.js.map +1 -0
  128. package/dist/research/research-engine.d.ts +21 -0
  129. package/dist/research/research-engine.js +204 -0
  130. package/dist/research/research-engine.js.map +1 -0
  131. package/dist/services/analytics.service.d.ts +16 -0
  132. package/dist/services/analytics.service.js +64 -0
  133. package/dist/services/analytics.service.js.map +1 -0
  134. package/dist/services/insight.service.d.ts +11 -0
  135. package/dist/services/insight.service.js +25 -0
  136. package/dist/services/insight.service.js.map +1 -0
  137. package/dist/services/signal.service.d.ts +22 -0
  138. package/dist/services/signal.service.js +96 -0
  139. package/dist/services/signal.service.js.map +1 -0
  140. package/dist/services/strategy.service.d.ts +29 -0
  141. package/dist/services/strategy.service.js +115 -0
  142. package/dist/services/strategy.service.js.map +1 -0
  143. package/dist/services/synapse.service.d.ts +20 -0
  144. package/dist/services/synapse.service.js +48 -0
  145. package/dist/services/synapse.service.js.map +1 -0
  146. package/dist/services/trade.service.d.ts +37 -0
  147. package/dist/services/trade.service.js +114 -0
  148. package/dist/services/trade.service.js.map +1 -0
  149. package/dist/signals/fingerprint.d.ts +29 -0
  150. package/dist/signals/fingerprint.js +98 -0
  151. package/dist/signals/fingerprint.js.map +1 -0
  152. package/dist/signals/wilson-score.d.ts +10 -0
  153. package/dist/signals/wilson-score.js +19 -0
  154. package/dist/signals/wilson-score.js.map +1 -0
  155. package/dist/synapses/decay.d.ts +6 -0
  156. package/dist/synapses/decay.js +17 -0
  157. package/dist/synapses/decay.js.map +1 -0
  158. package/dist/synapses/hebbian.d.ts +11 -0
  159. package/dist/synapses/hebbian.js +21 -0
  160. package/dist/synapses/hebbian.js.map +1 -0
  161. package/dist/synapses/synapse-manager.d.ts +22 -0
  162. package/dist/synapses/synapse-manager.js +99 -0
  163. package/dist/synapses/synapse-manager.js.map +1 -0
  164. package/dist/trading-core.d.ts +17 -0
  165. package/dist/trading-core.js +235 -0
  166. package/dist/trading-core.js.map +1 -0
  167. package/dist/types/config.types.d.ts +52 -0
  168. package/dist/types/config.types.js +2 -0
  169. package/dist/types/config.types.js.map +1 -0
  170. package/dist/types/ipc.types.d.ts +11 -0
  171. package/dist/types/ipc.types.js +2 -0
  172. package/dist/types/ipc.types.js.map +1 -0
  173. package/dist/utils/events.d.ts +48 -0
  174. package/dist/utils/events.js +23 -0
  175. package/dist/utils/events.js.map +1 -0
  176. package/dist/utils/hash.d.ts +1 -0
  177. package/dist/utils/hash.js +5 -0
  178. package/dist/utils/hash.js.map +1 -0
  179. package/dist/utils/logger.d.ts +8 -0
  180. package/dist/utils/logger.js +39 -0
  181. package/dist/utils/logger.js.map +1 -0
  182. package/dist/utils/paths.d.ts +3 -0
  183. package/dist/utils/paths.js +18 -0
  184. package/dist/utils/paths.js.map +1 -0
  185. package/package.json +47 -0
  186. package/src/api/server.ts +160 -0
  187. package/src/cli/colors.ts +80 -0
  188. package/src/cli/commands/config.ts +76 -0
  189. package/src/cli/commands/doctor.ts +62 -0
  190. package/src/cli/commands/export.ts +24 -0
  191. package/src/cli/commands/import.ts +44 -0
  192. package/src/cli/commands/insights.ts +30 -0
  193. package/src/cli/commands/network.ts +43 -0
  194. package/src/cli/commands/query.ts +28 -0
  195. package/src/cli/commands/rules.ts +27 -0
  196. package/src/cli/commands/start.ts +93 -0
  197. package/src/cli/commands/status.ts +64 -0
  198. package/src/cli/commands/stop.ts +33 -0
  199. package/src/cli/ipc-helper.ts +22 -0
  200. package/src/config.ts +103 -0
  201. package/src/db/connection.ts +22 -0
  202. package/src/db/migrations/001_core.ts +43 -0
  203. package/src/db/migrations/002_synapses.ts +44 -0
  204. package/src/db/migrations/003_learning.ts +49 -0
  205. package/src/db/migrations/004_research.ts +30 -0
  206. package/src/db/migrations/index.ts +60 -0
  207. package/src/db/repositories/calibration.repository.ts +86 -0
  208. package/src/db/repositories/chain.repository.ts +70 -0
  209. package/src/db/repositories/graph.repository.ts +103 -0
  210. package/src/db/repositories/insight.repository.ts +80 -0
  211. package/src/db/repositories/rule.repository.ts +67 -0
  212. package/src/db/repositories/signal.repository.ts +48 -0
  213. package/src/db/repositories/synapse.repository.ts +71 -0
  214. package/src/db/repositories/trade.repository.ts +97 -0
  215. package/src/graph/weighted-graph.ts +194 -0
  216. package/src/index.ts +55 -0
  217. package/src/ipc/client.ts +112 -0
  218. package/src/ipc/protocol.ts +35 -0
  219. package/src/ipc/router.ts +113 -0
  220. package/src/ipc/server.ts +150 -0
  221. package/src/learning/calibrator.ts +57 -0
  222. package/src/learning/chain-detector.ts +43 -0
  223. package/src/learning/learning-engine.ts +94 -0
  224. package/src/learning/pattern-extractor.ts +53 -0
  225. package/src/mcp/http-server.ts +118 -0
  226. package/src/mcp/server.ts +72 -0
  227. package/src/mcp/tools.ts +256 -0
  228. package/src/research/research-engine.ts +223 -0
  229. package/src/services/analytics.service.ts +68 -0
  230. package/src/services/insight.service.ts +29 -0
  231. package/src/services/signal.service.ts +109 -0
  232. package/src/services/strategy.service.ts +130 -0
  233. package/src/services/synapse.service.ts +58 -0
  234. package/src/services/trade.service.ts +139 -0
  235. package/src/signals/fingerprint.ts +93 -0
  236. package/src/signals/wilson-score.ts +17 -0
  237. package/src/synapses/decay.ts +19 -0
  238. package/src/synapses/hebbian.ts +23 -0
  239. package/src/synapses/synapse-manager.ts +112 -0
  240. package/src/trading-core.ts +285 -0
  241. package/src/types/config.types.ts +60 -0
  242. package/src/types/ipc.types.ts +8 -0
  243. package/src/utils/events.ts +42 -0
  244. package/src/utils/hash.ts +5 -0
  245. package/src/utils/logger.ts +48 -0
  246. package/src/utils/paths.ts +19 -0
  247. package/tsconfig.json +18 -0
@@ -0,0 +1,86 @@
1
+ import type Database from 'better-sqlite3';
2
+ import type { Statement } from 'better-sqlite3';
3
+ import type { CalibrationConfig } from '../../types/config.types.js';
4
+
5
+ export interface CalibrationRecord {
6
+ id: string;
7
+ learning_rate: number;
8
+ weaken_penalty: number;
9
+ decay_half_life_days: number;
10
+ pattern_extraction_interval: number;
11
+ pattern_min_samples: number;
12
+ pattern_wilson_threshold: number;
13
+ wilson_z: number;
14
+ spreading_activation_decay: number;
15
+ spreading_activation_threshold: number;
16
+ min_activations_for_weight: number;
17
+ min_outcomes_for_weights: number;
18
+ last_calibration: string;
19
+ updated_at: string;
20
+ }
21
+
22
+ export class CalibrationRepository {
23
+ private stmts: Record<string, Statement>;
24
+
25
+ constructor(private db: Database.Database) {
26
+ this.stmts = {
27
+ upsert: db.prepare(`
28
+ INSERT INTO calibration (id, learning_rate, weaken_penalty, decay_half_life_days,
29
+ pattern_extraction_interval, pattern_min_samples, pattern_wilson_threshold,
30
+ wilson_z, spreading_activation_decay, spreading_activation_threshold,
31
+ min_activations_for_weight, min_outcomes_for_weights, last_calibration, updated_at)
32
+ VALUES ('main', @learning_rate, @weaken_penalty, @decay_half_life_days,
33
+ @pattern_extraction_interval, @pattern_min_samples, @pattern_wilson_threshold,
34
+ @wilson_z, @spreading_activation_decay, @spreading_activation_threshold,
35
+ @min_activations_for_weight, @min_outcomes_for_weights, datetime('now'), datetime('now'))
36
+ ON CONFLICT(id) DO UPDATE SET
37
+ learning_rate = @learning_rate, weaken_penalty = @weaken_penalty,
38
+ decay_half_life_days = @decay_half_life_days,
39
+ pattern_extraction_interval = @pattern_extraction_interval,
40
+ pattern_min_samples = @pattern_min_samples,
41
+ pattern_wilson_threshold = @pattern_wilson_threshold,
42
+ wilson_z = @wilson_z,
43
+ spreading_activation_decay = @spreading_activation_decay,
44
+ spreading_activation_threshold = @spreading_activation_threshold,
45
+ min_activations_for_weight = @min_activations_for_weight,
46
+ min_outcomes_for_weights = @min_outcomes_for_weights,
47
+ last_calibration = datetime('now'), updated_at = datetime('now')
48
+ `),
49
+ get: db.prepare('SELECT * FROM calibration WHERE id = "main"'),
50
+ };
51
+ }
52
+
53
+ save(cal: CalibrationConfig): void {
54
+ this.stmts['upsert']!.run({
55
+ learning_rate: cal.learningRate,
56
+ weaken_penalty: cal.weakenPenalty,
57
+ decay_half_life_days: cal.decayHalfLifeDays,
58
+ pattern_extraction_interval: cal.patternExtractionInterval,
59
+ pattern_min_samples: cal.patternMinSamples,
60
+ pattern_wilson_threshold: cal.patternWilsonThreshold,
61
+ wilson_z: cal.wilsonZ,
62
+ spreading_activation_decay: cal.spreadingActivationDecay,
63
+ spreading_activation_threshold: cal.spreadingActivationThreshold,
64
+ min_activations_for_weight: cal.minActivationsForWeight,
65
+ min_outcomes_for_weights: cal.minOutcomesForWeights,
66
+ });
67
+ }
68
+
69
+ get(): CalibrationConfig | null {
70
+ const row = this.stmts['get']!.get() as CalibrationRecord | undefined;
71
+ if (!row) return null;
72
+ return {
73
+ learningRate: row.learning_rate,
74
+ weakenPenalty: row.weaken_penalty,
75
+ decayHalfLifeDays: row.decay_half_life_days,
76
+ patternExtractionInterval: row.pattern_extraction_interval,
77
+ patternMinSamples: row.pattern_min_samples,
78
+ patternWilsonThreshold: row.pattern_wilson_threshold,
79
+ wilsonZ: row.wilson_z,
80
+ spreadingActivationDecay: row.spreading_activation_decay,
81
+ spreadingActivationThreshold: row.spreading_activation_threshold,
82
+ minActivationsForWeight: row.min_activations_for_weight,
83
+ minOutcomesForWeights: row.min_outcomes_for_weights,
84
+ };
85
+ }
86
+ }
@@ -0,0 +1,70 @@
1
+ import type Database from 'better-sqlite3';
2
+ import type { Statement } from 'better-sqlite3';
3
+
4
+ export interface ChainRecord {
5
+ id: number;
6
+ pair: string;
7
+ type: string;
8
+ length: number;
9
+ fingerprints_json: string;
10
+ total_profit: number;
11
+ created_at: string;
12
+ }
13
+
14
+ export class ChainRepository {
15
+ private stmts: Record<string, Statement>;
16
+
17
+ constructor(private db: Database.Database) {
18
+ this.stmts = {
19
+ create: db.prepare(`
20
+ INSERT INTO chains (pair, type, length, fingerprints_json, total_profit)
21
+ VALUES (@pair, @type, @length, @fingerprints_json, @total_profit)
22
+ `),
23
+ getAll: db.prepare('SELECT * FROM chains ORDER BY created_at DESC'),
24
+ getRecent: db.prepare('SELECT * FROM chains ORDER BY created_at DESC LIMIT ?'),
25
+ getByPair: db.prepare('SELECT * FROM chains WHERE pair = ? ORDER BY created_at DESC'),
26
+ getByType: db.prepare('SELECT * FROM chains WHERE type = ? ORDER BY created_at DESC'),
27
+ count: db.prepare('SELECT COUNT(*) as count FROM chains'),
28
+ deleteOldest: db.prepare('DELETE FROM chains WHERE id IN (SELECT id FROM chains ORDER BY created_at ASC LIMIT ?)'),
29
+ };
30
+ }
31
+
32
+ create(data: { pair: string; type: string; length: number; fingerprints: string[]; total_profit: number }): number {
33
+ const result = this.stmts['create']!.run({
34
+ pair: data.pair,
35
+ type: data.type,
36
+ length: data.length,
37
+ fingerprints_json: JSON.stringify(data.fingerprints),
38
+ total_profit: data.total_profit,
39
+ });
40
+ return result.lastInsertRowid as number;
41
+ }
42
+
43
+ getAll(): ChainRecord[] {
44
+ return this.stmts['getAll']!.all() as ChainRecord[];
45
+ }
46
+
47
+ getRecent(limit: number = 10): ChainRecord[] {
48
+ return this.stmts['getRecent']!.all(limit) as ChainRecord[];
49
+ }
50
+
51
+ getByPair(pair: string): ChainRecord[] {
52
+ return this.stmts['getByPair']!.all(pair) as ChainRecord[];
53
+ }
54
+
55
+ getByType(type: string): ChainRecord[] {
56
+ return this.stmts['getByType']!.all(type) as ChainRecord[];
57
+ }
58
+
59
+ count(): number {
60
+ const row = this.stmts['count']!.get() as { count: number };
61
+ return row.count;
62
+ }
63
+
64
+ pruneOldest(keepCount: number): void {
65
+ const total = this.count();
66
+ if (total > keepCount) {
67
+ this.stmts['deleteOldest']!.run(total - keepCount);
68
+ }
69
+ }
70
+ }
@@ -0,0 +1,103 @@
1
+ import type Database from 'better-sqlite3';
2
+ import type { Statement } from 'better-sqlite3';
3
+
4
+ export interface GraphNodeRecord {
5
+ id: string;
6
+ type: string;
7
+ label: string;
8
+ activation: number;
9
+ total_activations: number;
10
+ }
11
+
12
+ export interface GraphEdgeRecord {
13
+ id: string;
14
+ source: string;
15
+ target: string;
16
+ weight: number;
17
+ activations: number;
18
+ last_activated: string;
19
+ }
20
+
21
+ export class GraphRepository {
22
+ private stmts: Record<string, Statement>;
23
+
24
+ constructor(private db: Database.Database) {
25
+ this.stmts = {
26
+ upsertNode: db.prepare(`
27
+ INSERT INTO graph_nodes (id, type, label, activation, total_activations)
28
+ VALUES (@id, @type, @label, @activation, @total_activations)
29
+ ON CONFLICT(id) DO UPDATE SET
30
+ activation = @activation, total_activations = @total_activations
31
+ `),
32
+ upsertEdge: db.prepare(`
33
+ INSERT INTO graph_edges (id, source, target, weight, activations, last_activated)
34
+ VALUES (@id, @source, @target, @weight, @activations, @last_activated)
35
+ ON CONFLICT(id) DO UPDATE SET
36
+ weight = @weight, activations = @activations, last_activated = @last_activated
37
+ `),
38
+ getAllNodes: db.prepare('SELECT * FROM graph_nodes'),
39
+ getAllEdges: db.prepare('SELECT * FROM graph_edges'),
40
+ getNode: db.prepare('SELECT * FROM graph_nodes WHERE id = ?'),
41
+ getEdge: db.prepare('SELECT * FROM graph_edges WHERE id = ?'),
42
+ getEdgesFrom: db.prepare('SELECT * FROM graph_edges WHERE source = ?'),
43
+ getEdgesTo: db.prepare('SELECT * FROM graph_edges WHERE target = ?'),
44
+ getEdgesFor: db.prepare('SELECT * FROM graph_edges WHERE source = ? OR target = ?'),
45
+ nodeCount: db.prepare('SELECT COUNT(*) as count FROM graph_nodes'),
46
+ edgeCount: db.prepare('SELECT COUNT(*) as count FROM graph_edges'),
47
+ updateEdgeWeight: db.prepare('UPDATE graph_edges SET weight = ?, activations = activations + 1, last_activated = datetime("now") WHERE id = ?'),
48
+ deleteAllNodes: db.prepare('DELETE FROM graph_nodes'),
49
+ deleteAllEdges: db.prepare('DELETE FROM graph_edges'),
50
+ };
51
+ }
52
+
53
+ upsertNode(node: GraphNodeRecord): void {
54
+ this.stmts['upsertNode']!.run(node);
55
+ }
56
+
57
+ upsertEdge(edge: GraphEdgeRecord): void {
58
+ this.stmts['upsertEdge']!.run(edge);
59
+ }
60
+
61
+ getAllNodes(): GraphNodeRecord[] {
62
+ return this.stmts['getAllNodes']!.all() as GraphNodeRecord[];
63
+ }
64
+
65
+ getAllEdges(): GraphEdgeRecord[] {
66
+ return this.stmts['getAllEdges']!.all() as GraphEdgeRecord[];
67
+ }
68
+
69
+ getNode(id: string): GraphNodeRecord | undefined {
70
+ return this.stmts['getNode']!.get(id) as GraphNodeRecord | undefined;
71
+ }
72
+
73
+ getEdge(id: string): GraphEdgeRecord | undefined {
74
+ return this.stmts['getEdge']!.get(id) as GraphEdgeRecord | undefined;
75
+ }
76
+
77
+ getEdgesFrom(nodeId: string): GraphEdgeRecord[] {
78
+ return this.stmts['getEdgesFrom']!.all(nodeId) as GraphEdgeRecord[];
79
+ }
80
+
81
+ getEdgesFor(nodeId: string): GraphEdgeRecord[] {
82
+ return this.stmts['getEdgesFor']!.all(nodeId, nodeId) as GraphEdgeRecord[];
83
+ }
84
+
85
+ nodeCount(): number {
86
+ const row = this.stmts['nodeCount']!.get() as { count: number };
87
+ return row.count;
88
+ }
89
+
90
+ edgeCount(): number {
91
+ const row = this.stmts['edgeCount']!.get() as { count: number };
92
+ return row.count;
93
+ }
94
+
95
+ updateEdgeWeight(id: string, weight: number): void {
96
+ this.stmts['updateEdgeWeight']!.run(weight, id);
97
+ }
98
+
99
+ clearAll(): void {
100
+ this.stmts['deleteAllEdges']!.run();
101
+ this.stmts['deleteAllNodes']!.run();
102
+ }
103
+ }
@@ -0,0 +1,80 @@
1
+ import type Database from 'better-sqlite3';
2
+ import type { Statement } from 'better-sqlite3';
3
+
4
+ export interface InsightRecord {
5
+ id: number;
6
+ type: string;
7
+ severity: string;
8
+ title: string;
9
+ description: string;
10
+ data_json: string | null;
11
+ created_at: string;
12
+ }
13
+
14
+ export class InsightRepository {
15
+ private stmts: Record<string, Statement>;
16
+
17
+ constructor(private db: Database.Database) {
18
+ this.stmts = {
19
+ create: db.prepare(`
20
+ INSERT INTO insights (type, severity, title, description, data_json)
21
+ VALUES (@type, @severity, @title, @description, @data_json)
22
+ `),
23
+ getAll: db.prepare('SELECT * FROM insights ORDER BY created_at DESC'),
24
+ getRecent: db.prepare('SELECT * FROM insights ORDER BY created_at DESC LIMIT ?'),
25
+ getByType: db.prepare('SELECT * FROM insights WHERE type = ? ORDER BY created_at DESC'),
26
+ getBySeverity: db.prepare('SELECT * FROM insights WHERE severity = ? ORDER BY created_at DESC'),
27
+ count: db.prepare('SELECT COUNT(*) as count FROM insights'),
28
+ search: db.prepare('SELECT insights.* FROM insights_fts JOIN insights ON insights_fts.rowid = insights.id WHERE insights_fts MATCH ? LIMIT ?'),
29
+ deleteOldest: db.prepare('DELETE FROM insights WHERE id IN (SELECT id FROM insights ORDER BY created_at ASC LIMIT ?)'),
30
+ deleteAll: db.prepare('DELETE FROM insights'),
31
+ };
32
+ }
33
+
34
+ create(data: { type: string; severity: string; title: string; description: string; data?: unknown }): number {
35
+ const result = this.stmts['create']!.run({
36
+ type: data.type,
37
+ severity: data.severity,
38
+ title: data.title,
39
+ description: data.description,
40
+ data_json: data.data ? JSON.stringify(data.data) : null,
41
+ });
42
+ return result.lastInsertRowid as number;
43
+ }
44
+
45
+ getAll(): InsightRecord[] {
46
+ return this.stmts['getAll']!.all() as InsightRecord[];
47
+ }
48
+
49
+ getRecent(limit: number = 10): InsightRecord[] {
50
+ return this.stmts['getRecent']!.all(limit) as InsightRecord[];
51
+ }
52
+
53
+ getByType(type: string): InsightRecord[] {
54
+ return this.stmts['getByType']!.all(type) as InsightRecord[];
55
+ }
56
+
57
+ getBySeverity(severity: string): InsightRecord[] {
58
+ return this.stmts['getBySeverity']!.all(severity) as InsightRecord[];
59
+ }
60
+
61
+ count(): number {
62
+ const row = this.stmts['count']!.get() as { count: number };
63
+ return row.count;
64
+ }
65
+
66
+ search(query: string, limit: number = 20): InsightRecord[] {
67
+ return this.stmts['search']!.all(query, limit) as InsightRecord[];
68
+ }
69
+
70
+ pruneOldest(keepCount: number): void {
71
+ const total = this.count();
72
+ if (total > keepCount) {
73
+ this.stmts['deleteOldest']!.run(total - keepCount);
74
+ }
75
+ }
76
+
77
+ deleteAll(): void {
78
+ this.stmts['deleteAll']!.run();
79
+ }
80
+ }
@@ -0,0 +1,67 @@
1
+ import type Database from 'better-sqlite3';
2
+ import type { Statement } from 'better-sqlite3';
3
+
4
+ export interface RuleRecord {
5
+ id: number;
6
+ pattern: string;
7
+ confidence: number;
8
+ sample_count: number;
9
+ win_rate: number;
10
+ avg_profit: number;
11
+ created_at: string;
12
+ updated_at: string;
13
+ }
14
+
15
+ export class RuleRepository {
16
+ private stmts: Record<string, Statement>;
17
+
18
+ constructor(private db: Database.Database) {
19
+ this.stmts = {
20
+ create: db.prepare(`
21
+ INSERT INTO rules (pattern, confidence, sample_count, win_rate, avg_profit)
22
+ VALUES (@pattern, @confidence, @sample_count, @win_rate, @avg_profit)
23
+ `),
24
+ getAll: db.prepare('SELECT * FROM rules ORDER BY confidence DESC'),
25
+ getById: db.prepare('SELECT * FROM rules WHERE id = ?'),
26
+ count: db.prepare('SELECT COUNT(*) as count FROM rules'),
27
+ deleteAll: db.prepare('DELETE FROM rules'),
28
+ deleteById: db.prepare('DELETE FROM rules WHERE id = ?'),
29
+ };
30
+ }
31
+
32
+ create(data: { pattern: string; confidence: number; sample_count: number; win_rate: number; avg_profit: number }): number {
33
+ const result = this.stmts['create']!.run(data);
34
+ return result.lastInsertRowid as number;
35
+ }
36
+
37
+ getAll(): RuleRecord[] {
38
+ return this.stmts['getAll']!.all() as RuleRecord[];
39
+ }
40
+
41
+ getById(id: number): RuleRecord | undefined {
42
+ return this.stmts['getById']!.get(id) as RuleRecord | undefined;
43
+ }
44
+
45
+ count(): number {
46
+ const row = this.stmts['count']!.get() as { count: number };
47
+ return row.count;
48
+ }
49
+
50
+ deleteAll(): void {
51
+ this.stmts['deleteAll']!.run();
52
+ }
53
+
54
+ delete(id: number): void {
55
+ this.stmts['deleteById']!.run(id);
56
+ }
57
+
58
+ replaceAll(rules: { pattern: string; confidence: number; sample_count: number; win_rate: number; avg_profit: number }[]): void {
59
+ const tx = this.db.transaction(() => {
60
+ this.stmts['deleteAll']!.run();
61
+ for (const rule of rules) {
62
+ this.stmts['create']!.run(rule);
63
+ }
64
+ });
65
+ tx();
66
+ }
67
+ }
@@ -0,0 +1,48 @@
1
+ import type Database from 'better-sqlite3';
2
+ import type { Statement } from 'better-sqlite3';
3
+
4
+ export interface SignalComboRecord {
5
+ id: number;
6
+ fingerprint: string;
7
+ signals_json: string;
8
+ regime: string | null;
9
+ created_at: string;
10
+ }
11
+
12
+ export class SignalRepository {
13
+ private stmts: Record<string, Statement>;
14
+
15
+ constructor(private db: Database.Database) {
16
+ this.stmts = {
17
+ create: db.prepare(`
18
+ INSERT INTO signal_combos (fingerprint, signals_json, regime)
19
+ VALUES (@fingerprint, @signals_json, @regime)
20
+ `),
21
+ getByFingerprint: db.prepare('SELECT * FROM signal_combos WHERE fingerprint = ? ORDER BY created_at DESC'),
22
+ getAll: db.prepare('SELECT * FROM signal_combos ORDER BY created_at DESC'),
23
+ count: db.prepare('SELECT COUNT(*) as count FROM signal_combos'),
24
+ };
25
+ }
26
+
27
+ create(fingerprint: string, signalsJson: string, regime?: string): number {
28
+ const result = this.stmts['create']!.run({
29
+ fingerprint,
30
+ signals_json: signalsJson,
31
+ regime: regime ?? null,
32
+ });
33
+ return result.lastInsertRowid as number;
34
+ }
35
+
36
+ getByFingerprint(fingerprint: string): SignalComboRecord[] {
37
+ return this.stmts['getByFingerprint']!.all(fingerprint) as SignalComboRecord[];
38
+ }
39
+
40
+ getAll(): SignalComboRecord[] {
41
+ return this.stmts['getAll']!.all() as SignalComboRecord[];
42
+ }
43
+
44
+ count(): number {
45
+ const row = this.stmts['count']!.get() as { count: number };
46
+ return row.count;
47
+ }
48
+ }
@@ -0,0 +1,71 @@
1
+ import type Database from 'better-sqlite3';
2
+ import type { Statement } from 'better-sqlite3';
3
+
4
+ export interface SynapseRecord {
5
+ id: string;
6
+ fingerprint: string;
7
+ weight: number;
8
+ wins: number;
9
+ losses: number;
10
+ activations: number;
11
+ total_profit: number;
12
+ last_activated: string;
13
+ created_at: string;
14
+ }
15
+
16
+ export class SynapseRepository {
17
+ private stmts: Record<string, Statement>;
18
+
19
+ constructor(private db: Database.Database) {
20
+ this.stmts = {
21
+ upsert: db.prepare(`
22
+ INSERT INTO synapses (id, fingerprint, weight, wins, losses, activations, total_profit, last_activated)
23
+ VALUES (@id, @fingerprint, @weight, @wins, @losses, @activations, @total_profit, @last_activated)
24
+ ON CONFLICT(id) DO UPDATE SET
25
+ weight = @weight, wins = @wins, losses = @losses,
26
+ activations = @activations, total_profit = @total_profit,
27
+ last_activated = @last_activated
28
+ `),
29
+ getById: db.prepare('SELECT * FROM synapses WHERE id = ?'),
30
+ getAll: db.prepare('SELECT * FROM synapses ORDER BY weight DESC'),
31
+ count: db.prepare('SELECT COUNT(*) as count FROM synapses'),
32
+ updateWeight: db.prepare('UPDATE synapses SET weight = ?, last_activated = datetime("now") WHERE id = ?'),
33
+ deleteById: db.prepare('DELETE FROM synapses WHERE id = ?'),
34
+ getByMinWeight: db.prepare('SELECT * FROM synapses WHERE weight >= ? ORDER BY weight DESC'),
35
+ getStrongest: db.prepare('SELECT * FROM synapses ORDER BY weight DESC LIMIT ?'),
36
+ };
37
+ }
38
+
39
+ upsert(synapse: Omit<SynapseRecord, 'created_at'>): void {
40
+ this.stmts['upsert']!.run(synapse);
41
+ }
42
+
43
+ getById(id: string): SynapseRecord | undefined {
44
+ return this.stmts['getById']!.get(id) as SynapseRecord | undefined;
45
+ }
46
+
47
+ getAll(): SynapseRecord[] {
48
+ return this.stmts['getAll']!.all() as SynapseRecord[];
49
+ }
50
+
51
+ count(): number {
52
+ const row = this.stmts['count']!.get() as { count: number };
53
+ return row.count;
54
+ }
55
+
56
+ updateWeight(id: string, weight: number): void {
57
+ this.stmts['updateWeight']!.run(weight, id);
58
+ }
59
+
60
+ delete(id: string): void {
61
+ this.stmts['deleteById']!.run(id);
62
+ }
63
+
64
+ getByMinWeight(minWeight: number): SynapseRecord[] {
65
+ return this.stmts['getByMinWeight']!.all(minWeight) as SynapseRecord[];
66
+ }
67
+
68
+ getStrongest(limit: number = 20): SynapseRecord[] {
69
+ return this.stmts['getStrongest']!.all(limit) as SynapseRecord[];
70
+ }
71
+ }
@@ -0,0 +1,97 @@
1
+ import type Database from 'better-sqlite3';
2
+ import type { Statement } from 'better-sqlite3';
3
+
4
+ export interface TradeRecord {
5
+ id: number;
6
+ fingerprint: string;
7
+ pair: string;
8
+ bot_type: string;
9
+ regime: string | null;
10
+ profit_pct: number;
11
+ win: number;
12
+ signals_json: string | null;
13
+ created_at: string;
14
+ }
15
+
16
+ export interface CreateTradeData {
17
+ fingerprint: string;
18
+ pair: string;
19
+ bot_type: string;
20
+ regime?: string;
21
+ profit_pct: number;
22
+ win: boolean;
23
+ signals_json?: string;
24
+ }
25
+
26
+ export class TradeRepository {
27
+ private stmts: Record<string, Statement>;
28
+
29
+ constructor(private db: Database.Database) {
30
+ this.stmts = {
31
+ create: db.prepare(`
32
+ INSERT INTO trades (fingerprint, pair, bot_type, regime, profit_pct, win, signals_json)
33
+ VALUES (@fingerprint, @pair, @bot_type, @regime, @profit_pct, @win, @signals_json)
34
+ `),
35
+ getById: db.prepare('SELECT * FROM trades WHERE id = ?'),
36
+ count: db.prepare('SELECT COUNT(*) as count FROM trades'),
37
+ getAll: db.prepare('SELECT * FROM trades ORDER BY created_at DESC'),
38
+ getRecent: db.prepare('SELECT * FROM trades ORDER BY created_at DESC LIMIT ?'),
39
+ getByPair: db.prepare('SELECT * FROM trades WHERE pair = ? ORDER BY created_at DESC'),
40
+ getByFingerprint: db.prepare('SELECT * FROM trades WHERE fingerprint = ? ORDER BY created_at DESC'),
41
+ getByBotType: db.prepare('SELECT * FROM trades WHERE bot_type = ? ORDER BY created_at DESC'),
42
+ getSince: db.prepare('SELECT * FROM trades WHERE created_at > ? ORDER BY created_at DESC'),
43
+ search: db.prepare(`SELECT * FROM trades WHERE fingerprint LIKE ? OR pair LIKE ? OR bot_type LIKE ? ORDER BY created_at DESC LIMIT ?`),
44
+ };
45
+ }
46
+
47
+ create(data: CreateTradeData): number {
48
+ const result = this.stmts['create']!.run({
49
+ fingerprint: data.fingerprint,
50
+ pair: data.pair,
51
+ bot_type: data.bot_type,
52
+ regime: data.regime ?? null,
53
+ profit_pct: data.profit_pct,
54
+ win: data.win ? 1 : 0,
55
+ signals_json: data.signals_json ?? null,
56
+ });
57
+ return result.lastInsertRowid as number;
58
+ }
59
+
60
+ getById(id: number): TradeRecord | undefined {
61
+ return this.stmts['getById']!.get(id) as TradeRecord | undefined;
62
+ }
63
+
64
+ count(): number {
65
+ const row = this.stmts['count']!.get() as { count: number };
66
+ return row.count;
67
+ }
68
+
69
+ getAll(): TradeRecord[] {
70
+ return this.stmts['getAll']!.all() as TradeRecord[];
71
+ }
72
+
73
+ getRecent(limit: number = 10): TradeRecord[] {
74
+ return this.stmts['getRecent']!.all(limit) as TradeRecord[];
75
+ }
76
+
77
+ getByPair(pair: string): TradeRecord[] {
78
+ return this.stmts['getByPair']!.all(pair) as TradeRecord[];
79
+ }
80
+
81
+ getByFingerprint(fingerprint: string): TradeRecord[] {
82
+ return this.stmts['getByFingerprint']!.all(fingerprint) as TradeRecord[];
83
+ }
84
+
85
+ getByBotType(botType: string): TradeRecord[] {
86
+ return this.stmts['getByBotType']!.all(botType) as TradeRecord[];
87
+ }
88
+
89
+ getSince(dateStr: string): TradeRecord[] {
90
+ return this.stmts['getSince']!.all(dateStr) as TradeRecord[];
91
+ }
92
+
93
+ search(query: string, limit: number = 50): TradeRecord[] {
94
+ const like = `%${query}%`;
95
+ return this.stmts['search']!.all(like, like, like, limit) as TradeRecord[];
96
+ }
97
+ }