sophhub 0.2.3 → 0.2.4
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/package.json +1 -1
- package/skills/consensus/skill.json +20 -0
- package/skills/consensus/src/SKILL.md +93 -0
- package/skills/deepwiki/skill.json +20 -0
- package/skills/deepwiki/src/SKILL.md +45 -0
- package/skills/deepwiki/src/_meta.json +6 -0
- package/skills/deepwiki/src/scripts/deepwiki.js +135 -0
- package/skills/feishu-bitable/skill.json +20 -0
- package/skills/feishu-bitable/src/CHECKLIST.md +150 -0
- package/skills/feishu-bitable/src/README.md +178 -0
- package/skills/feishu-bitable/src/SKILL.md +113 -0
- package/skills/feishu-bitable/src/_meta.json +6 -0
- package/skills/feishu-bitable/src/api.js +381 -0
- package/skills/feishu-bitable/src/bin/cli.js +284 -0
- package/skills/feishu-bitable/src/description.md +143 -0
- package/skills/feishu-bitable/src/examples/create-records.json +52 -0
- package/skills/feishu-bitable/src/examples/create-table.json +64 -0
- package/skills/feishu-bitable/src/package-lock.json +324 -0
- package/skills/feishu-bitable/src/package.json +33 -0
- package/skills/feishu-bitable/src/publish-config.json +14 -0
- package/skills/feishu-bitable/src/test-simple.js +61 -0
- package/skills/feishu-bitable/src/utils.js +261 -0
- package/skills/google-maps/skill.json +20 -0
- package/skills/google-maps/src/SKILL.md +237 -0
- package/skills/google-maps/src/_meta.json +6 -0
- package/skills/google-maps/src/lib/map_helper.py +912 -0
- package/skills/large-task-router/skill.json +20 -0
- package/skills/large-task-router/src/SKILL.md +79 -0
- package/skills/large-task-router/src/templates/plan.md +74 -0
- package/skills/skillhub/skill.json +11 -4
- package/skills/skillhub/src/SKILL.md +11 -1
- package/skills/sophnet-dailynews/skill.json +20 -0
- package/skills/sophnet-dailynews/src/SKILL.md +179 -0
- package/skills/sophnet-dailynews/src/cache.json +151 -0
- package/skills/sophnet-dailynews/src/sources.json +230 -0
- package/skills/sophnet-schedule/skill.json +20 -0
- package/skills/sophnet-schedule/src/ARCHITECTURE.md +321 -0
- package/skills/sophnet-schedule/src/IMPROVEMENTS.md +145 -0
- package/skills/sophnet-schedule/src/SKILL.md +1050 -0
- package/skills/sophnet-schedule/src/_meta.json +6 -0
- package/skills/sophnet-schedule/src/api/__init__.py +0 -0
- package/skills/sophnet-schedule/src/api/models.py +245 -0
- package/skills/sophnet-schedule/src/apps/add_event.py +237 -0
- package/skills/sophnet-schedule/src/apps/check_reminders.py +112 -0
- package/skills/sophnet-schedule/src/apps/check_roc.py +246 -0
- package/skills/sophnet-schedule/src/apps/generate_daily_plan.py +342 -0
- package/skills/sophnet-schedule/src/apps/import_events.py +216 -0
- package/skills/sophnet-schedule/src/apps/monitor_calendar_changes.py +140 -0
- package/skills/sophnet-schedule/src/apps/register_tasks.py +169 -0
- package/skills/sophnet-schedule/src/apps/sync_roc_to_gcal.py +174 -0
- package/skills/sophnet-schedule/src/compat.py +66 -0
- package/skills/sophnet-schedule/src/config/__init__.py +0 -0
- package/skills/sophnet-schedule/src/config/reminder_rules.yaml +96 -0
- package/skills/sophnet-schedule/src/config/roc_events.yaml +44 -0
- package/skills/sophnet-schedule/src/config/settings.py +133 -0
- package/skills/sophnet-schedule/src/config/task_registry.yaml +92 -0
- package/skills/sophnet-schedule/src/docs/FRONTEND_INTEGRATION_GUIDE.md +437 -0
- package/skills/sophnet-schedule/src/gcal/__init__.py +0 -0
- package/skills/sophnet-schedule/src/gcal/client.py +374 -0
- package/skills/sophnet-schedule/src/gcal/models.py +91 -0
- package/skills/sophnet-schedule/src/requirements.txt +6 -0
- package/skills/sophnet-schedule/src/scripts/setup_gcal_token.py +85 -0
- package/skills/sophnet-schedule/src/server.py +669 -0
- package/skills/sophnet-schedule/src/services/__init__.py +0 -0
- package/skills/sophnet-schedule/src/services/calendar_backend.py +139 -0
- package/skills/sophnet-schedule/src/services/conflict_detector.py +96 -0
- package/skills/sophnet-schedule/src/services/datetime_utils.py +117 -0
- package/skills/sophnet-schedule/src/services/event_classifier.py +100 -0
- package/skills/sophnet-schedule/src/services/event_diff.py +160 -0
- package/skills/sophnet-schedule/src/services/google_integration.py +500 -0
- package/skills/sophnet-schedule/src/services/job_store.py +100 -0
- package/skills/sophnet-schedule/src/services/local_event_store.py +266 -0
- package/skills/sophnet-schedule/src/services/reminder_planner.py +116 -0
- package/skills/sophnet-schedule/src/services/runtime_utils.py +31 -0
- package/skills/sophnet-schedule/src/services/table_parser.py +286 -0
- package/skills/sophnet-schedule/src/services/task_builder.py +167 -0
- package/skills/sophnet-schedule/src/services/time_window.py +72 -0
- package/skills/sophnet-stock/skill.json +20 -0
- package/skills/sophnet-stock/src/App-Plan.md +442 -0
- package/skills/sophnet-stock/src/README.md +214 -0
- package/skills/sophnet-stock/src/SKILL.md +236 -0
- package/skills/sophnet-stock/src/TODO.md +394 -0
- package/skills/sophnet-stock/src/_meta.json +6 -0
- package/skills/sophnet-stock/src/docs/ARCHITECTURE.md +408 -0
- package/skills/sophnet-stock/src/docs/CONCEPT.md +233 -0
- package/skills/sophnet-stock/src/docs/HOT_SCANNER.md +288 -0
- package/skills/sophnet-stock/src/docs/README.md +95 -0
- package/skills/sophnet-stock/src/docs/USAGE.md +465 -0
- package/skills/sophnet-stock/src/scripts/analyze_stock.py +2565 -0
- package/skills/sophnet-stock/src/scripts/dividends.py +365 -0
- package/skills/sophnet-stock/src/scripts/hot_scanner.py +582 -0
- package/skills/sophnet-stock/src/scripts/portfolio.py +548 -0
- package/skills/sophnet-stock/src/scripts/rumor_scanner.py +342 -0
- package/skills/sophnet-stock/src/scripts/test_stock_analysis.py +409 -0
- package/skills/sophnet-stock/src/scripts/watchlist.py +336 -0
- package/skills/xiaohongshu/skill.json +20 -0
- package/skills/xiaohongshu/src/SKILL.md +91 -0
- package/skills/xiaohongshu/src/_meta.json +6 -0
- package/skills/xiaohongshu/src/assets/card.html +216 -0
- package/skills/xiaohongshu/src/assets/cover.html +82 -0
- package/skills/xiaohongshu/src/assets/example.md +84 -0
- package/skills/xiaohongshu/src/assets/styles.css +318 -0
- package/skills/xiaohongshu/src/scripts/render_xhs_v2.py +737 -0
- package/skills/xiaohongshu/src/scripts/sign_server.py +158 -0
- package/skills/xiaohongshu/src/scripts/stealth.min.js +7 -0
- package/skills/xiaohongshu/src/scripts/xhs_tool.py +186 -0
- package/skills/xiaohongshu/src/workflow.py +185 -0
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
# Technical Architecture
|
|
2
|
+
|
|
3
|
+
How Stock Analysis v6.0 works under the hood.
|
|
4
|
+
|
|
5
|
+
## System Overview
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
┌─────────────────────────────────────────────────────────────────────┐
|
|
9
|
+
│ Stock Analysis v6.0 │
|
|
10
|
+
├─────────────────────────────────────────────────────────────────────┤
|
|
11
|
+
│ │
|
|
12
|
+
│ ┌──────────────────────────────────────────────────────────────┐ │
|
|
13
|
+
│ │ CLI Interface │ │
|
|
14
|
+
│ │ analyze_stock.py | dividends.py | watchlist.py | portfolio.py│ │
|
|
15
|
+
│ └────────────────────────────┬─────────────────────────────────┘ │
|
|
16
|
+
│ │ │
|
|
17
|
+
│ ┌────────────────────────────▼─────────────────────────────────┐ │
|
|
18
|
+
│ │ Analysis Engine │ │
|
|
19
|
+
│ │ │ │
|
|
20
|
+
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
|
|
21
|
+
│ │ │Earnings │ │Fundmtls │ │Analysts │ │Historical│ │ │
|
|
22
|
+
│ │ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ │ │
|
|
23
|
+
│ │ │ │ │ │ │ │
|
|
24
|
+
│ │ ┌────┴────┐ ┌────┴────┐ ┌────┴────┐ ┌────┴────┐ │ │
|
|
25
|
+
│ │ │ Market │ │ Sector │ │Momentum │ │Sentiment│ │ │
|
|
26
|
+
│ │ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ │ │
|
|
27
|
+
│ │ │ │ │ │ │ │
|
|
28
|
+
│ │ └───────────┴───────────┴───────────┘ │ │
|
|
29
|
+
│ │ │ │ │
|
|
30
|
+
│ │ [Synthesizer] │ │
|
|
31
|
+
│ │ │ │ │
|
|
32
|
+
│ │ [Signal Output] │ │
|
|
33
|
+
│ └──────────────────────────────────────────────────────────────┘ │
|
|
34
|
+
│ │ │
|
|
35
|
+
│ ┌────────────────────────────▼─────────────────────────────────┐ │
|
|
36
|
+
│ │ Data Sources │ │
|
|
37
|
+
│ │ │ │
|
|
38
|
+
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
|
|
39
|
+
│ │ │ Yahoo │ │ CNN │ │ SEC │ │ Google │ │ │
|
|
40
|
+
│ │ │ Finance │ │Fear/Grd │ │ EDGAR │ │ News │ │ │
|
|
41
|
+
│ │ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ │
|
|
42
|
+
│ └──────────────────────────────────────────────────────────────┘ │
|
|
43
|
+
│ │
|
|
44
|
+
└─────────────────────────────────────────────────────────────────────┘
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Core Components
|
|
50
|
+
|
|
51
|
+
### 1. Data Fetching (`fetch_stock_data`)
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
def fetch_stock_data(ticker: str, verbose: bool = False) -> StockData | None:
|
|
55
|
+
"""Fetch stock data from Yahoo Finance with retry logic."""
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Features:**
|
|
59
|
+
- 3 retries with exponential backoff
|
|
60
|
+
- Graceful handling of missing data
|
|
61
|
+
- Asset type detection (stock vs crypto)
|
|
62
|
+
|
|
63
|
+
**Returns:** `StockData` dataclass with:
|
|
64
|
+
- `info`: Company fundamentals
|
|
65
|
+
- `earnings_history`: Past earnings
|
|
66
|
+
- `analyst_info`: Ratings and targets
|
|
67
|
+
- `price_history`: 1-year OHLCV
|
|
68
|
+
|
|
69
|
+
### 2. Analysis Modules
|
|
70
|
+
|
|
71
|
+
Each dimension has its own analyzer:
|
|
72
|
+
|
|
73
|
+
| Module | Function | Returns |
|
|
74
|
+
|--------|----------|---------|
|
|
75
|
+
| Earnings | `analyze_earnings_surprise()` | `EarningsSurprise` |
|
|
76
|
+
| Fundamentals | `analyze_fundamentals()` | `Fundamentals` |
|
|
77
|
+
| Analysts | `analyze_analyst_sentiment()` | `AnalystSentiment` |
|
|
78
|
+
| Historical | `analyze_historical_patterns()` | `HistoricalPatterns` |
|
|
79
|
+
| Market | `analyze_market_context()` | `MarketContext` |
|
|
80
|
+
| Sector | `analyze_sector_performance()` | `SectorComparison` |
|
|
81
|
+
| Momentum | `analyze_momentum()` | `MomentumAnalysis` |
|
|
82
|
+
| Sentiment | `analyze_sentiment()` | `SentimentAnalysis` |
|
|
83
|
+
|
|
84
|
+
### 3. Sentiment Sub-Analyzers
|
|
85
|
+
|
|
86
|
+
Sentiment runs 5 parallel async tasks:
|
|
87
|
+
|
|
88
|
+
```python
|
|
89
|
+
results = await asyncio.gather(
|
|
90
|
+
get_fear_greed_index(), # CNN Fear & Greed
|
|
91
|
+
get_short_interest(data), # Yahoo Finance
|
|
92
|
+
get_vix_term_structure(), # VIX Futures
|
|
93
|
+
get_insider_activity(), # SEC EDGAR
|
|
94
|
+
get_put_call_ratio(data), # Options Chain
|
|
95
|
+
return_exceptions=True
|
|
96
|
+
)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**Timeout:** 10 seconds per indicator
|
|
100
|
+
**Minimum:** 2 of 5 indicators required
|
|
101
|
+
|
|
102
|
+
### 4. Signal Synthesis
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
def synthesize_signal(
|
|
106
|
+
ticker, company_name,
|
|
107
|
+
earnings, fundamentals, analysts, historical,
|
|
108
|
+
market_context, sector, earnings_timing,
|
|
109
|
+
momentum, sentiment,
|
|
110
|
+
breaking_news, geopolitical_risk_warning, geopolitical_risk_penalty
|
|
111
|
+
) -> Signal:
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
**Scoring:**
|
|
115
|
+
1. Collect available component scores
|
|
116
|
+
2. Apply normalized weights
|
|
117
|
+
3. Calculate weighted average → `final_score`
|
|
118
|
+
4. Apply adjustments (timing, overbought, risk-off)
|
|
119
|
+
5. Determine recommendation threshold
|
|
120
|
+
|
|
121
|
+
**Thresholds:**
|
|
122
|
+
```python
|
|
123
|
+
if final_score > 0.33:
|
|
124
|
+
recommendation = "BUY"
|
|
125
|
+
elif final_score < -0.33:
|
|
126
|
+
recommendation = "SELL"
|
|
127
|
+
else:
|
|
128
|
+
recommendation = "HOLD"
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Caching Strategy
|
|
134
|
+
|
|
135
|
+
### What's Cached
|
|
136
|
+
|
|
137
|
+
| Data | TTL | Key |
|
|
138
|
+
|------|-----|-----|
|
|
139
|
+
| Market Context | 1 hour | `market_context` |
|
|
140
|
+
| Fear & Greed | 1 hour | `fear_greed` |
|
|
141
|
+
| VIX Structure | 1 hour | `vix_structure` |
|
|
142
|
+
| Breaking News | 1 hour | `breaking_news` |
|
|
143
|
+
|
|
144
|
+
### Cache Implementation
|
|
145
|
+
|
|
146
|
+
```python
|
|
147
|
+
_SENTIMENT_CACHE = {}
|
|
148
|
+
_CACHE_TTL_SECONDS = 3600 # 1 hour
|
|
149
|
+
|
|
150
|
+
def _get_cached(key: str):
|
|
151
|
+
if key in _SENTIMENT_CACHE:
|
|
152
|
+
value, timestamp = _SENTIMENT_CACHE[key]
|
|
153
|
+
if time.time() - timestamp < _CACHE_TTL_SECONDS:
|
|
154
|
+
return value
|
|
155
|
+
return None
|
|
156
|
+
|
|
157
|
+
def _set_cache(key: str, value):
|
|
158
|
+
_SENTIMENT_CACHE[key] = (value, time.time())
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Why This Matters
|
|
162
|
+
|
|
163
|
+
- First stock: ~8 seconds (full fetch)
|
|
164
|
+
- Second stock: ~4 seconds (reuses market data)
|
|
165
|
+
- Same stock again: ~4 seconds (no stock-level cache)
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## Data Flow
|
|
170
|
+
|
|
171
|
+
### Single Stock Analysis
|
|
172
|
+
|
|
173
|
+
```
|
|
174
|
+
User Input: "AAPL"
|
|
175
|
+
│
|
|
176
|
+
▼
|
|
177
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
178
|
+
│ 1. FETCH DATA (yfinance) │
|
|
179
|
+
│ - Stock info, earnings, price history │
|
|
180
|
+
│ - ~2 seconds │
|
|
181
|
+
└────────────────────────┬────────────────────────────────────┘
|
|
182
|
+
│
|
|
183
|
+
▼
|
|
184
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
185
|
+
│ 2. PARALLEL ANALYSIS │
|
|
186
|
+
│ │
|
|
187
|
+
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
|
188
|
+
│ │ Earnings │ │Fundmtls │ │ Analysts │ ... (sync) │
|
|
189
|
+
│ └──────────┘ └──────────┘ └──────────┘ │
|
|
190
|
+
│ │
|
|
191
|
+
│ ┌────────────────────────────────────┐ │
|
|
192
|
+
│ │ Market Context (cached or fetch) │ ~1 second │
|
|
193
|
+
│ └────────────────────────────────────┘ │
|
|
194
|
+
│ │
|
|
195
|
+
│ ┌────────────────────────────────────┐ │
|
|
196
|
+
│ │ Sentiment (5 async tasks) │ ~3-5 seconds │
|
|
197
|
+
│ │ - Fear/Greed (cached) │ │
|
|
198
|
+
│ │ - Short Interest │ │
|
|
199
|
+
│ │ - VIX Structure (cached) │ │
|
|
200
|
+
│ │ - Insider Trading (slow!) │ │
|
|
201
|
+
│ │ - Put/Call Ratio │ │
|
|
202
|
+
│ └────────────────────────────────────┘ │
|
|
203
|
+
└────────────────────────┬────────────────────────────────────┘
|
|
204
|
+
│
|
|
205
|
+
▼
|
|
206
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
207
|
+
│ 3. SYNTHESIZE SIGNAL │
|
|
208
|
+
│ - Combine scores with weights │
|
|
209
|
+
│ - Apply adjustments │
|
|
210
|
+
│ - Generate caveats │
|
|
211
|
+
│ - ~10 ms │
|
|
212
|
+
└────────────────────────┬────────────────────────────────────┘
|
|
213
|
+
│
|
|
214
|
+
▼
|
|
215
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
216
|
+
│ 4. OUTPUT │
|
|
217
|
+
│ - Text or JSON format │
|
|
218
|
+
│ - Include disclaimer │
|
|
219
|
+
└─────────────────────────────────────────────────────────────┘
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## Risk Detection
|
|
225
|
+
|
|
226
|
+
### Geopolitical Risk
|
|
227
|
+
|
|
228
|
+
```python
|
|
229
|
+
GEOPOLITICAL_RISK_MAP = {
|
|
230
|
+
"taiwan": {
|
|
231
|
+
"keywords": ["taiwan", "tsmc", "strait"],
|
|
232
|
+
"sectors": ["Technology", "Communication Services"],
|
|
233
|
+
"affected_tickers": ["NVDA", "AMD", "TSM", ...],
|
|
234
|
+
"impact": "Semiconductor supply chain disruption",
|
|
235
|
+
},
|
|
236
|
+
# ... china, russia_ukraine, middle_east, banking_crisis
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
**Process:**
|
|
241
|
+
1. Check breaking news for keywords
|
|
242
|
+
2. If keyword found, check if ticker in affected list
|
|
243
|
+
3. Apply confidence penalty (30% direct, 15% sector)
|
|
244
|
+
|
|
245
|
+
### Breaking News
|
|
246
|
+
|
|
247
|
+
```python
|
|
248
|
+
def check_breaking_news(verbose: bool = False) -> list[str] | None:
|
|
249
|
+
"""Scan Google News RSS for crisis keywords (last 24h)."""
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
**Crisis Keywords:**
|
|
253
|
+
```python
|
|
254
|
+
CRISIS_KEYWORDS = {
|
|
255
|
+
"war": ["war", "invasion", "military strike", ...],
|
|
256
|
+
"economic": ["recession", "crisis", "collapse", ...],
|
|
257
|
+
"regulatory": ["sanctions", "embargo", "ban", ...],
|
|
258
|
+
"disaster": ["earthquake", "hurricane", "pandemic", ...],
|
|
259
|
+
"financial": ["emergency rate", "bailout", ...],
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
## File Structure
|
|
266
|
+
|
|
267
|
+
```
|
|
268
|
+
stock-analysis/
|
|
269
|
+
├── scripts/
|
|
270
|
+
│ ├── analyze_stock.py # Main analysis engine (2500+ lines)
|
|
271
|
+
│ ├── portfolio.py # Portfolio management
|
|
272
|
+
│ ├── dividends.py # Dividend analysis
|
|
273
|
+
│ ├── watchlist.py # Watchlist + alerts
|
|
274
|
+
│ └── test_stock_analysis.py # Unit tests
|
|
275
|
+
├── docs/
|
|
276
|
+
│ ├── CONCEPT.md # Philosophy & ideas
|
|
277
|
+
│ ├── USAGE.md # Practical guide
|
|
278
|
+
│ └── ARCHITECTURE.md # This file
|
|
279
|
+
├── SKILL.md # OpenClaw skill definition
|
|
280
|
+
├── README.md # Project overview
|
|
281
|
+
└── .clawdhub/ # ClawHub metadata
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
## Data Storage
|
|
287
|
+
|
|
288
|
+
### Portfolio (`portfolios.json`)
|
|
289
|
+
|
|
290
|
+
```json
|
|
291
|
+
{
|
|
292
|
+
"portfolios": [
|
|
293
|
+
{
|
|
294
|
+
"name": "Retirement",
|
|
295
|
+
"created_at": "2024-01-01T00:00:00Z",
|
|
296
|
+
"assets": [
|
|
297
|
+
{
|
|
298
|
+
"ticker": "AAPL",
|
|
299
|
+
"quantity": 100,
|
|
300
|
+
"cost_basis": 150.00,
|
|
301
|
+
"type": "stock",
|
|
302
|
+
"added_at": "2024-01-01T00:00:00Z"
|
|
303
|
+
}
|
|
304
|
+
]
|
|
305
|
+
}
|
|
306
|
+
]
|
|
307
|
+
}
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### Watchlist (`watchlist.json`)
|
|
311
|
+
|
|
312
|
+
```json
|
|
313
|
+
[
|
|
314
|
+
{
|
|
315
|
+
"ticker": "NVDA",
|
|
316
|
+
"added_at": "2024-01-15T10:30:00Z",
|
|
317
|
+
"price_at_add": 700.00,
|
|
318
|
+
"target_price": 800.00,
|
|
319
|
+
"stop_price": 600.00,
|
|
320
|
+
"alert_on_signal": true,
|
|
321
|
+
"last_signal": "BUY",
|
|
322
|
+
"last_check": "2024-01-20T08:00:00Z"
|
|
323
|
+
}
|
|
324
|
+
]
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
---
|
|
328
|
+
|
|
329
|
+
## Dependencies
|
|
330
|
+
|
|
331
|
+
```python
|
|
332
|
+
# /// script
|
|
333
|
+
# requires-python = ">=3.10"
|
|
334
|
+
# dependencies = [
|
|
335
|
+
# "yfinance>=0.2.40", # Stock data
|
|
336
|
+
# "pandas>=2.0.0", # Data manipulation
|
|
337
|
+
# "fear-and-greed>=0.4", # CNN Fear & Greed
|
|
338
|
+
# "edgartools>=2.0.0", # SEC EDGAR filings
|
|
339
|
+
# "feedparser>=6.0.0", # RSS parsing
|
|
340
|
+
# ]
|
|
341
|
+
# ///
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
**Why These:**
|
|
345
|
+
- `yfinance`: Most reliable free stock API
|
|
346
|
+
- `pandas`: Industry standard for financial data
|
|
347
|
+
- `fear-and-greed`: Simple CNN F&G wrapper
|
|
348
|
+
- `edgartools`: Clean SEC EDGAR access
|
|
349
|
+
- `feedparser`: Robust RSS parsing
|
|
350
|
+
|
|
351
|
+
---
|
|
352
|
+
|
|
353
|
+
## Performance Optimization
|
|
354
|
+
|
|
355
|
+
### Current
|
|
356
|
+
|
|
357
|
+
| Operation | Time |
|
|
358
|
+
|-----------|------|
|
|
359
|
+
| yfinance fetch | ~2s |
|
|
360
|
+
| Market context | ~1s (cached after) |
|
|
361
|
+
| Insider trading | ~3-5s (slowest!) |
|
|
362
|
+
| Sentiment (parallel) | ~3-5s |
|
|
363
|
+
| Synthesis | ~10ms |
|
|
364
|
+
| **Total** | **5-10s** |
|
|
365
|
+
|
|
366
|
+
### Fast Mode (`--fast`)
|
|
367
|
+
|
|
368
|
+
Skips:
|
|
369
|
+
- Insider trading (SEC EDGAR)
|
|
370
|
+
- Breaking news scan
|
|
371
|
+
|
|
372
|
+
**Result:** 2-3 seconds
|
|
373
|
+
|
|
374
|
+
### Future Optimizations
|
|
375
|
+
|
|
376
|
+
1. **Stock-level caching** — Cache fundamentals for 24h
|
|
377
|
+
2. **Batch API calls** — yfinance supports multiple tickers
|
|
378
|
+
3. **Background refresh** — Pre-fetch watchlist data
|
|
379
|
+
4. **Local SEC data** — Avoid EDGAR API calls
|
|
380
|
+
|
|
381
|
+
---
|
|
382
|
+
|
|
383
|
+
## Error Handling
|
|
384
|
+
|
|
385
|
+
### Retry Strategy
|
|
386
|
+
|
|
387
|
+
```python
|
|
388
|
+
max_retries = 3
|
|
389
|
+
for attempt in range(max_retries):
|
|
390
|
+
try:
|
|
391
|
+
# fetch data
|
|
392
|
+
except Exception as e:
|
|
393
|
+
wait_time = 2 ** attempt # Exponential backoff: 1, 2, 4 seconds
|
|
394
|
+
time.sleep(wait_time)
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
### Graceful Degradation
|
|
398
|
+
|
|
399
|
+
- Missing earnings → Skip dimension, reweight
|
|
400
|
+
- Missing analysts → Skip dimension, reweight
|
|
401
|
+
- Missing sentiment → Skip dimension, reweight
|
|
402
|
+
- API failure → Return None, continue with partial data
|
|
403
|
+
|
|
404
|
+
### Minimum Requirements
|
|
405
|
+
|
|
406
|
+
- At least 2 of 8 dimensions required
|
|
407
|
+
- At least 2 of 5 sentiment indicators required
|
|
408
|
+
- Otherwise → HOLD with low confidence
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
# Concept & Philosophy
|
|
2
|
+
|
|
3
|
+
## The Problem
|
|
4
|
+
|
|
5
|
+
Making investment decisions is hard. There's too much data, too many opinions, and too much noise. Most retail investors either:
|
|
6
|
+
|
|
7
|
+
1. **Over-simplify** — Buy based on headlines or tips
|
|
8
|
+
2. **Over-complicate** — Get lost in endless research
|
|
9
|
+
3. **Freeze** — Analysis paralysis, never act
|
|
10
|
+
|
|
11
|
+
## The Solution
|
|
12
|
+
|
|
13
|
+
Stock Analysis provides a **structured, multi-dimensional framework** that:
|
|
14
|
+
|
|
15
|
+
- Aggregates data from multiple sources
|
|
16
|
+
- Weighs different factors objectively
|
|
17
|
+
- Produces a clear **BUY / HOLD / SELL** signal
|
|
18
|
+
- Explains the reasoning with bullet points
|
|
19
|
+
- Flags risks and caveats
|
|
20
|
+
|
|
21
|
+
Think of it as a **second opinion** — not a replacement for your judgment, but a systematic check.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Core Philosophy
|
|
26
|
+
|
|
27
|
+
### 1. Multiple Perspectives Beat Single Metrics
|
|
28
|
+
|
|
29
|
+
No single metric tells the whole story:
|
|
30
|
+
- A low P/E might mean "cheap" or "dying business"
|
|
31
|
+
- High analyst ratings might mean "priced in" or "genuine upside"
|
|
32
|
+
- Strong momentum might mean "trend" or "overbought"
|
|
33
|
+
|
|
34
|
+
By combining **8 dimensions**, we get a more complete picture.
|
|
35
|
+
|
|
36
|
+
### 2. Contrarian Signals Matter
|
|
37
|
+
|
|
38
|
+
Some of our best signals are **contrarian**:
|
|
39
|
+
|
|
40
|
+
| Indicator | Crowd Says | We Interpret |
|
|
41
|
+
|-----------|------------|--------------|
|
|
42
|
+
| Extreme Fear (Fear & Greed < 25) | "Sell everything!" | Potential buy opportunity |
|
|
43
|
+
| Extreme Greed (> 75) | "Easy money!" | Caution, reduce exposure |
|
|
44
|
+
| High Short Interest + Days to Cover | "Stock is doomed" | Squeeze potential |
|
|
45
|
+
| Insider Buying | (often ignored) | Smart money signal |
|
|
46
|
+
|
|
47
|
+
### 3. Timing Matters
|
|
48
|
+
|
|
49
|
+
A good stock at the wrong time is a bad trade:
|
|
50
|
+
|
|
51
|
+
- **Pre-earnings** — Even strong stocks can gap down 10%+
|
|
52
|
+
- **Post-spike** — Buying after a 20% run often means buying the top
|
|
53
|
+
- **Overbought** — RSI > 70 + near 52-week high = high-risk entry
|
|
54
|
+
|
|
55
|
+
We detect these timing issues and adjust recommendations accordingly.
|
|
56
|
+
|
|
57
|
+
### 4. Context Changes Everything
|
|
58
|
+
|
|
59
|
+
The same stock behaves differently in different market regimes:
|
|
60
|
+
|
|
61
|
+
| Regime | Characteristics | Impact |
|
|
62
|
+
|--------|-----------------|--------|
|
|
63
|
+
| **Bull** | VIX < 20, SPY up | BUY signals more reliable |
|
|
64
|
+
| **Bear** | VIX > 30, SPY down | Even good stocks fall |
|
|
65
|
+
| **Risk-Off** | GLD/TLT/UUP rising | Flight to safety, reduce equity |
|
|
66
|
+
| **Geopolitical** | Crisis keywords | Sector-specific penalties |
|
|
67
|
+
|
|
68
|
+
### 5. Dividends Are Different
|
|
69
|
+
|
|
70
|
+
Income investors have different priorities than growth investors:
|
|
71
|
+
|
|
72
|
+
| Growth Investor | Income Investor |
|
|
73
|
+
|-----------------|-----------------|
|
|
74
|
+
| Price appreciation | Dividend yield |
|
|
75
|
+
| Revenue growth | Payout sustainability |
|
|
76
|
+
| Market share | Dividend growth rate |
|
|
77
|
+
| P/E ratio | Safety of payment |
|
|
78
|
+
|
|
79
|
+
That's why we have a **separate dividend analysis** module.
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## The 8 Dimensions
|
|
84
|
+
|
|
85
|
+
### Why These 8?
|
|
86
|
+
|
|
87
|
+
Each dimension captures a different aspect of investment quality:
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
91
|
+
│ FUNDAMENTAL VALUE │
|
|
92
|
+
│ ┌─────────────────┐ ┌─────────────────┐ │
|
|
93
|
+
│ │ Earnings │ │ Fundamentals │ │
|
|
94
|
+
│ │ Surprise │ │ (P/E, etc.) │ │
|
|
95
|
+
│ │ (30%) │ │ (20%) │ │
|
|
96
|
+
│ └─────────────────┘ └─────────────────┘ │
|
|
97
|
+
├─────────────────────────────────────────────────────────────┤
|
|
98
|
+
│ EXTERNAL VALIDATION │
|
|
99
|
+
│ ┌─────────────────┐ ┌─────────────────┐ │
|
|
100
|
+
│ │ Analyst │ │ Historical │ │
|
|
101
|
+
│ │ Sentiment │ │ Patterns │ │
|
|
102
|
+
│ │ (20%) │ │ (10%) │ │
|
|
103
|
+
│ └─────────────────┘ └─────────────────┘ │
|
|
104
|
+
├─────────────────────────────────────────────────────────────┤
|
|
105
|
+
│ MARKET ENVIRONMENT │
|
|
106
|
+
│ ┌─────────────────┐ ┌─────────────────┐ │
|
|
107
|
+
│ │ Market │ │ Sector │ │
|
|
108
|
+
│ │ Context │ │ Performance │ │
|
|
109
|
+
│ │ (10%) │ │ (15%) │ │
|
|
110
|
+
│ └─────────────────┘ └─────────────────┘ │
|
|
111
|
+
├─────────────────────────────────────────────────────────────┤
|
|
112
|
+
│ TECHNICAL & SENTIMENT │
|
|
113
|
+
│ ┌─────────────────┐ ┌─────────────────┐ │
|
|
114
|
+
│ │ Momentum │ │ Sentiment │ │
|
|
115
|
+
│ │ (RSI, range) │ │ (Fear, shorts) │ │
|
|
116
|
+
│ │ (15%) │ │ (10%) │ │
|
|
117
|
+
│ └─────────────────┘ └─────────────────┘ │
|
|
118
|
+
└─────────────────────────────────────────────────────────────┘
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Weight Rationale
|
|
122
|
+
|
|
123
|
+
| Weight | Dimension | Rationale |
|
|
124
|
+
|--------|-----------|-----------|
|
|
125
|
+
| 30% | Earnings | Most direct measure of company performance |
|
|
126
|
+
| 20% | Fundamentals | Long-term value indicators |
|
|
127
|
+
| 20% | Analysts | Professional consensus (with skepticism) |
|
|
128
|
+
| 15% | Sector | Relative performance matters |
|
|
129
|
+
| 15% | Momentum | Trend is your friend (until it isn't) |
|
|
130
|
+
| 10% | Market | Rising tide lifts all boats |
|
|
131
|
+
| 10% | Sentiment | Contrarian edge |
|
|
132
|
+
| 10% | Historical | Past behavior predicts future reactions |
|
|
133
|
+
|
|
134
|
+
**Note:** Weights auto-normalize when data is missing.
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Risk Detection Philosophy
|
|
139
|
+
|
|
140
|
+
### "Don't Lose Money"
|
|
141
|
+
|
|
142
|
+
Warren Buffett's Rule #1. Our risk detection is designed to **prevent bad entries**:
|
|
143
|
+
|
|
144
|
+
1. **Pre-Earnings Hold** — Don't buy right before a binary event
|
|
145
|
+
2. **Post-Spike Caution** — Don't chase a run-up
|
|
146
|
+
3. **Overbought Warning** — Technical exhaustion
|
|
147
|
+
4. **Risk-Off Mode** — When even good stocks fall
|
|
148
|
+
5. **Geopolitical Flags** — Sector-specific event risk
|
|
149
|
+
|
|
150
|
+
### False Positive vs False Negative
|
|
151
|
+
|
|
152
|
+
We err on the side of **caution**:
|
|
153
|
+
|
|
154
|
+
- Missing a 10% gain is annoying
|
|
155
|
+
- Catching a 30% loss is devastating
|
|
156
|
+
|
|
157
|
+
That's why our caveats are prominent, and we downgrade BUY → HOLD liberally.
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## Crypto Adaptation
|
|
162
|
+
|
|
163
|
+
Crypto is fundamentally different from stocks:
|
|
164
|
+
|
|
165
|
+
| Stocks | Crypto |
|
|
166
|
+
|--------|--------|
|
|
167
|
+
| Earnings | No earnings |
|
|
168
|
+
| P/E Ratio | Market cap tiers |
|
|
169
|
+
| Sector ETFs | BTC correlation |
|
|
170
|
+
| Dividends | Staking yields (not tracked) |
|
|
171
|
+
| SEC Filings | No filings |
|
|
172
|
+
|
|
173
|
+
We adapted the framework:
|
|
174
|
+
- **3 dimensions** instead of 8
|
|
175
|
+
- **BTC correlation** as a key metric
|
|
176
|
+
- **Category classification** (L1, DeFi, etc.)
|
|
177
|
+
- **No sentiment** (no insider data for crypto)
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## Why Not Just Use [X]?
|
|
182
|
+
|
|
183
|
+
### vs. Stock Screeners (Finviz, etc.)
|
|
184
|
+
- Screeners show data, we provide **recommendations**
|
|
185
|
+
- We combine fundamental + technical + sentiment
|
|
186
|
+
- We flag timing and risk issues
|
|
187
|
+
|
|
188
|
+
### vs. Analyst Reports
|
|
189
|
+
- Analysts have conflicts of interest
|
|
190
|
+
- Reports are often stale
|
|
191
|
+
- We aggregate multiple signals
|
|
192
|
+
|
|
193
|
+
### vs. Trading Bots
|
|
194
|
+
- Bots execute, we advise
|
|
195
|
+
- We explain reasoning
|
|
196
|
+
- Human stays in control
|
|
197
|
+
|
|
198
|
+
### vs. ChatGPT/AI Chat
|
|
199
|
+
- We have **structured scoring**, not just conversation
|
|
200
|
+
- Real-time data fetching
|
|
201
|
+
- Consistent methodology
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## Limitations We Acknowledge
|
|
206
|
+
|
|
207
|
+
1. **Data Lag** — Yahoo Finance is 15-20 min delayed
|
|
208
|
+
2. **US Focus** — International stocks have incomplete data
|
|
209
|
+
3. **No Execution** — We advise, you decide and execute
|
|
210
|
+
4. **Past ≠ Future** — All models have limits
|
|
211
|
+
5. **Black Swans** — Can't predict unpredictable events
|
|
212
|
+
|
|
213
|
+
**This is a tool, not a crystal ball.**
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## The Bottom Line
|
|
218
|
+
|
|
219
|
+
Stock Analysis v6.0 is designed to be your **systematic second opinion**:
|
|
220
|
+
|
|
221
|
+
- ✅ Multi-dimensional analysis
|
|
222
|
+
- ✅ Clear recommendations
|
|
223
|
+
- ✅ Risk detection
|
|
224
|
+
- ✅ Explained reasoning
|
|
225
|
+
- ✅ Fast and automated
|
|
226
|
+
|
|
227
|
+
**NOT:**
|
|
228
|
+
- ❌ Financial advice
|
|
229
|
+
- ❌ Guaranteed returns
|
|
230
|
+
- ❌ Replacement for research
|
|
231
|
+
- ❌ Trading signals
|
|
232
|
+
|
|
233
|
+
Use it wisely. 📈
|