opentradex 0.1.3 → 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 +1 -1
- 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
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import type { WorkspaceSummary } from "@/lib/types";
|
|
4
|
+
|
|
5
|
+
const PROJECT_ROOT = path.join(process.cwd(), "..");
|
|
6
|
+
const ENV_PATH = path.join(PROJECT_ROOT, ".env");
|
|
7
|
+
const PROFILE_PATH = path.join(PROJECT_ROOT, "opentradex.config.json");
|
|
8
|
+
|
|
9
|
+
const DEFAULT_CHANNELS = ["command", "markets", "feeds", "risk", "execution"];
|
|
10
|
+
const DEFAULT_WATCHLIST = ["SPY", "QQQ", "BTCUSD", "NQ1!"];
|
|
11
|
+
|
|
12
|
+
function parseEnv(text: string) {
|
|
13
|
+
const values: Record<string, string> = {};
|
|
14
|
+
for (const rawLine of text.split(/\r?\n/)) {
|
|
15
|
+
const line = rawLine.trim();
|
|
16
|
+
if (!line || line.startsWith("#")) {
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
const separatorIndex = line.indexOf("=");
|
|
20
|
+
if (separatorIndex === -1) {
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
const key = line.slice(0, separatorIndex).trim();
|
|
24
|
+
const value = line.slice(separatorIndex + 1).trim();
|
|
25
|
+
values[key] = value.replace(/^"(.*)"$/, "$1");
|
|
26
|
+
}
|
|
27
|
+
return values;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function readJson(filePath: string) {
|
|
31
|
+
try {
|
|
32
|
+
return JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
33
|
+
} catch {
|
|
34
|
+
return {};
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function parseCsv(value: unknown, fallback: string[] = []) {
|
|
39
|
+
if (!value) {
|
|
40
|
+
return fallback;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return String(value)
|
|
44
|
+
.split(",")
|
|
45
|
+
.map((item) => item.trim())
|
|
46
|
+
.filter(Boolean);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function readWorkspaceSummary(): WorkspaceSummary | null {
|
|
50
|
+
const hasEnv = fs.existsSync(ENV_PATH);
|
|
51
|
+
const hasProfile = fs.existsSync(PROFILE_PATH);
|
|
52
|
+
|
|
53
|
+
if (!hasEnv && !hasProfile) {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const env = hasEnv ? parseEnv(fs.readFileSync(ENV_PATH, "utf8")) : {};
|
|
58
|
+
const profile = hasProfile ? readJson(PROFILE_PATH) : {};
|
|
59
|
+
|
|
60
|
+
const enabledMarkets = parseCsv(
|
|
61
|
+
env.OPENTRADEX_ENABLED_MARKETS || profile.enabledMarkets,
|
|
62
|
+
[env.OPENTRADEX_PRIMARY_MARKET || profile.primaryMarket || "kalshi"]
|
|
63
|
+
);
|
|
64
|
+
const integrations = parseCsv(
|
|
65
|
+
env.OPENTRADEX_ENABLED_INTEGRATIONS || profile.integrations,
|
|
66
|
+
["apify", "rss"]
|
|
67
|
+
);
|
|
68
|
+
const channels = parseCsv(
|
|
69
|
+
env.OPENTRADEX_CHANNELS || profile.channels,
|
|
70
|
+
enabledMarkets.includes("tradingview")
|
|
71
|
+
? [...DEFAULT_CHANNELS, "tradingview"]
|
|
72
|
+
: DEFAULT_CHANNELS
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
const tradingviewEnabled = enabledMarkets.includes("tradingview");
|
|
76
|
+
const connectorMode =
|
|
77
|
+
String(env.TRADINGVIEW_CONNECTOR_MODE || profile.tradingviewConnectorMode || "watchlist").toLowerCase() === "mcp"
|
|
78
|
+
? "mcp"
|
|
79
|
+
: "watchlist";
|
|
80
|
+
const mcpEnabled =
|
|
81
|
+
String(env.TRADINGVIEW_MCP_ENABLED || profile.tradingviewMcpEnabled || "false").toLowerCase() === "true";
|
|
82
|
+
const transport =
|
|
83
|
+
String(env.TRADINGVIEW_MCP_TRANSPORT || profile.tradingviewMcpTransport || "stdio").toLowerCase() === "http"
|
|
84
|
+
? "http"
|
|
85
|
+
: "stdio";
|
|
86
|
+
const command = env.TRADINGVIEW_MCP_COMMAND || "";
|
|
87
|
+
const args = env.TRADINGVIEW_MCP_ARGS || "";
|
|
88
|
+
const url = env.TRADINGVIEW_MCP_URL || "";
|
|
89
|
+
const configured = connectorMode === "mcp" && mcpEnabled
|
|
90
|
+
? transport === "http"
|
|
91
|
+
? Boolean(url)
|
|
92
|
+
: Boolean(command)
|
|
93
|
+
: false;
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
isDemo: false,
|
|
97
|
+
runtime: String(env.OPENTRADEX_RUNTIME || profile.runtime || "claude-code"),
|
|
98
|
+
packageManager: String(env.OPENTRADEX_PACKAGE_MANAGER || profile.packageManager || "npm"),
|
|
99
|
+
mode: String(env.OPENTRADEX_EXECUTION_MODE || profile.mode || "paper"),
|
|
100
|
+
primaryMarket: String(env.OPENTRADEX_PRIMARY_MARKET || profile.primaryMarket || "kalshi"),
|
|
101
|
+
enabledMarkets,
|
|
102
|
+
integrations,
|
|
103
|
+
dashboardSurface: String(env.OPENTRADEX_DASHBOARD_SURFACE || profile.dashboardSurface || "chat"),
|
|
104
|
+
channels,
|
|
105
|
+
tradingview: {
|
|
106
|
+
enabled: tradingviewEnabled,
|
|
107
|
+
watchlist: parseCsv(env.TRADINGVIEW_WATCHLIST, DEFAULT_WATCHLIST),
|
|
108
|
+
connectorMode,
|
|
109
|
+
mcpEnabled,
|
|
110
|
+
transport,
|
|
111
|
+
command,
|
|
112
|
+
args,
|
|
113
|
+
url,
|
|
114
|
+
configured,
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
}
|