The same architecture our desk runs — taught so you can build it yourself, on a paper (practice) account. The lesson isn't the automation. It's the risk gate that turns a bot from gambling into a system.
Every signal must pass the gate before it ever reaches the broker. No gate = gambling.
Start with a broker that gives a free paper account + an API — Alpaca is the cleanest for learning (stocks + crypto, paper money, no funding needed). Generate your Paper API keys (Key ID starts with PK).
https://paper-api.alpaca.marketsA signal is just "buy/sell this symbol, here are the levels." Two honest options:
Either way, the signal is a small JSON message:
{ "symbol": "BTC/USD", "action": "buy", "entry": 64000, "sl": 61000, "tp": 73000, "qty": 0.01 }
A tiny web endpoint (Vercel, Cloudflare, AWS Lambda — all have free tiers) receives the signal as an HTTP POST. Protect it with a shared secret in the payload so randoms can't fire it.
// pseudo-code — your endpoint if (body.secret !== process.env.MY_SECRET) return reject(401); const verdict = riskGate(body); // step 4 if (verdict.go) placeOrder(body); // step 5
This is what separates a system from a gamble. Before any order, compute reward-to-risk (R:R) and refuse anything below your floor:
function riskGate(s){ const risk = Math.abs(s.entry - s.sl); // distance to your stop const reward = Math.abs(s.tp - s.entry); // distance to your target const rr = reward / risk; const floor = s.profile === "day" ? 1.5 : 2.0; // your minimum return { go: rr >= floor, rr }; // below floor → NO trade }
A trade with no defined stop has no risk gate possible — so it doesn't trade. That single rule eliminates most blow-ups. (Our desk runs a stricter version of exactly this on every signal.)
If the gate says GO, place a market order on the paper endpoint. Keys come from your environment variables — never hard-coded.
await fetch("https://paper-api.alpaca.markets/v2/orders", { method: "POST", headers: { "APCA-API-KEY-ID": process.env.ALPACA_KEY, "APCA-API-SECRET-KEY": process.env.ALPACA_SECRET }, body: JSON.stringify({ symbol, qty, side, type:"market", time_in_force: symbol.includes("/") ? "gtc" : "day" }) // crypto (BTC/USD) needs "gtc"; stocks use "day" });
Fire test signals — a good R:R (GO) and a bad one (should be refused). Confirm orders appear in your paper dashboard. Then check positions and P/L. Run it on paper for weeks before you ever think about real money.
Crypto orders on most brokers can't carry an attached stop, so nothing auto-closes a losing trade unless you build it. A monitor loops over your open positions and closes any that hit the stop or target your gate defined. Without this, your "stops" are just notes. Build it before you trust the system.