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,167 @@
|
|
|
1
|
+
"""
|
|
2
|
+
OpenClaw Cron Job payload 构造器。
|
|
3
|
+
|
|
4
|
+
统一管理三种任务类型的 payload 格式,防止配置混乱。
|
|
5
|
+
|
|
6
|
+
投递规则:
|
|
7
|
+
- 一次性提醒 → sessionTarget=main + payload.kind=systemEvent
|
|
8
|
+
- 周期静默监控 → sessionTarget=isolated + delivery.mode=none
|
|
9
|
+
- 报告/推送任务 → sessionTarget=isolated + delivery.mode=announce + channel 指定
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import uuid
|
|
15
|
+
import time
|
|
16
|
+
from datetime import datetime, timezone
|
|
17
|
+
from typing import Any
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _new_id() -> str:
|
|
21
|
+
return str(uuid.uuid4())
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _now_ms() -> int:
|
|
25
|
+
return int(time.time() * 1000)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def build_reminder_task_name(
|
|
29
|
+
summary: str,
|
|
30
|
+
start_dt: datetime,
|
|
31
|
+
event_id: str = "",
|
|
32
|
+
) -> str:
|
|
33
|
+
if event_id:
|
|
34
|
+
suffix = event_id
|
|
35
|
+
else:
|
|
36
|
+
if start_dt.tzinfo is None:
|
|
37
|
+
raise ValueError("start_dt 必须是 timezone-aware datetime")
|
|
38
|
+
suffix = start_dt.astimezone(timezone.utc).strftime("%Y%m%dT%H%M%SZ")
|
|
39
|
+
return f"提醒-{summary}-{suffix}"
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def build_reminder_task(
|
|
43
|
+
name: str,
|
|
44
|
+
remind_at_utc: datetime,
|
|
45
|
+
message: str,
|
|
46
|
+
) -> dict[str, Any]:
|
|
47
|
+
"""
|
|
48
|
+
一次性提醒任务。
|
|
49
|
+
|
|
50
|
+
投递方式:main + systemEvent。
|
|
51
|
+
不设置 delivery,避免 webchat / announce 渠道兼容性问题。
|
|
52
|
+
"""
|
|
53
|
+
now = _now_ms()
|
|
54
|
+
return {
|
|
55
|
+
"id": _new_id(),
|
|
56
|
+
"name": name,
|
|
57
|
+
"enabled": True,
|
|
58
|
+
"deleteAfterRun": True,
|
|
59
|
+
"createdAtMs": now,
|
|
60
|
+
"updatedAtMs": now,
|
|
61
|
+
"schedule": {
|
|
62
|
+
"kind": "at",
|
|
63
|
+
"at": _utc_str(remind_at_utc),
|
|
64
|
+
},
|
|
65
|
+
"sessionTarget": "main",
|
|
66
|
+
"wakeMode": "next-heartbeat",
|
|
67
|
+
"payload": {
|
|
68
|
+
"kind": "systemEvent",
|
|
69
|
+
"message": message,
|
|
70
|
+
},
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def build_periodic_silent_task(
|
|
75
|
+
name: str,
|
|
76
|
+
cron_expr: str,
|
|
77
|
+
message: str,
|
|
78
|
+
tz: str = "Asia/Shanghai",
|
|
79
|
+
) -> dict[str, Any]:
|
|
80
|
+
"""
|
|
81
|
+
周期性静默监控任务。
|
|
82
|
+
|
|
83
|
+
投递方式:isolated + delivery.mode=none。
|
|
84
|
+
适用:日程变化监控、context 使用率检查等。
|
|
85
|
+
"""
|
|
86
|
+
now = _now_ms()
|
|
87
|
+
return {
|
|
88
|
+
"id": _new_id(),
|
|
89
|
+
"name": name,
|
|
90
|
+
"enabled": True,
|
|
91
|
+
"createdAtMs": now,
|
|
92
|
+
"updatedAtMs": now,
|
|
93
|
+
"schedule": {
|
|
94
|
+
"kind": "cron",
|
|
95
|
+
"expr": cron_expr,
|
|
96
|
+
"tz": tz,
|
|
97
|
+
},
|
|
98
|
+
"sessionTarget": "isolated",
|
|
99
|
+
"wakeMode": "next-heartbeat",
|
|
100
|
+
"payload": {
|
|
101
|
+
"kind": "agentTurn",
|
|
102
|
+
"message": message,
|
|
103
|
+
},
|
|
104
|
+
"delivery": {"mode": "none"},
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def build_report_task(
|
|
109
|
+
name: str,
|
|
110
|
+
message: str,
|
|
111
|
+
channel: str = "",
|
|
112
|
+
to: str = "",
|
|
113
|
+
at_utc: datetime | None = None,
|
|
114
|
+
cron_expr: str | None = None,
|
|
115
|
+
tz: str = "Asia/Shanghai",
|
|
116
|
+
delete_after_run: bool = False,
|
|
117
|
+
) -> dict[str, Any]:
|
|
118
|
+
"""
|
|
119
|
+
报告/推送任务。
|
|
120
|
+
|
|
121
|
+
- channel/to 均为空(默认):deliver to channel="last"(最近活跃频道,不依赖 Telegram)
|
|
122
|
+
- to 有值:deliver to 指定 channel + to(Telegram 等具体频道)
|
|
123
|
+
|
|
124
|
+
at_utc 和 cron_expr 二选一:
|
|
125
|
+
- at_utc :一次性任务
|
|
126
|
+
- cron_expr :周期性任务
|
|
127
|
+
"""
|
|
128
|
+
if at_utc is not None:
|
|
129
|
+
schedule: dict[str, Any] = {"kind": "at", "at": _utc_str(at_utc)}
|
|
130
|
+
elif cron_expr is not None:
|
|
131
|
+
schedule = {"kind": "cron", "expr": cron_expr, "tz": tz}
|
|
132
|
+
else:
|
|
133
|
+
raise ValueError("at_utc 和 cron_expr 必须提供其中一个")
|
|
134
|
+
|
|
135
|
+
# 默认用 "last",Telegram 未配置时也能正常推送
|
|
136
|
+
if to:
|
|
137
|
+
delivery: dict[str, Any] = {"mode": "announce", "channel": channel, "to": to}
|
|
138
|
+
else:
|
|
139
|
+
delivery = {"mode": "announce", "channel": "last"}
|
|
140
|
+
|
|
141
|
+
now = _now_ms()
|
|
142
|
+
job: dict[str, Any] = {
|
|
143
|
+
"id": _new_id(),
|
|
144
|
+
"name": name,
|
|
145
|
+
"enabled": True,
|
|
146
|
+
"createdAtMs": now,
|
|
147
|
+
"updatedAtMs": now,
|
|
148
|
+
"schedule": schedule,
|
|
149
|
+
"sessionTarget": "isolated",
|
|
150
|
+
"wakeMode": "next-heartbeat",
|
|
151
|
+
"payload": {
|
|
152
|
+
"kind": "agentTurn",
|
|
153
|
+
"message": message,
|
|
154
|
+
},
|
|
155
|
+
"delivery": delivery,
|
|
156
|
+
}
|
|
157
|
+
if delete_after_run:
|
|
158
|
+
job["deleteAfterRun"] = True
|
|
159
|
+
return job
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
# ─────────────────────────── 内部工具 ────────────────────────────
|
|
163
|
+
|
|
164
|
+
def _utc_str(dt: datetime) -> str:
|
|
165
|
+
if dt.tzinfo is None:
|
|
166
|
+
raise ValueError("datetime 必须携带时区信息,不能把 naive datetime 当作 UTC")
|
|
167
|
+
return dt.astimezone(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"""
|
|
2
|
+
时间窗口工具。
|
|
3
|
+
|
|
4
|
+
所有窗口均基于指定时区的自然日边界(00:00:00),
|
|
5
|
+
不依赖系统本地时区,不使用 timedelta 滚动计算。
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import sys
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
|
|
13
|
+
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
14
|
+
|
|
15
|
+
from datetime import datetime, timedelta
|
|
16
|
+
from compat import ZoneInfo, make_aware
|
|
17
|
+
|
|
18
|
+
_DEFAULT_TZ = "Asia/Shanghai"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def get_today_window(tz: str = _DEFAULT_TZ) -> tuple[datetime, datetime]:
|
|
22
|
+
"""
|
|
23
|
+
今天的时间窗口:[今天 00:00, 明天 00:00),timezone-aware。
|
|
24
|
+
"""
|
|
25
|
+
zone = ZoneInfo(tz)
|
|
26
|
+
now = datetime.now(zone)
|
|
27
|
+
start = now.replace(hour=0, minute=0, second=0, microsecond=0)
|
|
28
|
+
end = start + timedelta(days=1)
|
|
29
|
+
return start, end
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def get_today_and_tomorrow_window(tz: str = _DEFAULT_TZ) -> tuple[datetime, datetime]:
|
|
33
|
+
"""
|
|
34
|
+
今天 + 明天:[今天 00:00, 后天 00:00),timezone-aware。
|
|
35
|
+
|
|
36
|
+
对应产品语义"监控今天+明天到明天 24:00 为止"。
|
|
37
|
+
"""
|
|
38
|
+
start, _ = get_today_window(tz)
|
|
39
|
+
return start, start + timedelta(days=2)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def get_next_n_days_window(
|
|
43
|
+
days: int,
|
|
44
|
+
tz: str = _DEFAULT_TZ,
|
|
45
|
+
from_now: bool = False,
|
|
46
|
+
) -> tuple[datetime, datetime]:
|
|
47
|
+
"""
|
|
48
|
+
未来 N 个自然日的窗口。
|
|
49
|
+
from_now=False(默认):从今天 00:00 开始
|
|
50
|
+
from_now=True :从当前时刻开始
|
|
51
|
+
"""
|
|
52
|
+
zone = ZoneInfo(tz)
|
|
53
|
+
now = datetime.now(zone)
|
|
54
|
+
start = now if from_now else now.replace(hour=0, minute=0, second=0, microsecond=0)
|
|
55
|
+
end = now.replace(hour=0, minute=0, second=0, microsecond=0) + timedelta(days=days)
|
|
56
|
+
return start, end
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def get_remaining_today_window(tz: str = _DEFAULT_TZ) -> tuple[datetime, datetime]:
|
|
60
|
+
"""
|
|
61
|
+
今天剩余时间:[当前时刻, 今天 24:00)。
|
|
62
|
+
用于"只查今天还没开始的事件"(check_reminders 场景)。
|
|
63
|
+
"""
|
|
64
|
+
zone = ZoneInfo(tz)
|
|
65
|
+
now = datetime.now(zone)
|
|
66
|
+
end = now.replace(hour=0, minute=0, second=0, microsecond=0) + timedelta(days=1)
|
|
67
|
+
return now, end
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def now_tz(tz: str = _DEFAULT_TZ) -> datetime:
|
|
71
|
+
"""返回当前指定时区时间(aware datetime)。"""
|
|
72
|
+
return datetime.now(ZoneInfo(tz))
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "sophnet-stock",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"types": [
|
|
5
|
+
"store"
|
|
6
|
+
],
|
|
7
|
+
"displayName": "股票分析助手",
|
|
8
|
+
"description": "支持实时股票数据查询、图表绘制、技术指标计算与分析,以及基于 AI 的个性化投资建议和风险评估。",
|
|
9
|
+
"changelog": [
|
|
10
|
+
{
|
|
11
|
+
"version": "1.0.0",
|
|
12
|
+
"date": "2026-04-14",
|
|
13
|
+
"changes": [
|
|
14
|
+
"初次提交"
|
|
15
|
+
]
|
|
16
|
+
}
|
|
17
|
+
],
|
|
18
|
+
"createdAt": "2026-04-14",
|
|
19
|
+
"updatedAt": "2026-04-14"
|
|
20
|
+
}
|
|
@@ -0,0 +1,442 @@
|
|
|
1
|
+
# StockPulse - Commercial Product Roadmap
|
|
2
|
+
|
|
3
|
+
## Vision
|
|
4
|
+
|
|
5
|
+
Transform the stock-analysis skill into **StockPulse**, a commercial mobile app for retail investors with AI-powered stock and crypto analysis, portfolio tracking, and personalized alerts.
|
|
6
|
+
|
|
7
|
+
## Technical Decisions
|
|
8
|
+
|
|
9
|
+
- **Mobile:** Flutter (iOS + Android cross-platform)
|
|
10
|
+
- **Backend:** Python FastAPI on AWS (ECS/Lambda)
|
|
11
|
+
- **Database:** PostgreSQL (RDS) + Redis (ElastiCache)
|
|
12
|
+
- **Auth:** AWS Cognito or Firebase Auth
|
|
13
|
+
- **Monetization:** Freemium + Subscription ($9.99/mo or $79.99/yr)
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Architecture Overview
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
21
|
+
│ MOBILE APP (Flutter) │
|
|
22
|
+
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
|
23
|
+
│ │Dashboard │ │Portfolio │ │ Analysis │ │ Alerts │ │
|
|
24
|
+
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
|
|
25
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
26
|
+
│ HTTPS/REST
|
|
27
|
+
▼
|
|
28
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
29
|
+
│ API GATEWAY (AWS) │
|
|
30
|
+
│ Rate Limiting, Auth, Caching │
|
|
31
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
32
|
+
│
|
|
33
|
+
▼
|
|
34
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
35
|
+
│ BACKEND (FastAPI on ECS) │
|
|
36
|
+
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
|
37
|
+
│ │ Auth Service │ │ Analysis API │ │ Portfolio API│ │
|
|
38
|
+
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
|
39
|
+
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
|
40
|
+
│ │ Alerts Svc │ │ Subscription │ │ User Service │ │
|
|
41
|
+
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
|
42
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
43
|
+
│
|
|
44
|
+
┌─────────────────────┼─────────────────────┐
|
|
45
|
+
▼ ▼ ▼
|
|
46
|
+
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
|
47
|
+
│ PostgreSQL │ │ Redis │ │ S3 │
|
|
48
|
+
│ (RDS) │ │ (ElastiCache)│ │ (Reports) │
|
|
49
|
+
└──────────────┘ └──────────────┘ └──────────────┘
|
|
50
|
+
|
|
51
|
+
BACKGROUND WORKERS (Lambda/ECS)
|
|
52
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
53
|
+
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
|
54
|
+
│ │Price Updater │ │Alert Checker │ │Daily Reports │ │
|
|
55
|
+
│ │ (5 min) │ │ (1 min) │ │ (Daily) │ │
|
|
56
|
+
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
|
57
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Feature Tiers
|
|
63
|
+
|
|
64
|
+
### Free Tier
|
|
65
|
+
- 1 portfolio (max 10 assets)
|
|
66
|
+
- Basic stock/crypto analysis
|
|
67
|
+
- Daily market summary
|
|
68
|
+
- Limited to 5 analyses/day
|
|
69
|
+
- Ads displayed
|
|
70
|
+
|
|
71
|
+
### Premium ($9.99/mo)
|
|
72
|
+
- Unlimited portfolios & assets
|
|
73
|
+
- Full 8-dimension analysis
|
|
74
|
+
- Real-time price alerts
|
|
75
|
+
- Push notifications
|
|
76
|
+
- Period reports (daily/weekly/monthly)
|
|
77
|
+
- No ads
|
|
78
|
+
- Priority support
|
|
79
|
+
|
|
80
|
+
### Pro ($19.99/mo) - Future
|
|
81
|
+
- API access
|
|
82
|
+
- Custom watchlists
|
|
83
|
+
- Advanced screeners
|
|
84
|
+
- Export to CSV/PDF
|
|
85
|
+
- Portfolio optimization suggestions
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Development Phases
|
|
90
|
+
|
|
91
|
+
### Phase 1: Backend API
|
|
92
|
+
|
|
93
|
+
**Goal:** Convert Python scripts to production REST API
|
|
94
|
+
|
|
95
|
+
#### Tasks:
|
|
96
|
+
1. **Project Setup**
|
|
97
|
+
- FastAPI project structure
|
|
98
|
+
- Docker containerization
|
|
99
|
+
- CI/CD pipeline (GitHub Actions)
|
|
100
|
+
- AWS infrastructure (Terraform)
|
|
101
|
+
|
|
102
|
+
2. **Core API Endpoints**
|
|
103
|
+
```
|
|
104
|
+
POST /auth/register
|
|
105
|
+
POST /auth/login
|
|
106
|
+
POST /auth/refresh
|
|
107
|
+
|
|
108
|
+
GET /analysis/{ticker}
|
|
109
|
+
POST /analysis/batch
|
|
110
|
+
|
|
111
|
+
GET /portfolios
|
|
112
|
+
POST /portfolios
|
|
113
|
+
PUT /portfolios/{id}
|
|
114
|
+
DELETE /portfolios/{id}
|
|
115
|
+
|
|
116
|
+
GET /portfolios/{id}/assets
|
|
117
|
+
POST /portfolios/{id}/assets
|
|
118
|
+
PUT /portfolios/{id}/assets/{ticker}
|
|
119
|
+
DELETE /portfolios/{id}/assets/{ticker}
|
|
120
|
+
|
|
121
|
+
GET /portfolios/{id}/performance?period=weekly
|
|
122
|
+
GET /portfolios/{id}/summary
|
|
123
|
+
|
|
124
|
+
GET /alerts
|
|
125
|
+
POST /alerts
|
|
126
|
+
DELETE /alerts/{id}
|
|
127
|
+
|
|
128
|
+
GET /user/subscription
|
|
129
|
+
POST /user/subscription/upgrade
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
3. **Database Schema**
|
|
133
|
+
```sql
|
|
134
|
+
users (id, email, password_hash, created_at, subscription_tier)
|
|
135
|
+
portfolios (id, user_id, name, created_at, updated_at)
|
|
136
|
+
assets (id, portfolio_id, ticker, asset_type, quantity, cost_basis)
|
|
137
|
+
alerts (id, user_id, ticker, condition, threshold, enabled)
|
|
138
|
+
analysis_cache (ticker, data, expires_at)
|
|
139
|
+
subscriptions (id, user_id, stripe_id, status, expires_at)
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
4. **Refactor Existing Code**
|
|
143
|
+
- Extract `analyze_stock.py` into modules:
|
|
144
|
+
- `analysis/earnings.py`
|
|
145
|
+
- `analysis/fundamentals.py`
|
|
146
|
+
- `analysis/sentiment.py`
|
|
147
|
+
- `analysis/crypto.py`
|
|
148
|
+
- `analysis/market_context.py`
|
|
149
|
+
- Add async support throughout
|
|
150
|
+
- Implement proper caching (Redis)
|
|
151
|
+
- Rate limiting per user tier
|
|
152
|
+
|
|
153
|
+
#### Files to Create:
|
|
154
|
+
```
|
|
155
|
+
backend/
|
|
156
|
+
├── app/
|
|
157
|
+
│ ├── main.py # FastAPI app
|
|
158
|
+
│ ├── config.py # Settings
|
|
159
|
+
│ ├── models/ # SQLAlchemy models
|
|
160
|
+
│ ├── schemas/ # Pydantic schemas
|
|
161
|
+
│ ├── routers/ # API routes
|
|
162
|
+
│ │ ├── auth.py
|
|
163
|
+
│ │ ├── analysis.py
|
|
164
|
+
│ │ ├── portfolios.py
|
|
165
|
+
│ │ └── alerts.py
|
|
166
|
+
│ ├── services/ # Business logic
|
|
167
|
+
│ │ ├── analysis/ # Refactored from analyze_stock.py
|
|
168
|
+
│ │ ├── portfolio.py
|
|
169
|
+
│ │ └── alerts.py
|
|
170
|
+
│ └── workers/ # Background tasks
|
|
171
|
+
├── tests/
|
|
172
|
+
├── Dockerfile
|
|
173
|
+
├── docker-compose.yml
|
|
174
|
+
└── requirements.txt
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
### Phase 2: Flutter Mobile App
|
|
180
|
+
|
|
181
|
+
**Goal:** Build polished cross-platform mobile app
|
|
182
|
+
|
|
183
|
+
#### Screens:
|
|
184
|
+
1. **Onboarding** - Welcome, feature highlights, sign up/login
|
|
185
|
+
2. **Dashboard** - Market overview, portfolio summary, alerts
|
|
186
|
+
3. **Analysis** - Search ticker, view full analysis, save to portfolio
|
|
187
|
+
4. **Portfolio** - List portfolios, asset breakdown, P&L chart
|
|
188
|
+
5. **Alerts** - Manage price alerts, notification settings
|
|
189
|
+
6. **Settings** - Account, subscription, preferences
|
|
190
|
+
|
|
191
|
+
#### Key Flutter Packages:
|
|
192
|
+
```yaml
|
|
193
|
+
dependencies:
|
|
194
|
+
flutter_bloc: ^8.0.0 # State management
|
|
195
|
+
dio: ^5.0.0 # HTTP client
|
|
196
|
+
go_router: ^12.0.0 # Navigation
|
|
197
|
+
fl_chart: ^0.65.0 # Charts
|
|
198
|
+
firebase_messaging: ^14.0.0 # Push notifications
|
|
199
|
+
in_app_purchase: ^3.0.0 # Subscriptions
|
|
200
|
+
shared_preferences: ^2.0.0
|
|
201
|
+
flutter_secure_storage: ^9.0.0
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
#### App Structure:
|
|
205
|
+
```
|
|
206
|
+
lib/
|
|
207
|
+
├── main.dart
|
|
208
|
+
├── app/
|
|
209
|
+
│ ├── routes.dart
|
|
210
|
+
│ └── theme.dart
|
|
211
|
+
├── features/
|
|
212
|
+
│ ├── auth/
|
|
213
|
+
│ │ ├── bloc/
|
|
214
|
+
│ │ ├── screens/
|
|
215
|
+
│ │ └── widgets/
|
|
216
|
+
│ ├── dashboard/
|
|
217
|
+
│ ├── analysis/
|
|
218
|
+
│ ├── portfolio/
|
|
219
|
+
│ ├── alerts/
|
|
220
|
+
│ └── settings/
|
|
221
|
+
├── core/
|
|
222
|
+
│ ├── api/
|
|
223
|
+
│ ├── models/
|
|
224
|
+
│ └── utils/
|
|
225
|
+
└── shared/
|
|
226
|
+
└── widgets/
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
### Phase 3: Infrastructure & DevOps
|
|
232
|
+
|
|
233
|
+
**Goal:** Production-ready cloud infrastructure
|
|
234
|
+
|
|
235
|
+
#### AWS Services:
|
|
236
|
+
- **ECS Fargate** - Backend containers
|
|
237
|
+
- **RDS PostgreSQL** - Database
|
|
238
|
+
- **ElastiCache Redis** - Caching
|
|
239
|
+
- **S3** - Static assets, reports
|
|
240
|
+
- **CloudFront** - CDN
|
|
241
|
+
- **Cognito** - Authentication
|
|
242
|
+
- **SES** - Email notifications
|
|
243
|
+
- **SNS** - Push notifications
|
|
244
|
+
- **CloudWatch** - Monitoring
|
|
245
|
+
- **WAF** - Security
|
|
246
|
+
|
|
247
|
+
#### Terraform Modules:
|
|
248
|
+
```
|
|
249
|
+
infrastructure/
|
|
250
|
+
├── main.tf
|
|
251
|
+
├── variables.tf
|
|
252
|
+
├── modules/
|
|
253
|
+
│ ├── vpc/
|
|
254
|
+
│ ├── ecs/
|
|
255
|
+
│ ├── rds/
|
|
256
|
+
│ ├── elasticache/
|
|
257
|
+
│ └── cognito/
|
|
258
|
+
└── environments/
|
|
259
|
+
├── dev/
|
|
260
|
+
├── staging/
|
|
261
|
+
└── prod/
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
#### Estimated Monthly Costs (Production):
|
|
265
|
+
| Service | Est. Cost |
|
|
266
|
+
|---------|-----------|
|
|
267
|
+
| ECS Fargate (2 tasks) | $50-100 |
|
|
268
|
+
| RDS (db.t3.small) | $30-50 |
|
|
269
|
+
| ElastiCache (cache.t3.micro) | $15-25 |
|
|
270
|
+
| S3 + CloudFront | $10-20 |
|
|
271
|
+
| Other (Cognito, SES, etc.) | $20-30 |
|
|
272
|
+
| **Total** | **$125-225/mo** |
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
|
|
276
|
+
### Phase 4: Payments & Subscriptions
|
|
277
|
+
|
|
278
|
+
**Goal:** Integrate Stripe for subscriptions
|
|
279
|
+
|
|
280
|
+
#### Implementation:
|
|
281
|
+
1. Stripe subscription products (Free, Premium, Pro)
|
|
282
|
+
2. In-app purchase for iOS/Android
|
|
283
|
+
3. Webhook handlers for subscription events
|
|
284
|
+
4. Grace period handling
|
|
285
|
+
5. Receipt validation
|
|
286
|
+
|
|
287
|
+
#### Stripe Integration:
|
|
288
|
+
```python
|
|
289
|
+
# Backend webhook handler
|
|
290
|
+
@router.post("/webhooks/stripe")
|
|
291
|
+
async def stripe_webhook(request: Request):
|
|
292
|
+
event = stripe.Webhook.construct_event(...)
|
|
293
|
+
|
|
294
|
+
if event.type == "customer.subscription.updated":
|
|
295
|
+
update_user_tier(event.data.object)
|
|
296
|
+
elif event.type == "customer.subscription.deleted":
|
|
297
|
+
downgrade_to_free(event.data.object)
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
---
|
|
301
|
+
|
|
302
|
+
### Phase 5: Push Notifications & Alerts
|
|
303
|
+
|
|
304
|
+
**Goal:** Real-time price alerts and notifications
|
|
305
|
+
|
|
306
|
+
#### Alert Types:
|
|
307
|
+
- Price above/below threshold
|
|
308
|
+
- Percentage change (daily)
|
|
309
|
+
- Earnings announcement
|
|
310
|
+
- Breaking news (geopolitical)
|
|
311
|
+
- Portfolio performance
|
|
312
|
+
|
|
313
|
+
#### Implementation:
|
|
314
|
+
- Firebase Cloud Messaging (FCM)
|
|
315
|
+
- Background worker checks alerts every minute
|
|
316
|
+
- Rate limit: max 10 alerts/day per free user
|
|
317
|
+
|
|
318
|
+
---
|
|
319
|
+
|
|
320
|
+
### Phase 6: Analytics & Monitoring
|
|
321
|
+
|
|
322
|
+
**Goal:** Track usage, errors, business metrics
|
|
323
|
+
|
|
324
|
+
#### Tools:
|
|
325
|
+
- **Mixpanel/Amplitude** - Product analytics
|
|
326
|
+
- **Sentry** - Error tracking
|
|
327
|
+
- **CloudWatch** - Infrastructure metrics
|
|
328
|
+
- **Custom dashboard** - Business KPIs
|
|
329
|
+
|
|
330
|
+
#### Key Metrics:
|
|
331
|
+
- DAU/MAU
|
|
332
|
+
- Conversion rate (free → premium)
|
|
333
|
+
- Churn rate
|
|
334
|
+
- API response times
|
|
335
|
+
- Analysis accuracy feedback
|
|
336
|
+
|
|
337
|
+
---
|
|
338
|
+
|
|
339
|
+
## Security Considerations
|
|
340
|
+
|
|
341
|
+
1. **Authentication**
|
|
342
|
+
- JWT tokens with refresh rotation
|
|
343
|
+
- OAuth2 (Google, Apple Sign-In)
|
|
344
|
+
- 2FA optional for premium users
|
|
345
|
+
|
|
346
|
+
2. **Data Protection**
|
|
347
|
+
- Encrypt PII at rest (RDS encryption)
|
|
348
|
+
- TLS 1.3 for all API traffic
|
|
349
|
+
- No plaintext passwords
|
|
350
|
+
|
|
351
|
+
3. **API Security**
|
|
352
|
+
- Rate limiting per tier
|
|
353
|
+
- Input validation (Pydantic)
|
|
354
|
+
- SQL injection prevention (SQLAlchemy ORM)
|
|
355
|
+
- CORS configuration
|
|
356
|
+
|
|
357
|
+
4. **Compliance**
|
|
358
|
+
- Privacy policy
|
|
359
|
+
- Terms of service
|
|
360
|
+
- GDPR data export/deletion
|
|
361
|
+
- Financial disclaimer (not investment advice)
|
|
362
|
+
|
|
363
|
+
---
|
|
364
|
+
|
|
365
|
+
## Risks & Mitigations
|
|
366
|
+
|
|
367
|
+
| Risk | Impact | Mitigation |
|
|
368
|
+
|------|--------|------------|
|
|
369
|
+
| Yahoo Finance rate limits | High | Implement caching, use paid API fallback |
|
|
370
|
+
| App store rejection | Medium | Follow guidelines, proper disclaimers |
|
|
371
|
+
| Data accuracy issues | High | Clear disclaimers, data validation |
|
|
372
|
+
| Security breach | Critical | Security audit, penetration testing |
|
|
373
|
+
| Low conversion rate | Medium | A/B testing, feature gating |
|
|
374
|
+
|
|
375
|
+
---
|
|
376
|
+
|
|
377
|
+
## Success Metrics (Year 1)
|
|
378
|
+
|
|
379
|
+
| Metric | Target |
|
|
380
|
+
|--------|--------|
|
|
381
|
+
| App downloads | 10,000+ |
|
|
382
|
+
| DAU | 1,000+ |
|
|
383
|
+
| Premium subscribers | 500+ |
|
|
384
|
+
| Monthly revenue | $5,000+ |
|
|
385
|
+
| App store rating | 4.5+ stars |
|
|
386
|
+
| Churn rate | <5%/month |
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
## Next Steps (Immediate)
|
|
391
|
+
|
|
392
|
+
1. **Validate idea** - User interviews, landing page
|
|
393
|
+
2. **Design** - Figma mockups for key screens
|
|
394
|
+
3. **Backend MVP** - Core API endpoints
|
|
395
|
+
4. **Flutter prototype** - Basic app with analysis feature
|
|
396
|
+
5. **Beta testing** - TestFlight/Google Play beta
|
|
397
|
+
|
|
398
|
+
---
|
|
399
|
+
|
|
400
|
+
## Repository Structure (Final)
|
|
401
|
+
|
|
402
|
+
```
|
|
403
|
+
stockpulse/
|
|
404
|
+
├── backend/ # FastAPI backend
|
|
405
|
+
│ ├── app/
|
|
406
|
+
│ ├── tests/
|
|
407
|
+
│ ├── Dockerfile
|
|
408
|
+
│ └── requirements.txt
|
|
409
|
+
├── mobile/ # Flutter app
|
|
410
|
+
│ ├── lib/
|
|
411
|
+
│ ├── test/
|
|
412
|
+
│ ├── ios/
|
|
413
|
+
│ ├── android/
|
|
414
|
+
│ └── pubspec.yaml
|
|
415
|
+
├── infrastructure/ # Terraform
|
|
416
|
+
│ ├── modules/
|
|
417
|
+
│ └── environments/
|
|
418
|
+
├── docs/ # Documentation
|
|
419
|
+
│ ├── api/
|
|
420
|
+
│ └── architecture/
|
|
421
|
+
└── scripts/ # Utility scripts
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
---
|
|
425
|
+
|
|
426
|
+
## Timeline Summary (Planning Only)
|
|
427
|
+
|
|
428
|
+
| Phase | Duration | Dependencies |
|
|
429
|
+
|-------|----------|--------------|
|
|
430
|
+
| 1. Backend API | 4-6 weeks | - |
|
|
431
|
+
| 2. Flutter App | 6-8 weeks | Phase 1 |
|
|
432
|
+
| 3. Infrastructure | 2-3 weeks | Phase 1 |
|
|
433
|
+
| 4. Payments | 2 weeks | Phase 2, 3 |
|
|
434
|
+
| 5. Notifications | 2 weeks | Phase 2, 3 |
|
|
435
|
+
| 6. Analytics | 1 week | Phase 2 |
|
|
436
|
+
| **Total** | **17-22 weeks** | |
|
|
437
|
+
|
|
438
|
+
This is a planning document. No fixed timeline - execute phases as resources allow.
|
|
439
|
+
|
|
440
|
+
---
|
|
441
|
+
|
|
442
|
+
**Disclaimer:** This tool is for informational purposes only and does NOT constitute financial advice.
|