Shared chat
Electron أم Egui لتطبيق التداول
This is a shared TryAI chat. Sign in to start your own conversation.
Sign in to TryAIShared chat
This is a shared TryAI chat. Sign in to start your own conversation.
Sign in to TryAIوالسبب الحاسم ليس الـ UI (طالما متطابق) بل الشارتات تحديداً، لأنها قلب أي منصة تداول مدفوعة:
مع Electron ستجد حلولاً جاهزة لكل شيء:
electron-updater) — ضروري جداً لتطبيق اشتراكاتنعم، استهلاك ذاكرة أعلى وحجم أكبر (~150MB+)، لكن المتداولون يشغّلون أصلاً MT5 وNinjaTrader وChrome بعشرات التابات. لن يلغي أحد اشتراكه بسبب 300MB رام، لكنه سيلغيه بسبب شارت ضعيف.
بما أنك أصلاً تخطط لمنطق Rust:
قراري لو كنت مكانك: Electron (أو Tauri إن أردت Rust بعمق) + TradingView Lightweight Charts، وأطلق المنتج بسرعة. egui خيار ممتاز تقنياً لكنه سيؤخر إطلاقك أشهراً بجودة شارت أقل — وهذا خسارة مباشرة لمنتج اشتراك شهري.
There are 4 main approaches — here they are ranked for your use case (a trading terminal):
Rust compiles to a .node native module that you require() directly in Electron's main process. Zero IPC overhead, direct function calls.
Ship a standalone Rust binary alongside your app. Electron spawns it and communicates via stdin/stdout (JSON), WebSocket, or gRPC.
Rust compiled to WASM, runs in the renderer.
Manual C ABI bindings. Fragile, unmaintained libraries — avoid.
Hybrid: use a Rust sidecar for the trading engine (market data, order execution, strategy logic) + optionally napi-rs for small hot-path utilities. The sidecar keeps your money-handling logic isolated and independently testable — critical for a paid product.
127.0.0.1 only and add a random auth token passed via env var on spawn — otherwise any local app could connect to your engine.{"v": 1, "type": "tick", ...}) so auto-updated Electron frontends stay compatible with older engine binaries.win-x64, mac-arm64, mac-x64, linux-x64 in GitHub Actions and inject it into the electron-builder step.Bottom line: sidecar for the engine, napi-rs later if you need microsecond-level calls. This keeps your paid product stable — the app UI never dies because of an engine bug.
cargo new trading-enginecd trading-enginecargo add tokio --features fullcargo add serde serde_json --features serde/derivecargo add tokio-tungstenite # if using WebSocket transport// src/main.rsuse tokio::net::TcpListener;
#[derive(serde::Serialize)]struct Tick { symbol: String, price: f64, ts: i64 }
#[tokio::main]async fn main() { // Bind to localhost only — never 0.0.0.0 let listener = TcpListener::bind("127.0.0.1:8765").await.unwrap(); while let Ok((stream, _)) = listener.accept().await { tokio::spawn(handle_connection(stream)); }}
async fn handle_connection(stream: tokio::net::TcpStream) { let ws = tokio_tungstenite::accept_async(stream).await.unwrap(); // stream market data / handle order commands here}// main.tsimport { spawn, ChildProcess } from "child_process";import path from "path";import { app } from "electron";
let engine: ChildProcess;
function startEngine() { const bin = app.isPackaged ? path.join(process.resourcesPath, "bin", "trading-engine") : path.join(__dirname, "../trading-engine/target/release/trading-engine");
engine = spawn(bin, [], { stdio: ["pipe", "pipe", "pipe"] });
engine.on("exit", (code) => { console.error(`engine died (${code}), restarting...`); setTimeout(startEngine, 1000); // auto-restart });}
app.whenReady().then(startEngine);app.on("before-quit", () => engine?.kill());// rendererconst ws = new WebSocket("ws://127.0.0.1:8765");ws.onmessage = (e) => { const tick = JSON.parse(e.data); candlestickSeries.update(tick); // feed TradingView Lightweight Charts directly};# electron-builder.ymlextraResources: - from: "trading-engine/target/release/trading-engine${/*}" to: "bin/"npm install -g @napi-rs/clinapi new rust-utils// lib.rsuse napi_derive::napi;
#[napi]pub fn calculate_ema(prices: Vec<f64>, period: u32) -> Vec<f64> { let k = 2.0 / (period as f64 + 1.0); let mut out = Vec::with_capacity(prices.len()); let mut ema = prices[0]; for p in &prices { ema = p * k + ema * (1.0 - k); out.push(ema); } out}// In Electron main — typed bindings are auto-generatedimport { calculateEma } from "./rust-utils";const ema = calculateEma(closes, 21);