@mulsok/traders-client 0.1.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 (119) hide show
  1. package/README.md +103 -0
  2. package/bin/cli.js +160 -0
  3. package/bin/postinstall.js +57 -0
  4. package/bin/preuninstall.js +36 -0
  5. package/dist/server/broker/kiwoom/cache.js +86 -0
  6. package/dist/server/broker/kiwoom/cache.js.map +1 -0
  7. package/dist/server/broker/kiwoom/client.js +256 -0
  8. package/dist/server/broker/kiwoom/client.js.map +1 -0
  9. package/dist/server/broker/kiwoom/endpoints/_helpers.js +61 -0
  10. package/dist/server/broker/kiwoom/endpoints/_helpers.js.map +1 -0
  11. package/dist/server/broker/kiwoom/endpoints/account.js +448 -0
  12. package/dist/server/broker/kiwoom/endpoints/account.js.map +1 -0
  13. package/dist/server/broker/kiwoom/endpoints/detail.js +118 -0
  14. package/dist/server/broker/kiwoom/endpoints/detail.js.map +1 -0
  15. package/dist/server/broker/kiwoom/endpoints/investor.js +139 -0
  16. package/dist/server/broker/kiwoom/endpoints/investor.js.map +1 -0
  17. package/dist/server/broker/kiwoom/endpoints/order.js +134 -0
  18. package/dist/server/broker/kiwoom/endpoints/order.js.map +1 -0
  19. package/dist/server/broker/kiwoom/endpoints/quote.js +165 -0
  20. package/dist/server/broker/kiwoom/endpoints/quote.js.map +1 -0
  21. package/dist/server/broker/kiwoom/endpoints/ranking.js +180 -0
  22. package/dist/server/broker/kiwoom/endpoints/ranking.js.map +1 -0
  23. package/dist/server/broker/kiwoom/endpoints/sector.js +135 -0
  24. package/dist/server/broker/kiwoom/endpoints/sector.js.map +1 -0
  25. package/dist/server/broker/kiwoom/endpoints/theme.js +104 -0
  26. package/dist/server/broker/kiwoom/endpoints/theme.js.map +1 -0
  27. package/dist/server/broker/kiwoom/endpoints/universe.js +119 -0
  28. package/dist/server/broker/kiwoom/endpoints/universe.js.map +1 -0
  29. package/dist/server/broker/kiwoom/index.js +59 -0
  30. package/dist/server/broker/kiwoom/index.js.map +1 -0
  31. package/dist/server/broker/kiwoom/order-tracker.js +353 -0
  32. package/dist/server/broker/kiwoom/order-tracker.js.map +1 -0
  33. package/dist/server/broker/kiwoom/price-feed.js +119 -0
  34. package/dist/server/broker/kiwoom/price-feed.js.map +1 -0
  35. package/dist/server/broker/kiwoom/rate-limiter.js +97 -0
  36. package/dist/server/broker/kiwoom/rate-limiter.js.map +1 -0
  37. package/dist/server/broker/kiwoom/types.js +13 -0
  38. package/dist/server/broker/kiwoom/types.js.map +1 -0
  39. package/dist/server/broker/kiwoom/ws/client.js +370 -0
  40. package/dist/server/broker/kiwoom/ws/client.js.map +1 -0
  41. package/dist/server/broker/kiwoom/ws/endpoints/condition.js +146 -0
  42. package/dist/server/broker/kiwoom/ws/endpoints/condition.js.map +1 -0
  43. package/dist/server/broker/kiwoom/ws/realtime-bus.js +42 -0
  44. package/dist/server/broker/kiwoom/ws/realtime-bus.js.map +1 -0
  45. package/dist/server/broker/kiwoom/ws/types.js +19 -0
  46. package/dist/server/broker/kiwoom/ws/types.js.map +1 -0
  47. package/dist/server/broker/news.js +34 -0
  48. package/dist/server/broker/news.js.map +1 -0
  49. package/dist/server/bundle.js +43 -0
  50. package/dist/server/bundle.js.map +1 -0
  51. package/dist/server/calendar/krx-holidays.js +162 -0
  52. package/dist/server/calendar/krx-holidays.js.map +1 -0
  53. package/dist/server/config.js +263 -0
  54. package/dist/server/config.js.map +1 -0
  55. package/dist/server/db/sqlite.js +252 -0
  56. package/dist/server/db/sqlite.js.map +1 -0
  57. package/dist/server/diary/writer.js +266 -0
  58. package/dist/server/diary/writer.js.map +1 -0
  59. package/dist/server/index.js +316 -0
  60. package/dist/server/index.js.map +1 -0
  61. package/dist/server/jobs/universe-sync.js +132 -0
  62. package/dist/server/jobs/universe-sync.js.map +1 -0
  63. package/dist/server/jobs/watchdog.js +87 -0
  64. package/dist/server/jobs/watchdog.js.map +1 -0
  65. package/dist/server/journal/pnl-stats.js +108 -0
  66. package/dist/server/journal/pnl-stats.js.map +1 -0
  67. package/dist/server/journal/telemetry.js +174 -0
  68. package/dist/server/journal/telemetry.js.map +1 -0
  69. package/dist/server/journal/trade-journal.js +239 -0
  70. package/dist/server/journal/trade-journal.js.map +1 -0
  71. package/dist/server/llm/anthropic.js +98 -0
  72. package/dist/server/llm/anthropic.js.map +1 -0
  73. package/dist/server/llm/claude-cli.js +204 -0
  74. package/dist/server/llm/claude-cli.js.map +1 -0
  75. package/dist/server/llm/context-builder.js +229 -0
  76. package/dist/server/llm/context-builder.js.map +1 -0
  77. package/dist/server/llm/gemini.js +86 -0
  78. package/dist/server/llm/gemini.js.map +1 -0
  79. package/dist/server/llm/index.js +36 -0
  80. package/dist/server/llm/index.js.map +1 -0
  81. package/dist/server/llm/openai.js +87 -0
  82. package/dist/server/llm/openai.js.map +1 -0
  83. package/dist/server/personas/executor.js +318 -0
  84. package/dist/server/personas/executor.js.map +1 -0
  85. package/dist/server/personas/loader.js +165 -0
  86. package/dist/server/personas/loader.js.map +1 -0
  87. package/dist/server/personas/persona-agent.js +386 -0
  88. package/dist/server/personas/persona-agent.js.map +1 -0
  89. package/dist/server/personas/persona-state.js +170 -0
  90. package/dist/server/personas/persona-state.js.map +1 -0
  91. package/dist/server/personas/runner.js +162 -0
  92. package/dist/server/personas/runner.js.map +1 -0
  93. package/dist/server/personas/schema.js +123 -0
  94. package/dist/server/personas/schema.js.map +1 -0
  95. package/dist/server/personas/wake-plan.js +313 -0
  96. package/dist/server/personas/wake-plan.js.map +1 -0
  97. package/dist/server/readiness.js +414 -0
  98. package/dist/server/readiness.js.map +1 -0
  99. package/dist/server/routes.js +1216 -0
  100. package/dist/server/routes.js.map +1 -0
  101. package/dist/server/safety.js +153 -0
  102. package/dist/server/safety.js.map +1 -0
  103. package/dist/server/screener/engine.js +856 -0
  104. package/dist/server/screener/engine.js.map +1 -0
  105. package/dist/server/server-sync.js +427 -0
  106. package/dist/server/server-sync.js.map +1 -0
  107. package/dist/server/signing.js +39 -0
  108. package/dist/server/signing.js.map +1 -0
  109. package/dist/server/watchers/condition-watcher.js +519 -0
  110. package/dist/server/watchers/condition-watcher.js.map +1 -0
  111. package/dist/server/watchers/types.js +16 -0
  112. package/dist/server/watchers/types.js.map +1 -0
  113. package/dist/web/assets/index-62SMpbaf.js +79 -0
  114. package/dist/web/assets/index-BPLQR0wt.css +1 -0
  115. package/dist/web/index.html +14 -0
  116. package/package.json +93 -0
  117. package/scripts/com.mulsok.traders.client.plist.template +58 -0
  118. package/scripts/install-daemon.sh +156 -0
  119. package/scripts/uninstall-daemon.sh +62 -0
@@ -0,0 +1,162 @@
1
+ /**
2
+ * ํŽ˜๋ฅด์†Œ๋‚˜ ๊ธฐ๋ฐ˜ ์Šคํฌ๋ฆฌ๋‹ ์‹คํ–‰๊ธฐ
3
+ *
4
+ * ๋ชฉ์ :
5
+ * ํŽ˜๋ฅด์†Œ๋‚˜ slug ๋งŒ ์ฃผ๋ฉด frontmatter โ†’ ์Šคํฌ๋ฆฌ๋„ˆ ์—”์ง„ ํ˜ธ์ถœ๊นŒ์ง€ ์ž๋™ํ™”.
6
+ * ํŽ˜๋ฅด์†Œ๋‚˜ ์ถ”๊ฐ€ ์‹œ ์ฝ”๋“œ ์ˆ˜์ • 0 (ํ”„๋กฌํ”„ํŠธ body + frontmatter ๋งŒ).
7
+ *
8
+ * ํ๋ฆ„:
9
+ * loadPersona(slug)
10
+ * โ†’ frontmatter.screener ํ™•์ธ
11
+ * โ†’ ScreenerFilter ๋กœ ๋งคํ•‘
12
+ * โ†’ runScreener() ์‹คํ–‰
13
+ * โ†’ ๊ฒฐ๊ณผ + ํŽ˜๋ฅด์†Œ๋‚˜ ๋ฉ”ํƒ€ ๋ฐ˜ํ™˜
14
+ *
15
+ * ์ฃผ์˜:
16
+ * - screener ๋ฏธ์„ค์ • ํŽ˜๋ฅด์†Œ๋‚˜ (์˜ˆ: ๋Œ€ํ™”ํ˜•๋งŒ ํ•˜๋Š” ํŽ˜๋ฅด์†Œ๋‚˜) ๋Š” skip + ์•ˆ๋‚ด
17
+ * - Universe ๋ฐฐ์น˜ ๋ฏธ์‹คํ–‰ ์‹œ candidates=[] ๋ฐ˜ํ™˜ (ํ˜ธ์ถœ์ž ๊ฒฝ๊ณ  ์ฑ…์ž„)
18
+ */
19
+ import { runScreener } from "../screener/engine.js";
20
+ import { loadPersona } from "./loader.js";
21
+ export async function runPersonaScreening(slug) {
22
+ const persona = await loadPersona(slug);
23
+ if (!persona)
24
+ return null;
25
+ const cfg = persona.frontmatter.screener;
26
+ if (!cfg) {
27
+ return {
28
+ persona: metaOf(persona),
29
+ screener: emptyResult(),
30
+ screenedAt: new Date().toISOString(),
31
+ skipped: true,
32
+ skipReason: `ํŽ˜๋ฅด์†Œ๋‚˜ ${slug} ๋Š” frontmatter ์— screener ์„ค์ •์ด ์—†์Œ`,
33
+ };
34
+ }
35
+ const filter = configToFilter(cfg);
36
+ const screener = await runScreener(filter);
37
+ return {
38
+ persona: metaOf(persona),
39
+ screener,
40
+ screenedAt: new Date().toISOString(),
41
+ skipped: false,
42
+ };
43
+ }
44
+ export async function listAvailablePersonas(slugs) {
45
+ const results = await Promise.all(slugs.map(async (slug) => {
46
+ try {
47
+ const p = await loadPersona(slug);
48
+ return p ? { slug, ok: true, info: metaOf(p) } : { slug, ok: false, error: "not found" };
49
+ }
50
+ catch (e) {
51
+ return { slug, ok: false, error: String(e) };
52
+ }
53
+ }));
54
+ return results;
55
+ }
56
+ function metaOf(p) {
57
+ return {
58
+ slug: p.slug,
59
+ version: p.frontmatter.version,
60
+ displayName: p.frontmatter.displayName,
61
+ source: p.source,
62
+ };
63
+ }
64
+ function configToFilter(cfg) {
65
+ const filter = {};
66
+ if (cfg.universe) {
67
+ if (cfg.universe.marketIn)
68
+ filter.marketIn = cfg.universe.marketIn;
69
+ if (cfg.universe.excludeStates)
70
+ filter.excludeStates = cfg.universe.excludeStates;
71
+ if (cfg.universe.excludeNonCommon !== undefined)
72
+ filter.excludeNonCommon = cfg.universe.excludeNonCommon;
73
+ if (cfg.universe.priceRange)
74
+ filter.priceRange = cfg.universe.priceRange;
75
+ if (cfg.universe.marketCapRange)
76
+ filter.marketCapRange = cfg.universe.marketCapRange;
77
+ }
78
+ if (cfg.maOrder)
79
+ filter.maOrder = cfg.maOrder;
80
+ if (cfg.volumeAvgMultiple)
81
+ filter.volumeAvgMultiple = cfg.volumeAvgMultiple;
82
+ if (cfg.circulatingVolumeRatio)
83
+ filter.circulatingVolumeRatio = cfg.circulatingVolumeRatio;
84
+ if (cfg.candlePatterns) {
85
+ filter.candlePatterns = cfg.candlePatterns;
86
+ }
87
+ if (cfg.candlePatternsMode)
88
+ filter.candlePatternsMode = cfg.candlePatternsMode;
89
+ if (cfg.sort)
90
+ filter.sort = cfg.sort;
91
+ if (cfg.limit)
92
+ filter.limit = cfg.limit;
93
+ return filter;
94
+ }
95
+ function emptyResult() {
96
+ return {
97
+ filter: {},
98
+ candidates: [],
99
+ universeSize: 0,
100
+ evaluated: 0,
101
+ skippedNoCandles: 0,
102
+ elapsedMs: 0,
103
+ dataAsOf: undefined,
104
+ diagnostics: {
105
+ universeAfterStaticFilter: 0,
106
+ rejectedBy: {
107
+ priceRange: 0,
108
+ marketCapRange: 0,
109
+ excludeStates: 0,
110
+ nonCommon: 0,
111
+ maOrder: 0,
112
+ volumeAvgMultiple: 0,
113
+ circulatingVolumeRatio: 0,
114
+ candlePattern: 0,
115
+ noCandles: 0,
116
+ },
117
+ patternReject: {},
118
+ samples: [],
119
+ },
120
+ };
121
+ }
122
+ /**
123
+ * ์Šคํฌ๋ฆฌ๋‹ ๊ฒฐ๊ณผ๋ฅผ LLM Layer 3 context ๋กœ ์กฐ๋ฆฝ (๋ฒ”์šฉ ยท ํŽ˜๋ฅด์†Œ๋‚˜ ๋น„์˜์กด).
124
+ *
125
+ * persona ๋ณ„ ์„น์…˜ ์ œ๋ชฉ๊ณผ ํ›„๋ณด ํ‘œํ˜„์€ frontmatter.displayName ์—์„œ ๊ฐ€์ ธ์˜ด.
126
+ */
127
+ export function buildPersonaCandidatesContext(result, topN = 8) {
128
+ const title = result.persona.displayName ?? result.persona.slug;
129
+ if (result.skipped) {
130
+ return `## ${title}\n\n(ํŽ˜๋ฅด์†Œ๋‚˜๊ฐ€ ์Šคํฌ๋ฆฌ๋„ˆ๋ฅผ ์“ฐ์ง€ ์•Š์Œ ยท ${result.skipReason ?? ""})`;
131
+ }
132
+ const s = result.screener;
133
+ if (s.candidates.length === 0) {
134
+ return [
135
+ `## ${title} ์Šคํฌ๋ฆฌ๋‹ ๊ฒฐ๊ณผ`,
136
+ `์œ ๋‹ˆ๋ฒ„์Šค ${s.universeSize} ยท ํ‰๊ฐ€ ${s.evaluated} ยท ํ›„๋ณด 0`,
137
+ s.skippedNoCandles > 0 ? `(candles ๋ฏธ๋ณด์œ  ${s.skippedNoCandles}๊ฑด ยท ๋ฐฐ์น˜ ํ•„์š”)` : "",
138
+ ].filter((x) => x.length > 0).join("\n");
139
+ }
140
+ const lines = [
141
+ `## ${title} ์Šคํฌ๋ฆฌ๋‹ ๊ฒฐ๊ณผ`,
142
+ `์œ ๋‹ˆ๋ฒ„์Šค ${s.universeSize} ยท ํ‰๊ฐ€ ${s.evaluated} ยท ํ›„๋ณด ${s.candidates.length} ยท ์†Œ์š” ${s.elapsedMs}ms`,
143
+ "",
144
+ `### ์ƒ์œ„ ${Math.min(topN, s.candidates.length)} ํ›„๋ณด (score ๋‚ด๋ฆผ์ฐจ์ˆœ)`,
145
+ "",
146
+ ];
147
+ for (const c of s.candidates.slice(0, topN)) {
148
+ const maStr = Object.entries(c.ma)
149
+ .map(([k, v]) => `${k}=${Math.round(v).toLocaleString()}`)
150
+ .join(" ยท ");
151
+ lines.push(`**[${c.code}] ${c.name}** ยท ${c.market} ยท ํ˜„์žฌ๊ฐ€ ${c.lastPriceKrw.toLocaleString()} ยท score ${c.score}`);
152
+ lines.push(`- ์˜ค๋Š˜ ๋ณ€๋™๋ฅ : ${c.todayChangePct.toFixed(2)}%`);
153
+ lines.push(`- ์œ ํ†ต ์ฃผ์‹์ˆ˜: ${c.listCount.toLocaleString()}์ฃผ`);
154
+ if (maStr)
155
+ lines.push(`- ${maStr}`);
156
+ if (c.reasons.length > 0)
157
+ lines.push(`- ์‚ฌ์œ : ${c.reasons.join(" ยท ")}`);
158
+ lines.push("");
159
+ }
160
+ return lines.join("\n");
161
+ }
162
+ //# sourceMappingURL=runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../../src-server/personas/runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,123 @@
1
+ /**
2
+ * ํŽ˜๋ฅด์†Œ๋‚˜ Frontmatter ์Šคํ‚ค๋งˆ (zod)
3
+ *
4
+ * ์„ค๊ณ„ ์›์น™:
5
+ * - ํŽ˜๋ฅด์†Œ๋‚˜ = Supabase persona.body ์˜ **frontmatter + ๋ณธ๋ฌธ**
6
+ * - ์ƒˆ ํŽ˜๋ฅด์†Œ๋‚˜ ์ถ”๊ฐ€ = body text ์ž‘์„ฑ๋งŒ (์ฝ”๋“œ ์ˆ˜์ • 0)
7
+ * - ๋กœ์ปฌ override (~/.mulsok-traders/personas/<slug>.yaml) ๋กœ Supabase ๋ฐฐํฌ ์ „ ํ…Œ์ŠคํŠธ ๊ฐ€๋Šฅ
8
+ *
9
+ * Frontmatter ์˜ˆ์‹œ (markdown body ์ƒ๋‹จ):
10
+ * ---
11
+ * persona: neoul
12
+ * version: 1.8.0
13
+ * displayName: "๋„ˆ์šธ โ€” ์–‘์Œ์–‘ ํŠธ๋ ˆ์ด๋”"
14
+ * screener:
15
+ * universe:
16
+ * marketIn: [kospi, kosdaq]
17
+ * excludeStates: ["๊ด€๋ฆฌ์ข…๋ชฉ", "์ •๋ฆฌ๋งค๋งค", "ํˆฌ์ž์ฃผ์˜ํ™˜๊ธฐ"]
18
+ * candlePatterns:
19
+ * - kind: yinYangBull
20
+ * params:
21
+ * d1MinChangePct: 5
22
+ * d1MaxChangePct: 23
23
+ * d1MinVolumeRatio: 1.5
24
+ * d0MaxVolumeRatio: 0.8
25
+ * mustHoldMa: 5
26
+ * maClusterPeriods: [5, 10, 20]
27
+ * sort: { by: score, order: desc }
28
+ * limit: 30
29
+ * ---
30
+ *
31
+ * # ๋„ˆ์šธ ํ”„๋กฌํ”„ํŠธ ๋ณธ๋ฌธ...
32
+ */
33
+ import { z } from "zod";
34
+ /* โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Candle pattern ์Šคํ‚ค๋งˆ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */
35
+ const YinYangBullParamsSchema = z.object({
36
+ d1MinChangePct: z.number().optional(),
37
+ d1MaxChangePct: z.number().optional(),
38
+ d1VolumeBaselineDays: z.number().int().positive().optional(),
39
+ d1MinVolumeRatio: z.number().optional(),
40
+ d1ExceptionalVolumeRatio: z.number().optional(),
41
+ d0MaxVolumeRatio: z.number().optional(),
42
+ d0IdealVolumeRatio: z.number().optional(),
43
+ d0MustBeBearish: z.boolean().optional(),
44
+ d0BodyRatioIdeal: z.tuple([z.number(), z.number()]).optional(),
45
+ d0BodyRatioAcceptable: z.tuple([z.number(), z.number()]).optional(),
46
+ d0BodyRatioMarginalScore: z.number().optional(),
47
+ mustHoldMa: z.number().int().positive().optional(),
48
+ maClusterIdealPct: z.number().optional(),
49
+ maClusterAcceptablePct: z.number().optional(),
50
+ maClusterPeriods: z.array(z.number().int().positive()).optional(),
51
+ maOrderBonus: z.boolean().optional(),
52
+ longMaBreakoutBonus: z.boolean().optional(),
53
+ d0HighVolumeExclude: z.boolean().optional(),
54
+ tradingValueBonus: z.boolean().optional(),
55
+ tradingValueTier1Krw: z.number().positive().optional(),
56
+ tradingValueTier2Krw: z.number().positive().optional(),
57
+ });
58
+ const YinYangUpperShadowParamsSchema = z.object({
59
+ d1MinUpperShadowRatio: z.number().optional(),
60
+ d1MustCloseAboveMa: z.array(z.number().int().positive()).optional(),
61
+ d0MaxVolumeRatio: z.number().optional(),
62
+ d0OpenBelowD1Close: z.boolean().optional(),
63
+ d1MaxChangePct: z.number().optional(),
64
+ mustHoldMa: z.number().int().positive().optional(),
65
+ });
66
+ const YinYangSidewaysParamsSchema = z.object({
67
+ sidewaysDaysRange: z.tuple([z.number().int().positive(), z.number().int().positive()]).optional(),
68
+ sidewaysMaxAvgVolumeRatio: z.number().optional(),
69
+ mustStayAboveMa: z.number().int().positive().optional(),
70
+ bigBullishMinChangePct: z.number().optional(),
71
+ bigBullishMaxChangePct: z.number().optional(),
72
+ bullishMinGapPct: z.number().optional(),
73
+ requireGapConvergence: z.boolean().optional(),
74
+ });
75
+ const CandlePatternSchema = z.discriminatedUnion("kind", [
76
+ z.object({ kind: z.literal("yinYangBull"), params: YinYangBullParamsSchema.optional() }),
77
+ z.object({ kind: z.literal("yinYangUpperShadow"), params: YinYangUpperShadowParamsSchema.optional() }),
78
+ z.object({ kind: z.literal("yinYangSideways"), params: YinYangSidewaysParamsSchema.optional() }),
79
+ z.object({ kind: z.literal("engulfingBull"), params: z.object({ minBodyRatio: z.number().optional() }).optional() }),
80
+ z.object({ kind: z.literal("morningStar"), params: z.object({ minBodyRatio: z.number().optional() }).optional() }),
81
+ z.object({ kind: z.literal("hammer"), params: z.object({ minTailBodyRatio: z.number().optional() }).optional() }),
82
+ z.object({ kind: z.literal("maRebound"), params: z.object({ ma: z.number().int().positive(), minBouncePct: z.number().optional() }) }),
83
+ ]);
84
+ /* โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Universe ํ•„ํ„ฐ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */
85
+ const UniverseFilterSchema = z.object({
86
+ marketIn: z.array(z.enum(["kospi", "kosdaq"])).optional(),
87
+ excludeStates: z.array(z.string()).optional(),
88
+ /** ๋ณดํ†ต์ฃผ๋งŒ (ETFยทETNยทELWยท์šฐ์„ ์ฃผยท๋ฆฌ์ธ ยท์ŠคํŒฉ ์ œ์™ธ) โ€” engine.ts isNonCommon */
89
+ excludeNonCommon: z.boolean().optional(),
90
+ priceRange: z.object({ minKrw: z.number().optional(), maxKrw: z.number().optional() }).optional(),
91
+ marketCapRange: z.object({ minKrw: z.number().optional(), maxKrw: z.number().optional() }).optional(),
92
+ });
93
+ /* โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Screener ์ „์ฒด โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */
94
+ const ScreenerConfigSchema = z.object({
95
+ universe: UniverseFilterSchema.optional(),
96
+ maOrder: z.object({
97
+ asc: z.array(z.number().int().positive()).optional(),
98
+ desc: z.array(z.number().int().positive()).optional(),
99
+ }).optional(),
100
+ volumeAvgMultiple: z.object({ baselineDays: z.number().int().positive(), minRatio: z.number() }).optional(),
101
+ circulatingVolumeRatio: z.object({ minPct: z.number() }).optional(),
102
+ candlePatterns: z.array(CandlePatternSchema).optional(),
103
+ candlePatternsMode: z.enum(["and", "any"]).optional(),
104
+ sort: z.object({
105
+ by: z.enum(["score", "changePct", "volume", "marketCap"]),
106
+ order: z.enum(["asc", "desc"]).optional(),
107
+ }).optional(),
108
+ limit: z.number().int().positive().optional(),
109
+ });
110
+ /* โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Persona Frontmatter โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */
111
+ export const PersonaFrontmatterSchema = z.object({
112
+ persona: z.string().min(1),
113
+ version: z.string().min(1),
114
+ displayName: z.string().optional(),
115
+ tagline: z.string().optional(),
116
+ screener: ScreenerConfigSchema.optional(),
117
+ /** LLM ์ตœ์ข… ํŒ์ •์— ์“ฐ์ผ ์ถœ๋ ฅ ์Šคํ‚ค๋งˆ ํžŒํŠธ (optional) */
118
+ decision: z.object({
119
+ maxCandidates: z.number().int().positive().optional(),
120
+ outputShape: z.enum(["json", "markdown"]).optional(),
121
+ }).optional(),
122
+ });
123
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src-server/personas/schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,313 @@
1
+ /**
2
+ * wake_plan ํŒŒ์‹ฑ ยท ์ž๋™ ๋“ฑ๋ก ์œ ํ‹ธ
3
+ *
4
+ * ํ๋ฆ„:
5
+ * 1. LLM ์‘๋‹ต ํ…์ŠคํŠธ โ†’ JSON ํŒŒ์‹ฑ โ†’ wake_plan ์ถ”์ถœ
6
+ * 2. next_scheduled (์žˆ์œผ๋ฉด) โ†’ time watcher ๋กœ ์ž๋™ ๋“ฑ๋ก
7
+ * 3. watchers[] ํ•ญ๋ชฉ ์ค‘ ๊ตฌ์กฐํ™”๋œ `condition` ๊ฐ์ฒด๊ฐ€ ์žˆ๋Š” ๊ฒƒ โ†’ ConditionWatcher.add
8
+ * 4. condition_summary (์„œ์ˆ ) ๋งŒ ์žˆ๋Š” ํ•ญ๋ชฉ โ†’ skip + ๋กœ๊น… (ํ–ฅํ›„ NLP ๋˜๋Š” ํ”„๋กฌํ”„ํŠธ ๊ฐœ์„ )
9
+ *
10
+ * Layer 1 c1.4.0 ์ŠคํŽ™:
11
+ * wake_plan: {
12
+ * mode: "scheduled" | "watcher" | "mixed",
13
+ * next_scheduled: { at: ISO8601, reason: string } | null,
14
+ * watchers: [{ intent, condition_summary, wake_action, max_wait_hours, condition? }]
15
+ * }
16
+ *
17
+ * `condition` ์€ Layer 1 ์ŠคํŽ™์— ์—†์œผ๋ฏ€๋กœ optional ยท ์žˆ์œผ๋ฉด ์šฐ๋ฆฌ ํŒŒ์„œ๊ฐ€ ํ™œ์šฉ.
18
+ */
19
+ import { z } from "zod";
20
+ import { getConditionWatcher } from "../watchers/condition-watcher.js";
21
+ import { nextTradingDay, isKrxHoliday } from "../calendar/krx-holidays.js";
22
+ /* โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ ์Šคํ‚ค๋งˆ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */
23
+ const ComparisonOpSchema = z.enum(["gte", "gt", "lte", "lt", "eq"]);
24
+ // Minimum interval (SPEC-4 ยท ๋ฌดํ•œ ๋ฃจํ”„ ๋ฐฉ์–ด ยท ์ž์œจ์„ฑ ์นจํ•ด X ยท ๋ช…๋ฐฑํ•œ ๋ฒ„๊ทธ ๊ฐ€๋“œ)
25
+ const MIN_AFTER_MS = 60_000; // 1๋ถ„ โ€” time.afterMs ์ตœ์†Œ
26
+ const MIN_CHECK_INTERVAL_MS = 5_000; // 5์ดˆ โ€” price/event polling ์ตœ์†Œ
27
+ const PriceConditionSchema = z.object({
28
+ type: z.literal("price"),
29
+ config: z.object({
30
+ symbolCode: z.string().min(1),
31
+ metric: z.enum(["current_price", "change_pct", "from_buy_price_pct", "from_open_pct", "volume_ratio_d1"]),
32
+ op: ComparisonOpSchema,
33
+ value: z.number(),
34
+ buyPriceKrw: z.number().positive().optional(),
35
+ checkIntervalMs: z.number().int().min(MIN_CHECK_INTERVAL_MS, `checkIntervalMs โ‰ฅ ${MIN_CHECK_INTERVAL_MS}ms (๋ฌดํ•œ polling ๋ฐฉ์–ด)`).optional(),
36
+ }),
37
+ });
38
+ const EventConditionSchema = z.object({
39
+ type: z.literal("event"),
40
+ config: z.object({
41
+ symbolCode: z.string().min(1),
42
+ metric: z.enum([
43
+ "ma_touch",
44
+ "ma_break_below",
45
+ "ma_break_above",
46
+ "bullish_engulfing",
47
+ "high_volume_bearish",
48
+ "previous_low_break",
49
+ "candle_volume_surge",
50
+ ]),
51
+ maPeriod: z.union([z.literal(5), z.literal(10), z.literal(20), z.literal(60), z.literal(120)]).optional(),
52
+ volumeMultiple: z.number().positive().optional(),
53
+ checkIntervalMs: z.number().int().min(MIN_CHECK_INTERVAL_MS, `checkIntervalMs โ‰ฅ ${MIN_CHECK_INTERVAL_MS}ms (๋ฌดํ•œ polling ๋ฐฉ์–ด)`).optional(),
54
+ }),
55
+ });
56
+ const TimeConditionSchema = z.object({
57
+ type: z.literal("time"),
58
+ config: z.object({
59
+ at: z.string().optional(),
60
+ afterMs: z.number().int().min(MIN_AFTER_MS, `afterMs โ‰ฅ ${MIN_AFTER_MS}ms (์ฆ‰์‹œ ๋ฐœํ™” ๋ฌดํ•œ ๋ฃจํ”„ ๋ฐฉ์–ด)`).optional(),
61
+ }),
62
+ });
63
+ const ConditionConfigSchema = z.discriminatedUnion("type", [
64
+ PriceConditionSchema,
65
+ EventConditionSchema,
66
+ TimeConditionSchema,
67
+ ]);
68
+ const WatcherEntrySchema = z.object({
69
+ intent: z.string().min(1),
70
+ condition_summary: z.string().optional(),
71
+ wake_action: z.string().optional(),
72
+ max_wait_hours: z.number().positive().max(720).optional(),
73
+ /** ๊ตฌ์กฐํ™”๋œ condition ๊ฐ์ฒด (ํ”„๋กฌํ”„ํŠธ๊ฐ€ ๋ช…์‹œ์ ์œผ๋กœ ์ œ๊ณตํ•  ๋•Œ) */
74
+ condition: ConditionConfigSchema.optional(),
75
+ repeat: z.boolean().optional(),
76
+ });
77
+ const NextScheduledSchema = z.object({
78
+ at: z.string().min(1),
79
+ reason: z.string().optional(),
80
+ });
81
+ export const WakePlanSchema = z.object({
82
+ mode: z.enum(["scheduled", "watcher", "mixed"]),
83
+ next_scheduled: NextScheduledSchema.nullable().optional(),
84
+ watchers: z.array(WatcherEntrySchema).optional().default([]),
85
+ });
86
+ /**
87
+ * LLM ์‘๋‹ต ํ…์ŠคํŠธ์—์„œ wake_plan ์ถ”์ถœ.
88
+ * ์—ฌ๋Ÿฌ ํฌ๋งท์„ ๊ด€์šฉ:
89
+ * 1. ์ˆœ์ˆ˜ JSON
90
+ * 2. ```json ... ``` code fence ๋ž˜ํ•‘
91
+ * 3. ์•ž๋’ค์— ์ผ๋ฐ˜ ํ…์ŠคํŠธ๊ฐ€ ์„ž์ธ JSON
92
+ */
93
+ export function extractWakePlan(llmResponseText) {
94
+ const trimmed = llmResponseText.trim();
95
+ if (!trimmed)
96
+ return { ok: false, error: "empty response" };
97
+ const candidates = [
98
+ trimmed,
99
+ stripCodeFence(trimmed),
100
+ firstJsonObject(trimmed),
101
+ ].filter((s) => !!s && s !== undefined);
102
+ for (const text of candidates) {
103
+ try {
104
+ const obj = JSON.parse(text);
105
+ if (!obj || typeof obj !== "object")
106
+ continue;
107
+ const wp = obj.wake_plan;
108
+ if (!wp)
109
+ continue;
110
+ const parsed = WakePlanSchema.safeParse(wp);
111
+ if (!parsed.success) {
112
+ return {
113
+ ok: false,
114
+ error: `wake_plan schema ์˜ค๋ฅ˜: ${parsed.error.issues.map((i) => i.path.join(".") + ": " + i.message).join(" ยท ")}`,
115
+ rawJson: wp,
116
+ };
117
+ }
118
+ return { ok: true, wakePlan: parsed.data, rawJson: wp };
119
+ }
120
+ catch {
121
+ continue;
122
+ }
123
+ }
124
+ return { ok: false, error: "wake_plan ํฌํ•จ JSON ํŒŒ์‹ฑ ์‹คํŒจ" };
125
+ }
126
+ function stripCodeFence(text) {
127
+ const m = text.match(/```(?:json)?\s*([\s\S]*?)```/);
128
+ return m?.[1]?.trim();
129
+ }
130
+ function firstJsonObject(text) {
131
+ const start = text.indexOf("{");
132
+ if (start < 0)
133
+ return undefined;
134
+ // ๋‹จ์ˆœ brace ๊ท ํ˜• (๋ฌธ์ž์—ด ๋‚ด๋ถ€ escape ๋ฌด์‹œ ยท ์‹ค์šฉ ์ˆ˜์ค€)
135
+ let depth = 0;
136
+ let inStr = false;
137
+ let escape = false;
138
+ for (let i = start; i < text.length; i++) {
139
+ const c = text[i];
140
+ if (escape) {
141
+ escape = false;
142
+ continue;
143
+ }
144
+ if (c === "\\" && inStr) {
145
+ escape = true;
146
+ continue;
147
+ }
148
+ if (c === '"') {
149
+ inStr = !inStr;
150
+ continue;
151
+ }
152
+ if (inStr)
153
+ continue;
154
+ if (c === "{")
155
+ depth++;
156
+ else if (c === "}") {
157
+ depth--;
158
+ if (depth === 0)
159
+ return text.slice(start, i + 1);
160
+ }
161
+ }
162
+ return undefined;
163
+ }
164
+ /* โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ KST ์‹œ๊ฐ ๋งˆ์ปค ์ •๊ทœํ™” โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */
165
+ /**
166
+ * "์˜ค๋Š˜T15:25:00+09:00", "๋‚ด์ผT08:50:00+09:00", "๋‹ค์Œ์›”์š”์ผT08:50:00+09:00",
167
+ * "๋‹ค์Œ๊ฑฐ๋ž˜์ผT08:50:00+09:00", ๋˜๋Š” ISO8601 ์ ˆ๋Œ€ ์‹œ๊ฐ์„ ์‹ค Date ๋กœ.
168
+ *
169
+ * ใ€Œ๋‹ค์Œ๊ฑฐ๋ž˜์ผใ€ ์ฒ˜๋ฆฌ: KRX ๊ณตํœด์ผ + ์ฃผ๋ง ๋ชจ๋‘ skip (calendar/krx-holidays.ts).
170
+ * ใ€Œ๋‚ด์ผใ€ ์ฒ˜๋ฆฌ: ๋‹จ์ˆœ +1์ผ (ํœด์žฅ์ผ ๊ฒ€์ฆ X ยท LLM ์˜๋„ ๊ทธ๋Œ€๋กœ). ํœด์žฅ์ผ ๋ฐœํ™”ํ•˜๋ฉด
171
+ * safety:market_closed ๋กœ ์ฐจ๋‹จ๋˜๋ฏ€๋กœ ์‚ฌ์šฉ์ž๊ฐ€ ์ •ํ™•ํ•˜๋ฉด "๋‹ค์Œ๊ฑฐ๋ž˜์ผ" ์‚ฌ์šฉ ๊ถŒ์žฅ.
172
+ */
173
+ export function normalizeKstDateMarker(input) {
174
+ // ISO8601 ์‹œ๋„
175
+ const direct = new Date(input);
176
+ if (!Number.isNaN(direct.getTime()) && /\d{4}/.test(input))
177
+ return direct;
178
+ const m = input.match(/^(์˜ค๋Š˜|๋‚ด์ผ|๋‹ค์Œ(?:์ฃผ)?์›”์š”์ผ|๋‹ค์Œ๊ฑฐ๋ž˜์ผ)T(\d{2}):(\d{2}):(\d{2})([+-]\d{2}:\d{2})$/);
179
+ if (!m)
180
+ return null;
181
+ const [, dayKey, hh, mm, ss, tz] = m;
182
+ const nowUtc = new Date();
183
+ const kstOffsetMs = 9 * 3600 * 1000;
184
+ const kstNow = new Date(nowUtc.getTime() + kstOffsetMs);
185
+ const kstDay = kstNow.getUTCDay(); // 0 = ์ผ, 1 = ์›”, ...
186
+ let offsetDays = 0;
187
+ if (dayKey === "์˜ค๋Š˜") {
188
+ offsetDays = 0;
189
+ }
190
+ else if (dayKey === "๋‚ด์ผ") {
191
+ offsetDays = 1;
192
+ }
193
+ else if (dayKey.includes("์›”์š”์ผ")) {
194
+ // ๋‹ค์Œ ์›”์š”์ผ
195
+ offsetDays = kstDay === 0 ? 1 : (8 - kstDay) % 7;
196
+ if (offsetDays === 0)
197
+ offsetDays = 7; // ์˜ค๋Š˜์ด ์›”์š”์ผ์ด๋ฉด ๋‹ค์Œ ์ฃผ ์›”์š”์ผ
198
+ }
199
+ else if (dayKey === "๋‹ค์Œ๊ฑฐ๋ž˜์ผ") {
200
+ // KRX ๊ณตํœด์ผ + ์ฃผ๋ง ๋ชจ๋‘ skip (D ๋ณด๊ฐ• ยท ๊ณตํœด์ผ ์บ˜๋ฆฐ๋” ํ™œ์šฉ)
201
+ // 1) +1์ผ ํ›„๋ณด
202
+ let candidate = new Date(nowUtc.getTime() + 86400_000);
203
+ // 2) ์‹œ๊ฐ ๋ถ€๋ถ„์„ hh:mm:ss ๋กœ ๋งž์ถฐ์„œ ๊ฑฐ๋ž˜์ผ ๊ฒ€์ฆ (์žฅ ์‹œ๊ฐ„๋Œ€ ๊ณ ๋ ค)
204
+ const candidateIso = `${candidate.toISOString().slice(0, 10)}T${hh}:${mm}:${ss}${tz}`;
205
+ candidate = new Date(candidateIso);
206
+ if (!Number.isNaN(candidate.getTime())) {
207
+ // 3) ํœด์žฅ์ผ์ด๋ฉด ๋‹ค์Œ ๊ฑฐ๋ž˜์ผ๋กœ
208
+ if (isKrxHoliday(candidate)) {
209
+ candidate = nextTradingDay(candidate);
210
+ // ์‹œ๊ฐ ๋ถ€๋ถ„ ๋‹ค์‹œ ์ ์šฉ (nextTradingDay ๋Š” ์‹œ๊ฐ ๊ทธ๋Œ€๋กœ ๋‘์ง€๋งŒ ์•ˆ์ „)
211
+ const adjusted = `${candidate.toISOString().slice(0, 10)}T${hh}:${mm}:${ss}${tz}`;
212
+ const adjustedDate = new Date(adjusted);
213
+ return Number.isNaN(adjustedDate.getTime()) ? null : adjustedDate;
214
+ }
215
+ return candidate;
216
+ }
217
+ // fallback: ์ด์ „ ๋‹จ์ˆœ ๋กœ์ง
218
+ offsetDays = 1;
219
+ const nextDay = (kstDay + offsetDays) % 7;
220
+ if (nextDay === 6)
221
+ offsetDays += 2;
222
+ else if (nextDay === 0)
223
+ offsetDays += 1;
224
+ }
225
+ const ymd = new Date(kstNow.getTime() + offsetDays * 86400000).toISOString().slice(0, 10);
226
+ const iso = `${ymd}T${hh}:${mm}:${ss}${tz}`;
227
+ const d = new Date(iso);
228
+ return Number.isNaN(d.getTime()) ? null : d;
229
+ }
230
+ export function registerWakePlan(personaSlug, plan) {
231
+ const cw = getConditionWatcher();
232
+ const registered = [];
233
+ const skipped = [];
234
+ let nextScheduledRegistered = false;
235
+ // 1. next_scheduled โ†’ time watcher
236
+ if (plan.next_scheduled?.at) {
237
+ const at = normalizeKstDateMarker(plan.next_scheduled.at);
238
+ if (!at) {
239
+ skipped.push({
240
+ reason: `next_scheduled.at ํŒŒ์‹ฑ ์‹คํŒจ ยท "${plan.next_scheduled.at}"`,
241
+ entry: plan.next_scheduled,
242
+ });
243
+ }
244
+ else if (at.getTime() <= Date.now() + 10_000) {
245
+ skipped.push({
246
+ reason: `next_scheduled.at ์ด ๊ณผ๊ฑฐ ยท "${plan.next_scheduled.at}" โ†’ ${at.toISOString()}`,
247
+ entry: plan.next_scheduled,
248
+ });
249
+ }
250
+ else {
251
+ try {
252
+ const spec = {
253
+ intent: `next_scheduled ยท ${plan.next_scheduled.reason ?? "(reason ์—†์Œ)"}`,
254
+ condition: { type: "time", config: { at: at.toISOString() } },
255
+ wakeAction: "LLM ์žฌํ˜ธ์ถœ (scheduled)",
256
+ maxWaitHours: 336, // 2์ฃผ ์ƒํ•œ
257
+ };
258
+ registered.push(cw.add(personaSlug, spec));
259
+ nextScheduledRegistered = true;
260
+ }
261
+ catch (e) {
262
+ skipped.push({ reason: `next_scheduled ๋“ฑ๋ก ์‹คํŒจ: ${String(e)}`, entry: plan.next_scheduled });
263
+ }
264
+ }
265
+ }
266
+ // 2. watchers[] ์˜ ๊ตฌ์กฐํ™” condition ์ด ์žˆ๋Š” ํ•ญ๋ชฉ๋งŒ ๋“ฑ๋ก
267
+ for (const entry of plan.watchers ?? []) {
268
+ if (!entry.condition) {
269
+ skipped.push({
270
+ reason: "condition ๊ตฌ์กฐํ™” ๊ฐ์ฒด ์—†์Œ (condition_summary ์„œ์ˆ ๋งŒ) ยท ํ–ฅํ›„ ํ”„๋กฌํ”„ํŠธ ๊ฐœ์„  ๋˜๋Š” NLP ํŒŒ์„œ ํ•„์š”",
271
+ entry,
272
+ });
273
+ continue;
274
+ }
275
+ // time condition ์˜ KST ๋งˆ์ปค๋ฅผ ISO ์ ˆ๋Œ€ ์‹œ๊ฐ์œผ๋กœ ์‚ฌ์ „ ์ •๊ทœํ™”.
276
+ // c1.8.0 ยงwake_plan KST ๋งˆ์ปค (`์˜ค๋Š˜T15:35:00+09:00` ๋“ฑ) ๊ฐ€ ์ •์‹ ํ˜•์‹์ด์ง€๋งŒ
277
+ // condition-watcher ์˜ setTimeout ์€ ISO ๋งŒ ์ฒ˜๋ฆฌํ•˜๋ฏ€๋กœ ๋“ฑ๋ก ์‹œ์ ์— ํ’€์–ด๋‘”๋‹ค.
278
+ const condition = entry.condition;
279
+ if (condition.type === "time" && condition.config?.at) {
280
+ const normalized = normalizeKstDateMarker(condition.config.at);
281
+ if (!normalized) {
282
+ skipped.push({
283
+ reason: `time condition.at ํŒŒ์‹ฑ ์‹คํŒจ ยท "${condition.config.at}"`,
284
+ entry,
285
+ });
286
+ continue;
287
+ }
288
+ if (normalized.getTime() <= Date.now() + 10_000) {
289
+ skipped.push({
290
+ reason: `time condition.at ์ด ๊ณผ๊ฑฐ ยท "${condition.config.at}" โ†’ ${normalized.toISOString()}`,
291
+ entry,
292
+ });
293
+ continue;
294
+ }
295
+ condition.config = { ...condition.config, at: normalized.toISOString() };
296
+ }
297
+ try {
298
+ const spec = {
299
+ intent: entry.intent,
300
+ condition,
301
+ wakeAction: entry.wake_action ?? "LLM ์žฌํ˜ธ์ถœ",
302
+ maxWaitHours: entry.max_wait_hours ?? 48,
303
+ repeat: entry.repeat,
304
+ };
305
+ registered.push(cw.add(personaSlug, spec));
306
+ }
307
+ catch (e) {
308
+ skipped.push({ reason: `watcher ๋“ฑ๋ก ์‹คํŒจ: ${String(e)}`, entry });
309
+ }
310
+ }
311
+ return { registered, skipped, nextScheduledRegistered };
312
+ }
313
+ //# sourceMappingURL=wake-plan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wake-plan.js","sourceRoot":"","sources":["../../../src-server/personas/wake-plan.ts"],"names":[],"mappings":"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"}