clawock 0.1.0__py3-none-any.whl

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 (123) hide show
  1. clawock/__init__.py +11 -0
  2. clawock/__main__.py +5 -0
  3. clawock/adapters/__init__.py +1 -0
  4. clawock/adapters/mobile.py +117 -0
  5. clawock/cli.py +764 -0
  6. clawock/config/earnings_review.schema.json +235 -0
  7. clawock/config/entry_gate.schema.json +204 -0
  8. clawock/config/instruments.schema.json +74 -0
  9. clawock/config/thesis.schema.json +164 -0
  10. clawock/context/__init__.py +1 -0
  11. clawock/context/assembly.py +379 -0
  12. clawock/context/brief.py +448 -0
  13. clawock/context/manifest.json +138 -0
  14. clawock/decision/__init__.py +1 -0
  15. clawock/decision/actions.py +8 -0
  16. clawock/decision/earnings.py +803 -0
  17. clawock/decision/entry.py +530 -0
  18. clawock/decision/execution.py +41 -0
  19. clawock/decision/ledger.py +1945 -0
  20. clawock/decision/packet.py +780 -0
  21. clawock/decision/plans.py +182 -0
  22. clawock/decision/regime.py +379 -0
  23. clawock/decision/risk.py +620 -0
  24. clawock/decision/settlement.py +146 -0
  25. clawock/decision/setup_review.py +163 -0
  26. clawock/decision/setups.py +256 -0
  27. clawock/decision/signal_review.py +164 -0
  28. clawock/decision/signals.py +415 -0
  29. clawock/decision/theses.py +521 -0
  30. clawock/evaluation/__init__.py +1 -0
  31. clawock/evaluation/combined_regime.py +299 -0
  32. clawock/evaluation/hstech_regime.py +202 -0
  33. clawock/evaluation/regime_validation.py +478 -0
  34. clawock/evaluation/us_leverage.py +243 -0
  35. clawock/evidence/__init__.py +1 -0
  36. clawock/evidence/build_evidence.py +309 -0
  37. clawock/evidence/claim_provenance.py +192 -0
  38. clawock/evidence/news_evidence_graph.py +1035 -0
  39. clawock/evidence/research_provenance.py +253 -0
  40. clawock/evidence/research_surface.py +569 -0
  41. clawock/evidence/run_card.py +193 -0
  42. clawock/harness/__init__.py +18 -0
  43. clawock/harness/agent_run.py +198 -0
  44. clawock/harness/config.py +102 -0
  45. clawock/harness/model.py +127 -0
  46. clawock/harness/report.py +144 -0
  47. clawock/harness/runner.py +63 -0
  48. clawock/harness/validation.py +269 -0
  49. clawock/json_repair.py +372 -0
  50. clawock/market_data/__init__.py +5 -0
  51. clawock/market_data/bars.py +320 -0
  52. clawock/market_data/benchmarks.py +176 -0
  53. clawock/market_data/calendar.py +469 -0
  54. clawock/market_data/eastmoney_http.py +101 -0
  55. clawock/market_data/eastmoney_news.py +167 -0
  56. clawock/market_data/eastmoney_symbols.py +116 -0
  57. clawock/market_data/factors.py +908 -0
  58. clawock/market_data/filings.py +408 -0
  59. clawock/market_data/fund_flows.py +125 -0
  60. clawock/market_data/fundamentals.py +232 -0
  61. clawock/market_data/hk_analysis.py +772 -0
  62. clawock/market_data/integrity.py +198 -0
  63. clawock/market_data/known_catalysts.py +75 -0
  64. clawock/market_data/macro.py +292 -0
  65. clawock/market_data/mover_evidence.py +480 -0
  66. clawock/market_data/peer_discovery.py +254 -0
  67. clawock/market_data/peer_quotes.py +419 -0
  68. clawock/market_data/peer_residuals.py +656 -0
  69. clawock/market_data/peer_scan.py +236 -0
  70. clawock/market_data/sentiment.py +179 -0
  71. clawock/market_data/sessions.py +282 -0
  72. clawock/market_data/us_analysis.py +545 -0
  73. clawock/market_data/us_quotes.py +1368 -0
  74. clawock/portfolio/__init__.py +1 -0
  75. clawock/portfolio/aggregates.py +152 -0
  76. clawock/portfolio/books.py +49 -0
  77. clawock/portfolio/cash.py +103 -0
  78. clawock/portfolio/fx.py +264 -0
  79. clawock/portfolio/instruments.py +407 -0
  80. clawock/portfolio/integrity.py +579 -0
  81. clawock/portfolio/math.py +77 -0
  82. clawock/portfolio/realized.py +121 -0
  83. clawock/portfolio/reconcile.py +37 -0
  84. clawock/portfolio/risk.py +1369 -0
  85. clawock/portfolio/shadow.py +1138 -0
  86. clawock/portfolio/snapshots.py +128 -0
  87. clawock/providers/__init__.py +44 -0
  88. clawock/providers/delivery.py +167 -0
  89. clawock/providers/openclaw.py +547 -0
  90. clawock/providers/runs.py +140 -0
  91. clawock/publish/__init__.py +33 -0
  92. clawock/publish/artifacts.py +1068 -0
  93. clawock/publish/dashboard.py +3140 -0
  94. clawock/publish/deploy.py +92 -0
  95. clawock/publish/outcomes.py +62 -0
  96. clawock/publish/outputs.py +222 -0
  97. clawock/publish/store.py +384 -0
  98. clawock/safe_io.py +204 -0
  99. clawock/tools/__init__.py +134 -0
  100. clawock/tools/context_tools.py +176 -0
  101. clawock/workflows/__init__.py +34 -0
  102. clawock/workflows/improvements.py +467 -0
  103. clawock/workflows/packs/__init__.py +1 -0
  104. clawock/workflows/packs/investment-decision/SKILL.md +54 -0
  105. clawock/workflows/packs/investment-decision/agents/openai.yaml +4 -0
  106. clawock/workflows/packs/investment-decision/assets/decision.example.json +63 -0
  107. clawock/workflows/packs/investment-decision/assets/outcome.example.json +19 -0
  108. clawock/workflows/packs/investment-decision/references/decision-contract.md +110 -0
  109. clawock/workflows/packs/investment-decision/references/decision.schema.json +159 -0
  110. clawock/workflows/packs/investment-decision/references/improvement-proposal.schema.json +53 -0
  111. clawock/workflows/packs/investment-decision/references/outcome.schema.json +49 -0
  112. clawock/workflows/packs/investment-decision/workflow.json +75 -0
  113. clawock/workflows/registry.py +171 -0
  114. clawock/workflows/schemas.py +66 -0
  115. clawock/workflows/validators.py +333 -0
  116. clawock/workspace.py +115 -0
  117. clawock-0.1.0.dist-info/METADATA +399 -0
  118. clawock-0.1.0.dist-info/RECORD +123 -0
  119. clawock-0.1.0.dist-info/WHEEL +5 -0
  120. clawock-0.1.0.dist-info/entry_points.txt +2 -0
  121. clawock-0.1.0.dist-info/licenses/LICENSE +21 -0
  122. clawock-0.1.0.dist-info/licenses/NOTICE +13 -0
  123. clawock-0.1.0.dist-info/top_level.txt +1 -0
clawock/__init__.py ADDED
@@ -0,0 +1,11 @@
1
+ """clawock — portable decision intelligence for external agents.
2
+
3
+ This package is the runtime-neutral product that can be installed and pointed at
4
+ any workspace. Cohesive product areas live in domain subpackages such as
5
+ ``clawock.evidence`` and ``clawock.portfolio``; remaining code under ``scripts``
6
+ is instance or repository operations, never an alternate product namespace.
7
+ """
8
+
9
+ from clawock.workspace import ENV_VAR, describe, missing_pieces, workspace_root
10
+
11
+ __all__ = ["ENV_VAR", "describe", "missing_pieces", "workspace_root"]
clawock/__main__.py ADDED
@@ -0,0 +1,5 @@
1
+ from clawock.cli import main
2
+
3
+
4
+ if __name__ == "__main__":
5
+ raise SystemExit(main())
@@ -0,0 +1 @@
1
+ """Presentation adapters for external clients and narrow messaging surfaces."""
@@ -0,0 +1,117 @@
1
+ """Visual-width-aware markdown table renderer for narrow messaging clients.
2
+
3
+ WeChat 移动端不渲染 markdown table,只显示原始 monospace 文本。CJK 字符
4
+ 在 monospace 字体下视觉宽度 = 2 个 ASCII 字符。该 helper 用 visual width
5
+ 做 padding,确保表格在 mobile/desktop WeChat 上每行视觉宽度一致 —— 即使
6
+ 被强制换行,wrap 出来的子串也对齐。
7
+
8
+ 用法:
9
+ from clawock.adapters.mobile import render_holdings_table
10
+
11
+ rows = [
12
+ {'code': '00100', 'shares': 60, 'cost': 822.83, 'price': 722.00,
13
+ 'today_pct': 5.1, 'pnl_pct': -12.2, 'pnl_abs': -6049.8},
14
+ ...
15
+ ]
16
+ print('\\n'.join(render_holdings_table(rows, currency='HKD')))
17
+ """
18
+
19
+ from typing import Dict, List
20
+
21
+
22
+ def vw(s: str) -> int:
23
+ """Visual width: CJK = 2, ASCII = 1 in common monospace renderers."""
24
+ return sum(2 if ord(c) > 127 else 1 for c in s)
25
+
26
+
27
+ def pad_right(s: str, width: int) -> str:
28
+ """Right-align in visual width (left-pad with spaces)."""
29
+ return ' ' * max(0, width - vw(s)) + s
30
+
31
+
32
+ def pad_left(s: str, width: int) -> str:
33
+ """Left-align in visual width (right-pad with spaces)."""
34
+ return s + ' ' * max(0, width - vw(s))
35
+
36
+
37
+ # Cell content widths (visual). Chosen to fit max expected portfolio values.
38
+ # code: 5-char HK / 4-char US tickers
39
+ # shares: up to 99999 (current max ~6200 on 07226)
40
+ # cost/price: 999.99 fits in 6 chars; numbers ≥ 1000 use compact ',' format
41
+ # today/pnl_pct: "+12.3%" 6 vw; "-100.0%" rare 7
42
+ # pnl_abs: "-10,050" 7 vw
43
+ W_CODE = 5
44
+ W_SHARES = 5
45
+ W_COST = 6
46
+ W_PRICE = 6
47
+ W_TODAY = 6
48
+ W_PNL_P = 6
49
+ W_PNL_A = 7
50
+
51
+
52
+ def render_holdings_table(rows: List[Dict], currency: str = '') -> List[str]:
53
+ """Render a seven-column narrow-client holdings table.
54
+
55
+ Returns list of strings (no trailing newline). Caller joins with '\\n'.
56
+
57
+ rows: each dict has keys code, shares, cost, price, today_pct, pnl_pct, pnl_abs.
58
+ currency: kept for backward-compat / future use. We do NOT emit a unit-note
59
+ line because: (1) WeChat 不渲染 markdown italic, the raw `_...._`
60
+ looked ugly and LLM verbatim-trimmed it; (2) the currency is already
61
+ implicit via the 市值 line above the table (HK$xxx / $xxx).
62
+ """
63
+ _ = currency # intentionally unused
64
+ out: List[str] = []
65
+ # Header — left-align code, right-align rest. All widths in visual chars.
66
+ out.append(
67
+ '| ' + pad_left('代码', W_CODE) +
68
+ ' | ' + pad_right('股', W_SHARES) +
69
+ ' | ' + pad_right('成本', W_COST) +
70
+ ' | ' + pad_right('现价', W_PRICE) +
71
+ ' | ' + pad_right('今日', W_TODAY) +
72
+ ' | ' + pad_right('浮%', W_PNL_P) +
73
+ ' | ' + pad_right('浮$', W_PNL_A) + ' |'
74
+ )
75
+ # Separator — dashes per cell width + alignment colon.
76
+ out.append(
77
+ '|:' + '-' * (W_CODE + 1) +
78
+ '|' + '-' * (W_SHARES + 1) + ':' +
79
+ '|' + '-' * (W_COST + 1) + ':' +
80
+ '|' + '-' * (W_PRICE + 1) + ':' +
81
+ '|' + '-' * (W_TODAY + 1) + ':' +
82
+ '|' + '-' * (W_PNL_P + 1) + ':' +
83
+ '|' + '-' * (W_PNL_A + 1) + ':|'
84
+ )
85
+ for r in rows:
86
+ code = str(r['code'])
87
+ shares = r['shares']
88
+ cost = r.get('cost')
89
+ price = r['price']
90
+ today_pct = r.get('today_pct', 0.0)
91
+ pnl_pct = r.get('pnl_pct', 0.0)
92
+ pnl_abs = r.get('pnl_abs', 0.0)
93
+
94
+ cost_s = f'{cost:,.2f}' if cost else '—'
95
+ price_s = f'{price:,.2f}'
96
+ today_s = f'{today_pct:+.1f}%'
97
+ pnlp_s = f'{pnl_pct:+.1f}%'
98
+ pnla_s = f'{pnl_abs:+,.0f}'
99
+
100
+ out.append(
101
+ '| ' + pad_left(code, W_CODE) +
102
+ ' | ' + pad_right(str(shares), W_SHARES) +
103
+ ' | ' + pad_right(cost_s, W_COST) +
104
+ ' | ' + pad_right(price_s, W_PRICE) +
105
+ ' | ' + pad_right(today_s, W_TODAY) +
106
+ ' | ' + pad_right(pnlp_s, W_PNL_P) +
107
+ ' | ' + pad_right(pnla_s, W_PNL_A) + ' |'
108
+ )
109
+ # Self-check: header / separator / each data row must split to the same
110
+ # number of pipe segments. Catches regressions in this builder itself.
111
+ seg_counts = {line.count('|') for line in out}
112
+ if len(seg_counts) != 1:
113
+ raise AssertionError(
114
+ f'adapters.mobile: pipe-segment counts diverge across rows ({seg_counts}); '
115
+ f'header/sep/data must be identical column count.'
116
+ )
117
+ return out