opentradex 0.1.1 → 0.1.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/.env.example +8 -0
- package/README.md +3 -1
- package/gossip/__pycache__/polymarket.cpython-314.pyc +0 -0
- package/main.py +38 -7
- package/package.json +1 -1
- package/src/catalog.mjs +76 -4
- package/src/cli.mjs +44 -18
- package/src/index.mjs +433 -19
- package/web/next-env.d.ts +6 -0
- package/web/src/app/api/workspace/route.ts +12 -0
- package/web/src/app/globals.css +28 -0
- package/web/src/app/guide/page.tsx +262 -0
- package/web/src/app/layout.tsx +2 -1
- package/web/src/app/page.tsx +15 -0
- package/web/src/components/DashboardApp.tsx +192 -88
- package/web/src/components/HarnessBootPanel.tsx +160 -0
- package/web/src/components/LiveStream.tsx +632 -255
- package/web/src/components/TopBar.tsx +135 -82
- package/web/src/lib/demo-data.ts +25 -0
- package/web/src/lib/trading-guide-content.ts +337 -0
- package/web/src/lib/types.ts +30 -0
- package/web/src/lib/workspace.ts +117 -0
- package/web/.playwright-cli/page-2026-04-05T08-03-12-564Z.yml +0 -289
- package/web/.playwright-cli/page-2026-04-05T08-07-03-122Z.yml +0 -289
- package/web/.playwright-cli/page-2026-04-05T08-07-09-741Z.yml +0 -227
- package/web/.playwright-cli/page-2026-04-05T08-07-37-379Z.yml +0 -287
- package/web/.playwright-cli/page-2026-04-05T08-07-43-577Z.yml +0 -227
- package/web/output/playwright/dashboard.png +0 -0
- package/web/output/playwright/home.png +0 -0
- package/web/output/playwright/next-start.err.log +0 -0
- package/web/output/playwright/next-start.out.log +0 -9
package/.env.example
CHANGED
|
@@ -9,6 +9,8 @@ OPENTRADEX_PRIMARY_MARKET=kalshi
|
|
|
9
9
|
OPENTRADEX_ENABLED_MARKETS=kalshi
|
|
10
10
|
OPENTRADEX_ENABLED_INTEGRATIONS=apify,rss
|
|
11
11
|
OPENTRADEX_LIVE_EXECUTION_MARKET=kalshi
|
|
12
|
+
OPENTRADEX_DASHBOARD_SURFACE=chat
|
|
13
|
+
OPENTRADEX_CHANNELS=command,markets,feeds,risk,execution
|
|
12
14
|
NEWS_PROVIDER=apify,rss
|
|
13
15
|
|
|
14
16
|
# Risk configuration
|
|
@@ -32,6 +34,12 @@ POLYMARKET_PRIVATE_KEY=
|
|
|
32
34
|
TRADINGVIEW_USERNAME=
|
|
33
35
|
TRADINGVIEW_PASSWORD=
|
|
34
36
|
TRADINGVIEW_WATCHLIST=SPY,QQQ,BTCUSD,NQ1!
|
|
37
|
+
TRADINGVIEW_CONNECTOR_MODE=watchlist
|
|
38
|
+
TRADINGVIEW_MCP_ENABLED=false
|
|
39
|
+
TRADINGVIEW_MCP_TRANSPORT=stdio
|
|
40
|
+
TRADINGVIEW_MCP_COMMAND=
|
|
41
|
+
TRADINGVIEW_MCP_ARGS=
|
|
42
|
+
TRADINGVIEW_MCP_URL=
|
|
35
43
|
|
|
36
44
|
# Robinhood and Groww
|
|
37
45
|
ROBINHOOD_USERNAME=
|
package/README.md
CHANGED
|
@@ -36,8 +36,10 @@ During onboarding you can choose:
|
|
|
36
36
|
- Your agent runtime profile
|
|
37
37
|
- Your primary market rail
|
|
38
38
|
- Extra rails like `polymarket`, `tradingview`, `robinhood`, or `groww`
|
|
39
|
+
- Your dashboard surface and operator messaging channels
|
|
39
40
|
- Optional data integrations like `apify`, `rss`, `reddit`, `twitter`, `truthsocial`, and `tiktok`
|
|
40
41
|
- Your package manager for local web workflows
|
|
42
|
+
- TradingView in watchlist mode or via an optional local MCP connector
|
|
41
43
|
|
|
42
44
|
### CLI Commands
|
|
43
45
|
|
|
@@ -56,7 +58,7 @@ opentradex web # launch the Next.js dashboard
|
|
|
56
58
|
|---|---|
|
|
57
59
|
| Kalshi | Best live execution path |
|
|
58
60
|
| Polymarket | Public market discovery and comparison |
|
|
59
|
-
| TradingView | Watchlist
|
|
61
|
+
| TradingView | Watchlist context or optional local MCP-backed chart context |
|
|
60
62
|
| Robinhood | Broker profile placeholder |
|
|
61
63
|
| Groww | Broker profile placeholder |
|
|
62
64
|
|
|
Binary file
|
package/main.py
CHANGED
|
@@ -42,6 +42,11 @@ def build_runtime_context() -> str:
|
|
|
42
42
|
primary_market = os.getenv("OPENTRADEX_PRIMARY_MARKET", "kalshi")
|
|
43
43
|
enabled_markets = parse_csv_env("OPENTRADEX_ENABLED_MARKETS", primary_market)
|
|
44
44
|
integrations = parse_csv_env("OPENTRADEX_ENABLED_INTEGRATIONS", "apify,rss")
|
|
45
|
+
dashboard_surface = os.getenv("OPENTRADEX_DASHBOARD_SURFACE", "chat")
|
|
46
|
+
channels = parse_csv_env("OPENTRADEX_CHANNELS", "command,markets,feeds,risk,execution")
|
|
47
|
+
tradingview_connector_mode = os.getenv("TRADINGVIEW_CONNECTOR_MODE", "watchlist").strip().lower()
|
|
48
|
+
tradingview_mcp_enabled = os.getenv("TRADINGVIEW_MCP_ENABLED", "false").strip().lower() == "true"
|
|
49
|
+
tradingview_mcp_transport = os.getenv("TRADINGVIEW_MCP_TRANSPORT", "stdio").strip().lower()
|
|
45
50
|
|
|
46
51
|
lines = [
|
|
47
52
|
"Workspace profile:",
|
|
@@ -49,6 +54,8 @@ def build_runtime_context() -> str:
|
|
|
49
54
|
f"- Primary market: {primary_market}",
|
|
50
55
|
f"- Enabled market rails: {', '.join(enabled_markets)}",
|
|
51
56
|
f"- Enabled data integrations: {', '.join(integrations)}",
|
|
57
|
+
f"- Dashboard surface: {dashboard_surface}",
|
|
58
|
+
f"- Operator channels: {', '.join(channels)}",
|
|
52
59
|
"- Use only the rails enabled in this workspace.",
|
|
53
60
|
"- Live execution is currently routed through Kalshi only. Other rails are for discovery, research, and cross-market context unless explicitly extended.",
|
|
54
61
|
"",
|
|
@@ -76,13 +83,23 @@ def build_runtime_context() -> str:
|
|
|
76
83
|
)
|
|
77
84
|
|
|
78
85
|
if "tradingview" in enabled_markets:
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
+
if tradingview_connector_mode == "mcp" and tradingview_mcp_enabled:
|
|
87
|
+
lines.extend(
|
|
88
|
+
[
|
|
89
|
+
"- TradingView MCP rail:",
|
|
90
|
+
f" Transport: {tradingview_mcp_transport}",
|
|
91
|
+
" If the local Claude session has the TradingView MCP server available, use it for richer chart and symbol context.",
|
|
92
|
+
" Fall back to `TRADINGVIEW_WATCHLIST` if the MCP server is unavailable or incomplete.",
|
|
93
|
+
]
|
|
94
|
+
)
|
|
95
|
+
else:
|
|
96
|
+
lines.extend(
|
|
97
|
+
[
|
|
98
|
+
"- TradingView watchlist rail:",
|
|
99
|
+
" Read `TRADINGVIEW_WATCHLIST` from `.env` and use it to focus macro/equity/crypto research.",
|
|
100
|
+
" Treat this as a watchlist/context source unless a dedicated adapter is added.",
|
|
101
|
+
]
|
|
102
|
+
)
|
|
86
103
|
|
|
87
104
|
if "robinhood" in enabled_markets:
|
|
88
105
|
lines.append("- Robinhood is enabled as a broker profile placeholder. Use it for planning and watchlist context unless you add a dedicated execution adapter.")
|
|
@@ -98,9 +115,21 @@ def build_runtime_context() -> str:
|
|
|
98
115
|
return "\n".join(lines)
|
|
99
116
|
|
|
100
117
|
|
|
118
|
+
def build_harness_protocol() -> str:
|
|
119
|
+
return """Operator harness for this cycle:
|
|
120
|
+
- Scout lane: scan enabled rails fast and surface the best 3-5 candidates.
|
|
121
|
+
- Quant lane: extract the hard numbers, implied price, probability gap, and what actually changed.
|
|
122
|
+
- Risk lane: kill weak, speculative, thin, or unsupported setups early. If the evidence is soft, size down or pass.
|
|
123
|
+
- Executor lane: act only on the best 1-2 ideas, then record the reasoning clearly for the next cycle.
|
|
124
|
+
|
|
125
|
+
Always think in that order: scout -> quantify -> challenge -> execute."""
|
|
126
|
+
|
|
127
|
+
|
|
101
128
|
def build_cycle_prompt() -> str:
|
|
102
129
|
return f"""{build_runtime_context()}
|
|
103
130
|
|
|
131
|
+
{build_harness_protocol()}
|
|
132
|
+
|
|
104
133
|
Read SOUL.md for your identity and strategy principles.
|
|
105
134
|
Read data/strategy_notes.md for lessons from past sessions.
|
|
106
135
|
Check data/user_rationales.json for any pending user theses to research.
|
|
@@ -155,6 +184,8 @@ EXECUTION DISCIPLINE:
|
|
|
155
184
|
def build_rationale_prompt(rationale: str) -> str:
|
|
156
185
|
return f"""{build_runtime_context()}
|
|
157
186
|
|
|
187
|
+
{build_harness_protocol()}
|
|
188
|
+
|
|
158
189
|
Read SOUL.md for your identity and strategy principles.
|
|
159
190
|
|
|
160
191
|
A user has submitted this thesis for you to research and potentially trade on:
|
package/package.json
CHANGED
package/src/catalog.mjs
CHANGED
|
@@ -2,7 +2,7 @@ export const PACKAGE_MANAGER_OPTIONS = [
|
|
|
2
2
|
{
|
|
3
3
|
id: "npm",
|
|
4
4
|
label: "npm",
|
|
5
|
-
description: "Default Node workflow for installs and the
|
|
5
|
+
description: "Default Node workflow for installs, scripts, and the local harness.",
|
|
6
6
|
installHint: "npm install -g opentradex@latest",
|
|
7
7
|
},
|
|
8
8
|
{
|
|
@@ -17,7 +17,7 @@ export const RUNTIME_OPTIONS = [
|
|
|
17
17
|
{
|
|
18
18
|
id: "claude-code",
|
|
19
19
|
label: "Claude Code",
|
|
20
|
-
description: "Production-ready local tool-using runtime.",
|
|
20
|
+
description: "Production-ready local tool-using runtime for the current harness.",
|
|
21
21
|
support: "working",
|
|
22
22
|
},
|
|
23
23
|
{
|
|
@@ -56,13 +56,13 @@ export const MARKET_OPTIONS = [
|
|
|
56
56
|
{
|
|
57
57
|
id: "robinhood",
|
|
58
58
|
label: "Robinhood",
|
|
59
|
-
description: "US broker profile placeholder.",
|
|
59
|
+
description: "US broker profile placeholder for future adapter work.",
|
|
60
60
|
support: "profile",
|
|
61
61
|
},
|
|
62
62
|
{
|
|
63
63
|
id: "groww",
|
|
64
64
|
label: "Groww",
|
|
65
|
-
description: "India-focused broker profile placeholder.",
|
|
65
|
+
description: "India-focused broker profile placeholder for future adapter work.",
|
|
66
66
|
support: "profile",
|
|
67
67
|
},
|
|
68
68
|
];
|
|
@@ -100,6 +100,78 @@ export const INTEGRATION_OPTIONS = [
|
|
|
100
100
|
},
|
|
101
101
|
];
|
|
102
102
|
|
|
103
|
+
export const CHANNEL_OPTIONS = [
|
|
104
|
+
{
|
|
105
|
+
id: "command",
|
|
106
|
+
label: "Command",
|
|
107
|
+
description: "Primary operator chat lane for direct prompts and mission launches.",
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
id: "markets",
|
|
111
|
+
label: "Markets",
|
|
112
|
+
description: "Cross-market scanning across Kalshi, Polymarket, and active rails.",
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
id: "feeds",
|
|
116
|
+
label: "Feeds",
|
|
117
|
+
description: "News, social, and alert ingestion for live context.",
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
id: "risk",
|
|
121
|
+
label: "Risk",
|
|
122
|
+
description: "Position review, exposure control, and exit discipline.",
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
id: "execution",
|
|
126
|
+
label: "Execution",
|
|
127
|
+
description: "Trade routing, fills, and cycle outcomes.",
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
id: "tradingview",
|
|
131
|
+
label: "TradingView",
|
|
132
|
+
description: "Watchlist and chart-context lane for symbols and macro instruments.",
|
|
133
|
+
},
|
|
134
|
+
];
|
|
135
|
+
|
|
136
|
+
export const DASHBOARD_SURFACE_OPTIONS = [
|
|
137
|
+
{
|
|
138
|
+
id: "chat",
|
|
139
|
+
label: "Chat cockpit",
|
|
140
|
+
description: "Channel-based operator chat inside the local dashboard.",
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
id: "stream",
|
|
144
|
+
label: "Stream log",
|
|
145
|
+
description: "Lean terminal-style stream without the full chat cockpit framing.",
|
|
146
|
+
},
|
|
147
|
+
];
|
|
148
|
+
|
|
149
|
+
export const TRADINGVIEW_CONNECTOR_OPTIONS = [
|
|
150
|
+
{
|
|
151
|
+
id: "watchlist",
|
|
152
|
+
label: "Watchlist only",
|
|
153
|
+
description: "Use TradingView symbols as context without an MCP connector.",
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
id: "mcp",
|
|
157
|
+
label: "TradingView MCP",
|
|
158
|
+
description: "Route TradingView context through your local MCP server when available.",
|
|
159
|
+
},
|
|
160
|
+
];
|
|
161
|
+
|
|
162
|
+
export const MCP_TRANSPORT_OPTIONS = [
|
|
163
|
+
{
|
|
164
|
+
id: "stdio",
|
|
165
|
+
label: "stdio",
|
|
166
|
+
description: "Spawn a local MCP command such as a node, bun, or python process.",
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
id: "http",
|
|
170
|
+
label: "http",
|
|
171
|
+
description: "Connect to an MCP endpoint exposed over HTTP.",
|
|
172
|
+
},
|
|
173
|
+
];
|
|
174
|
+
|
|
103
175
|
export function getOptionById(options, id, fallbackId) {
|
|
104
176
|
const fallback = options.find((item) => item.id === fallbackId) || options[0];
|
|
105
177
|
if (!id) {
|
package/src/cli.mjs
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
import process from "node:process";
|
|
2
|
+
import {
|
|
3
|
+
CHANNEL_OPTIONS,
|
|
4
|
+
DASHBOARD_SURFACE_OPTIONS,
|
|
5
|
+
INTEGRATION_OPTIONS,
|
|
6
|
+
MARKET_OPTIONS,
|
|
7
|
+
PACKAGE_MANAGER_OPTIONS,
|
|
8
|
+
RUNTIME_OPTIONS,
|
|
9
|
+
labelsForIds,
|
|
10
|
+
} from "./catalog.mjs";
|
|
2
11
|
import {
|
|
3
12
|
collectDoctor,
|
|
4
13
|
formatDoctorReport,
|
|
@@ -22,25 +31,32 @@ export async function runCli(argv = process.argv.slice(2)) {
|
|
|
22
31
|
return;
|
|
23
32
|
case "onboard": {
|
|
24
33
|
const result = await onboard(options);
|
|
34
|
+
if (!result) {
|
|
35
|
+
printLines(["OpenTradex onboarding cancelled."]);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
25
39
|
printLines([
|
|
26
|
-
"
|
|
40
|
+
"OpenTradex profile written.",
|
|
27
41
|
"Our implementation. Your strategy.",
|
|
28
42
|
"",
|
|
29
|
-
"
|
|
30
|
-
`workspace: ${result.workspace}`,
|
|
31
|
-
`mode: ${result.mode}`,
|
|
32
|
-
`runtime: ${result.profile.runtime}`,
|
|
33
|
-
`primary market: ${result.profile.primaryMarket}`,
|
|
34
|
-
`market rails: ${result.profile.enabledMarkets.join(", ")}`,
|
|
35
|
-
`integrations: ${result.profile.integrations.join(", ")}`,
|
|
36
|
-
`
|
|
43
|
+
"Local harness configured:",
|
|
44
|
+
` workspace: ${result.workspace}`,
|
|
45
|
+
` mode: ${result.mode}`,
|
|
46
|
+
` runtime: ${labelsForIds(RUNTIME_OPTIONS, [result.profile.runtime]).join(", ")}`,
|
|
47
|
+
` primary market: ${labelsForIds(MARKET_OPTIONS, [result.profile.primaryMarket]).join(", ")}`,
|
|
48
|
+
` market rails: ${labelsForIds(MARKET_OPTIONS, result.profile.enabledMarkets).join(", ") || "none"}`,
|
|
49
|
+
` integrations: ${labelsForIds(INTEGRATION_OPTIONS, result.profile.integrations).join(", ") || "none"}`,
|
|
50
|
+
` dashboard: ${labelsForIds(DASHBOARD_SURFACE_OPTIONS, [result.profile.dashboardSurface]).join(", ")}`,
|
|
51
|
+
` channels: ${labelsForIds(CHANNEL_OPTIONS, result.profile.channels).join(", ") || "none"}`,
|
|
52
|
+
` package manager: ${labelsForIds(PACKAGE_MANAGER_OPTIONS, [result.profile.packageManager]).join(", ")}`,
|
|
37
53
|
...(result.notes.length > 0 ? ["", "Notes:", ...result.notes.map((note) => ` - ${note}`)] : []),
|
|
38
54
|
"",
|
|
39
|
-
"Next
|
|
40
|
-
" opentradex doctor",
|
|
41
|
-
" opentradex
|
|
42
|
-
" opentradex
|
|
43
|
-
" opentradex providers",
|
|
55
|
+
"Next:",
|
|
56
|
+
" 1. opentradex doctor",
|
|
57
|
+
" 2. opentradex web",
|
|
58
|
+
" 3. opentradex start",
|
|
59
|
+
" 4. opentradex providers",
|
|
44
60
|
]);
|
|
45
61
|
return;
|
|
46
62
|
}
|
|
@@ -71,6 +87,8 @@ export async function runCli(argv = process.argv.slice(2)) {
|
|
|
71
87
|
|
|
72
88
|
function parseArgs(argv) {
|
|
73
89
|
const options = {};
|
|
90
|
+
const booleanFlags = new Set(["skip-install", "yes", "install", "force", "paper", "live"]);
|
|
91
|
+
const dashValueKeys = new Set(["tradingview-mcp-args"]);
|
|
74
92
|
|
|
75
93
|
for (let index = 0; index < argv.length; index += 1) {
|
|
76
94
|
const token = argv[index];
|
|
@@ -89,12 +107,18 @@ function parseArgs(argv) {
|
|
|
89
107
|
continue;
|
|
90
108
|
}
|
|
91
109
|
|
|
92
|
-
if (
|
|
110
|
+
if (booleanFlags.has(key)) {
|
|
93
111
|
options[toCamel(key)] = true;
|
|
94
112
|
continue;
|
|
95
113
|
}
|
|
96
114
|
|
|
97
115
|
const next = argv[index + 1];
|
|
116
|
+
if (dashValueKeys.has(key) && next) {
|
|
117
|
+
options[toCamel(key)] = next;
|
|
118
|
+
index += 1;
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
|
|
98
122
|
if (!next || next.startsWith("--")) {
|
|
99
123
|
options[toCamel(key)] = true;
|
|
100
124
|
continue;
|
|
@@ -115,10 +139,11 @@ function printHelp() {
|
|
|
115
139
|
printLines([
|
|
116
140
|
"opentradex",
|
|
117
141
|
"",
|
|
118
|
-
"
|
|
142
|
+
"OpenTradex CLI",
|
|
143
|
+
"Our implementation. Your strategy.",
|
|
119
144
|
"",
|
|
120
145
|
"Commands:",
|
|
121
|
-
" opentradex onboard [--workspace <dir>] [--paper|--live] [--llm <id>] [--primary-market <id>]",
|
|
146
|
+
" opentradex onboard [--workspace <dir>] [--paper|--live] [--llm <id>] [--primary-market <id>] [--dashboard-surface <id>]",
|
|
122
147
|
" opentradex doctor [--workspace <dir>]",
|
|
123
148
|
" opentradex providers",
|
|
124
149
|
" opentradex start [--workspace <dir>] [--interval <seconds>] [--rationale <text>]",
|
|
@@ -129,7 +154,8 @@ function printHelp() {
|
|
|
129
154
|
"Examples:",
|
|
130
155
|
" npm install -g opentradex@latest",
|
|
131
156
|
" bunx opentradex@latest onboard",
|
|
132
|
-
" opentradex
|
|
157
|
+
" opentradex web",
|
|
158
|
+
" opentradex onboard --llm claude-code --primary-market kalshi --markets polymarket,tradingview --dashboard-surface chat",
|
|
133
159
|
" opentradex doctor",
|
|
134
160
|
" opentradex providers",
|
|
135
161
|
" opentradex cycle --rationale \"Tariffs will escalate next week\"",
|