← Dashboard

Help & option reference

Every control in the application, what it does, and how the pieces fit together.


Reading balances…
CLOSED
closed
Orientation. This is a server application, not a desktop .exe: a Python/FastAPI process serving web pages. There is no Node.js and no build step. Paper trading is the default; live Angel One orders stay locked until every gate in Settings is green. No software can guarantee a requested profit percentage — targets are goals, not promises.

1. How a campaign flows

StepWhat happens
CreateYou set budget, target, stop loss, price band, sector, automation and execution mode. Status becomes draft.
Research / StartThe engine filters a universe by price band and sector, then scores each candidate (with AI if a provider key is set). Status becomes researching, and every candidate is saved as SELECTED or REJECTED with a reason.
Plan reviewIn Approval mode status becomes ready and waits for you. In full/semi auto it buys immediately.
ExecuteRisk checks run per position (cash, position cap, trades/day, daily loss, confidence). Passing checks create positions in pending, which become open on fill.
MonitorThe background loop reconciles order status, enforces the intraday exit window, and checks targets and stop losses as prices update.
ExitPositions close on target, stop loss, trailing stop, campaign target, daily loss limit, intraday forced exit, or your manual close. Status becomes closed with gross, estimated charges and net P&L.

2. Dashboard — create campaign

OptionWhat it does
NameLabel for the campaign. Campaigns are fully isolated: separate budget, rules, positions and history.
Budget ₹Maximum this campaign may spend. Remaining cash is tracked per campaign.
Profit Target %Goal as a percentage of budget. Combined with Target Mode it decides when the whole campaign exits.
Stop Loss %Per-position exit level below entry. 3% on a ₹100 entry exits near ₹97.
Trailing Stop %Raises the stop as price makes new highs. 0 disables. At 2%, ₹100 → ₹120 lifts the stop to ≈₹117.60.
Min AI Confidence %Only candidates rated at or above this may be bought. Higher means fewer, stronger positions.
Max PositionsCaps simultaneous open positions. The budget is split across the planned positions.
Daily Loss Limit ₹Circuit breaker: once realised losses reach it, buying stops and open positions are closed.
Price CategoryShare-price band filter (below ₹20, ₹20–50, ₹50–100, ₹100–250, ₹250–500, ₹500–1,000, ₹1,000+, or Low/Mid/High/All).
SectorAll, banking, IT, energy or telecom.
Trade TypeDelivery (held overnight) or Intraday (squared off the same session, subject to the cutoff times).
Target ModeWhole Campaign Target (exit everything at the goal) or Each Stock Target (apply the target per position).
AutomationResearch Only · Approval Required · Semi Auto · Full Auto.
ExecutionPaper Trading (simulated fills) or Angel One Live (real orders, gated).
Campaign Chat InstructionNatural-language brief. Parsed for budget, target %, stop loss %, confidence %, max positions, price band, sector and intraday/delivery.

3. Dashboard panels

PanelMeaning
Market statusIST session state (OPEN 09:15–15:30 on trading days) and the phase: entries_allowed before the intraday cutoff, manage_only after it, then exit_window for the forced square-off.
Headline statsCampaign count · positions open/pending/closing · realised net P&L (after estimated charges) · unrealised P&L on open positions · whether live trading is LOCKED or UNLOCKED.
CampaignsBudget, remaining cash, target, trade type, automation level, status. Open to control the campaign.
Live tradesPositions currently open, waiting for a fill, or mid-exit.
Recent ordersRaw order log with broker name and broker order id, so you can confirm what was really sent.
Trade historyClosed trades with net P&L, exit reason and whether the trade came from a campaign or was manual.

4. Campaign page

ControlWhat it does
Research / StartRuns the AI scan and produces the plan. Blocked while the campaign is paused.
Approve & Execute PlanShown when a plan is ready; places the approved positions after risk checks.
Pause / ResumeStops new automated actions, then restores monitoring. Existing positions stay visible either way.
Stop / Enable Auto BuyBlocks or allows new positions. Stopping it keeps current positions monitored.
Stop / Enable Auto SellDisables or restores automatic target and stop-loss exits. With auto-sell off you must close positions manually.
Close All PositionsSubmits exits for every open position and completes the campaign.
Campaign chatChange rules or issue commands in plain English (pause, resume, stop buy, close all, research, "target 7%", "minimum 85% confidence", "max 3 companies"). Everything is stored on the timeline.
Active rulesThe live rule set currently applied to this campaign.
AI research planEvery scored candidate with price, confidence, rating, SELECTED/REJECTED and the reason. The best place to judge AI stock-picking quality.
Live / pending tradesEntry, last price, target, stop. Paper Price Tick simulates a price move — crossing target or stop fires the exit rules. Close Manually exits now.
Trade historyGross P&L, estimated charges, net P&L and exit reason per closed trade.
Campaign timelineAudit trail: scans, selections, rejections, risk blocks, submissions, fills, closures.

5. Status glossary

StatusMeaning
draftCampaign created, nothing researched yet.
researchingA scan is in progress.
readyPlan prepared and waiting for your approval.
waitingNo candidate passed the current rules.
activePositions are being monitored.
pausedNew automated actions suspended.
completedEverything is closed and the campaign is flat.
stoppedHalted by the daily loss limit.
failedThe last run raised an error; see the timeline.
pending → open → closing → closedTrade lifecycle: submitted, filled, exit submitted, exited. rejected means the broker or a risk check refused it.

6. Settings reference

SettingPurpose
Deployment & network — Where this app is running, what the outside world sees, and which URL and IP are registered with the broker. The panel above detects these automatically; these fields are the ones you want saved.
PUBLIC_BASE_URLThe https:// URL this app is served from, e.g. https://trade.example.com. Leave blank and the app derives one from whatever address you are browsing on.
ANGEL_STATIC_IPThe public IPv4 you whitelisted in the SmartAPI portal. Saved here so the app can warn you the moment your IP drifts, which would silently start rejecting live orders.
ANGEL_REDIRECT_URLThe redirect URL registered against your API key in the portal. Recorded here so the portal value and this deployment stay in sync.
PUBLIC_IP_LOOKUP_URLKeyless HTTPS endpoint used to discover the IP the internet sees. Clear it if you would rather not call a third party; detection then reports the IP as unverified.
Safety & realism — The master kill switch and how honestly paper fills are modelled.
TRADING_ENABLEDMaster switch for OPENING positions. Turning this off blocks new buys but still allows exits, so a halt can never trap you in a position. Persisted, so it survives a restart.
PAPER_SLIPPAGE_BPSFills are moved against you by this many basis points (1 bp = 0.01%). 5 is a realistic default for liquid NSE names. Set 0 for frictionless, optimistic fills.
AI / Research — Which AI provider rates stocks, and how many calls it may make.
LLM_PROVIDERWhich AI provider rates stocks. "auto" uses the first provider that has a key saved.
LLM_RESEARCH_ENABLEDWhen on, the AI rates candidates and overrides the built-in placeholder scores. When off, only the offline model is used.
GEMINI_API_KEYGoogle AI Studio key (starts with AIza). Free tier available at aistudio.google.com/apikey. (secret — masked in the UI)
GEMINI_MODELe.g. gemini-2.5-flash (fast/cheap) or gemini-2.5-pro (stronger).
OPENAI_API_KEYAlternative to Gemini. Starts with sk-. (secret — masked in the UI)
OPENAI_MODELe.g. gpt-4o-mini.
ANTHROPIC_API_KEYAlternative to Gemini/OpenAI. Starts with sk-ant-. (secret — masked in the UI)
ANTHROPIC_MODELe.g. claude-3-5-sonnet-latest.
LLM_MAX_CANDIDATESCaps how many stocks the AI rates per research run. This is the only real driver of AI cost: each call is a fraction of a paisa, so the cap is about speed and rate limits more than money. See AI usage & cost below.
USD_INR_RATEUsed to show estimated AI spend in rupees. Set it to your card rate so the cost panel matches your statement.
TRADINGAGENTS_ENABLEDAdvanced multi-agent research. Requires the tradingagents package plus its own keys. Falls back to the simple AI rating on error.
Price feed & market data — Where live prices come from, and the historical window the Fetch fresh data button downloads. Without a feed the exit rules can never fire on their own; without real history a backtest cannot tell you anything.
QUOTE_SOURCEWhere live prices come from. none = manual price ticks only. replay = walk one bar per poll through data/history CSVs (great for watching exit rules fire). angel = real Angel One last-traded prices.
QUOTE_REFRESH_SECONDSHow often to pull fresh prices. This is what lets target, stop-loss and trailing-stop rules fire without manual ticks.
QUOTE_REPLAY_SOURCEWhere replay bars come from. auto prefers data/history/*.csv, then Yahoo Finance, then Alpha Vantage, then synthetic.
HISTORY_REFRESH_DAYSDefault window for the Fetch fresh data buttons on Backtest and here. 400 calendar days is roughly 18 months of trading sessions.
QUOTE_REPLAY_DAYSHow many daily bars to load per symbol for replay mode.
QUOTE_REPLAY_LOOPRestart from the first bar when replay runs out of history.
Notifications — Webhook, Telegram and email alerts for events that matter.
NOTIFY_ENABLEDMaster switch for outbound notifications. Alerts are best-effort and never interrupt trading.
NOTIFY_EVENTSComma-separated keys: position_opened, position_closed, campaign_completed, daily_loss_limit, order_rejected, global_halt, intraday_force_exit, risk_block, warning, error.
NOTIFY_WEBHOOK_URLReceives a JSON POST with app, key, level, title, message and campaign_id. Works with Slack/Discord/ntfy style endpoints.
NOTIFY_TELEGRAM_BOT_TOKENFrom @BotFather. Needs NOTIFY_TELEGRAM_CHAT_ID too. (secret — masked in the UI)
NOTIFY_TELEGRAM_CHAT_IDThe chat, group or channel id to post into.
NOTIFY_SMTP_HOSTe.g. smtp.gmail.com. Needs from/to addresses; set user+password to authenticate.
NOTIFY_SMTP_PORT587 for STARTTLS (default), 465 for implicit TLS, 25 for plain.
NOTIFY_SMTP_USERUsually the full email address.
NOTIFY_SMTP_PASSWORDAn app password, not your normal account password. (secret — masked in the UI)
NOTIFY_EMAIL_FROMSender address.
NOTIFY_EMAIL_TORecipient address.
Angel One broker — Credentials and the safety gates for real-money orders.
DEFAULT_BROKERPaper simulates fills locally. Live routes real orders to Angel One.
ALLOW_LIVE_TRADINGMaster live switch. Also needs the acknowledgement text and a registered static IP.
LIVE_TRADING_ACKMust be exactly: I_UNDERSTAND_LIVE_TRADING_RISK
ANGEL_API_KEYFrom the Angel One SmartAPI developer portal. (secret — masked in the UI)
ANGEL_CLIENT_CODEYour Angel One login ID, e.g. A123456.
ANGEL_PASSWORDYour Angel One trading password (not the app PIN). (secret — masked in the UI)
ANGEL_TOTP_SECRETThe base32 seed behind your 2FA QR code, used to generate the 6-digit code at login. (secret — masked in the UI)
ANGEL_STATIC_IP_REGISTEREDSet true only after registering your server IP with Angel One, otherwise live orders are rejected.
ANGEL_INSTRUMENT_MASTER_URLAngel One symbol/token master used to resolve NSE tradingsymbols.
Risk & runtime — Defaults for new campaigns and the daily session timetable.
DEFAULT_TARGET_PCTPre-filled target for new campaigns. A target is a goal, never a guarantee.
DEFAULT_STOP_LOSS_PCTPre-filled stop loss for new campaigns.
DEFAULT_MAX_DAILY_LOSSPre-filled daily loss cap. When hit, new buying stops and open positions are closed.
DEFAULT_MAX_OPEN_TRADESPre-filled cap on simultaneous positions.
MONITOR_INTERVAL_SECONDSHow often the background loop reconciles orders and checks targets. Minimum 5 seconds.
INTRADAY_STOP_NEW_ENTRIESIST clock time (HH:MM) after which no new intraday position is opened. Default 14:45.
INTRADAY_FORCE_EXITIST clock time (HH:MM) when intraday positions are squared off automatically. Default 15:05.
MARKET_HOLIDAYSComma-separated ISO dates treated as closed, e.g. 2026-01-26,2026-03-04
Dashboard access — Login protection for the web UI.
AUTH_MAX_FAILURESPer source IP, within the lockout window.
AUTH_LOCKOUT_SECONDSHow long a source IP is blocked after too many failed logins.
DASHBOARD_REFRESH_SECONDSHow often the dashboard polls for updated prices and P&L. 0 disables auto-refresh.
AUTH_ENABLEDKeep on for any internet-facing deployment. Turn off only on a trusted local machine.
ADMIN_USERNAMEHTTP Basic username.
ADMIN_PASSWORDChange this from CHANGE_ME_NOW before exposing the app. (secret — masked in the UI)
System — Read-only runtime information.
APP_ENVInformational label reported by /health.
DATABASE_URLSQLite file path. Changing this requires editing .env and restarting, because the engine is bound at startup.

Currently active AI provider: gemini.

7. AI research modes

ModeBehaviour
No key configuredOffline placeholder scores. These are not real signals — use them only to exercise the workflow.
Gemini / OpenAI / Anthropic keyUp to LLM_MAX_CANDIDATES candidates per scan are rated by the model, which returns a rating, a confidence and a one-sentence reason. Results are cached per symbol per day to avoid repeat billing.
TradingAgents enabledThe multi-agent research graph overrides the simple rating. Needs its own package and provider keys; on failure the platform falls back instead of trading on an unvalidated signal.

8. HTTP API

EndpointPurpose
GET /healthUnauthenticated health probe used by Docker.
GET /, GET /campaign/{id}Dashboard and campaign pages.
GET /settings, GET /helpThis page and the settings page.
GET /api/market/status, GET /api/market/candidatesSession state and candidate lists.
POST /api/campaigns, GET /api/campaignsCreate and list campaigns.
POST /api/campaigns/{id}/start|execute-plan|pause|resume|close-all|stop-buy|start-buy|stop-sell|start-sellCampaign control.
POST /api/campaigns/{id}/chatNatural-language campaign instruction.
PATCH /api/campaigns/{id}/rulesChange targets, stops, confidence and position cap.
POST /api/trades/manualManual buy outside the campaign logic.
POST /api/trades/{id}/price, POST /api/trades/{id}/closePrice tick (paper) and manual exit.
GET /api/trades, GET /api/ordersTrade and order listings.
GET /api/broker/fundsThe balance strip in the header: paper figures from the database, plus the real Angel One balance when credentials exist. Read-only, so it works while live trading is still locked; ?refresh=1 bypasses the cache.
GET /api/broker/accountLive funds, holdings and positions (locked until live is enabled).
GET/POST /api/settings, POST /api/settings/test/{llm|broker|database}Read, save and connection-test settings.
GET /backtest, GET /backtest/{id}Backtest page and a saved run.
POST /api/backtest/runRun a backtest (or a signal comparison with compare:true).
GET /api/backtest/runs, DELETE /api/backtest/runs/{id}List and delete saved runs.
GET /api/ai/statusWhich AI provider is active.
GET /api/summaryCompact dashboard figures used by auto-refresh.
GET /api/global/status, POST /api/global/halt, POST /api/global/resumeKill switch. Halt optionally flattens every open position.
GET /api/quotes/status, POST /api/quotes/refresh, POST /api/quotes/resetPrice feed state, forced refresh, and replay rewind.
GET /api/notify/status, POST /api/notify/testNotification channels and a real test alert.
GET /api/export/trades.csv, GET /api/export/orders.csv, GET /api/export/campaign/{id}.csvCSV downloads for records and tax.
POST /api/settings/test/{llm|broker|database|notify|quotes}Live connection tests from the Settings page.

9. Backtesting ("would this have worked?")

Open Backtest in the navigation. The engine replays daily history one session at a time and drives the same code that runs paper trading — the real target/stop/trailing logic, the real risk checks and the real Indian charge model — against a throwaway database, so a backtest can never touch your live campaigns.

OptionWhat it does
SymbolsComma-separated NSE tickers to replay.
Sessions to replayHow many sessions to walk; the first few serve as SMA warm-up.
Entry signalmomentum (fast SMA above slow SMA), mean_reversion (buys dips below the slow SMA), random (a deliberate no-edge control), ai (your LLM rates each symbol each session).
Price sourceauto tries CSV → Yahoo Finance → Alpha Vantage → synthetic. Pin it to csv after fetching data so a run can never quietly use synthetic prices, or to yahoo to pull real prices on each run.
Fast / Slow SMA windowMoving-average lengths used by the momentum and mean-reversion signals.
Target / stop loss / trailing / confidence / max positions / daily lossThe same risk rules as a live campaign.
Target modePer-position targets, or stop the whole run when the campaign goal is reached.
Trade typeDelivery holds across sessions; intraday squares off at the end of every simulated session.
Run backtest / Compare signalsRun one signal, or replay several over the same window alongside buy & hold.

How to read the result. The metric that matters most is Excess vs buy & hold. Beating nothing is not an achievement: if a signal cannot beat simply holding the same stocks, the trading costs and timing are destroying value. The random control is the second check — a real signal should beat it. Always check the source badge: if it says SYNTHETIC DATA, the numbers are a plumbing test, not evidence.

Step-by-step: your first real backtest

  1. Open Backtest in the navigation.
  2. In the Fetch fresh data panel, leave Symbols as ALL (or type e.g. SBIN,RELIANCE,INFY), set Days of history to 400, pick Yahoo Finance and overwrite, then press Fetch fresh data. No API key is needed. The table below then shows every symbol on disk with its row count and date range — confirm it says 2024-09-23 to 2026-09-23 or similar, not “nothing on disk”.
  3. Scroll to Run a backtest. Set Symbols to symbols you actually fetched, and Price source to csv — pinning it means the run cannot silently fall back to synthetic prices.
  4. Set a first Entry signal of momentum, keep Target 10% / Stop 3%, and press Run backtest.
  5. Read the result. The badge must say source: csv. If it says SYNTHETIC DATA the run is a plumbing test only.
  6. Now press Compare signals. This replays momentum, mean-reversion and a random control over the same window next to buy & hold. The honest question is whether your signal beats both buy & hold and the random control.
  7. Saved runs appear under Saved runs; each one opens at /backtest/<id> with its equity curve and full trade log, and exports are available from there.

A real example from this deployment. With 13 NSE symbols fetched from Yahoo (501 real sessions, 2024-09-23 → 2026-09-23), momentum with a 10% target and 3% stop returned −36.5% against −12.9% for buy & hold — 51 trades, 27.5% win rate, profit factor 0.54, ₹5,525 of charges and a 47% drawdown. That is what testing is for: the strategy lost money and lost to simply holding, so it should not be trusted with real money as configured.

Supplying data by hand instead. You can skip the fetch button and drop one CSV per symbol into data/history/ named after the ticker, e.g. data/history/SBIN.csv. A date column and a close column are required (full OHLCV exports and yfinance-style Adj Close headers are handled; unusable rows are skipped and reported). Save an ALPHA_VANTAGE_API_KEY in Settings to use the alpha source instead. overwrite replaces a symbol’s whole window; append merges new days into the existing file and keeps older bars.

10. How the campaign decides what to buy — and what the AI costs

You do not tell it which stock to buy, and it cannot read your mind. Selection is a filter, not a guess:

  1. Shortlist. The campaign starts from the platform’s tracked NSE universe and narrows it by your Price category and Sector.
  2. Score every candidate. With an AI key saved, each candidate (up to Max AI calls per scan) is sent to the provider, which returns a rating (BUY/OVERWEIGHT/HOLD/UNDERWEIGHT/SELL/REVIEW), a confidence 0–100 and a one-sentence reason. With no key, the offline placeholder model scores them instead — those scores are not signals.
  3. Approve. A candidate is approved only if its confidence is at or above your Minimum AI confidence and its rating is not SELL or UNDERWEIGHT. The rest are rejected, with the reason recorded in the activity feed.
  4. Rank and cap. Approved candidates are sorted by confidence and the top Max positions are kept. Budget is then split evenly across them.
  5. Risk-check each order. Cash, position cap, trades-per-day, market session and the intraday entry cutoff are all still enforced. A blocked order is logged as a risk block rather than silently skipped.
  6. Execute. Whether that final step happens automatically is the Automation level:
Automation levelWhat happens after research
researchResearch only. Never places an order — a plan is produced for you to read.
approvalWaits for you to press Approve & Execute Plan. Nothing is bought until you do.
full_autoBuys on its own, within every rule above, as soon as research approves something.

Ways to steer it without giving it a ticker. Price category, sector, minimum confidence, max positions and trade type are the real controls: raising minimum confidence to 85% and capping max positions at 2 produces “fewer, higher-conviction, cheaper stocks”. Campaign chat understands plain English (“research banking shares, minimum 85% confidence, target 7%”) and applies those same fields. To name the stock yourself, use Buy a specific stock on the campaign page: it places your chosen symbol in this campaign, with your target and stop, and every risk rule still applies.

What the AI actually costs. Billing is per token, and this platform’s research prompt is tiny — about 149 input tokens and 60 output tokens per stock. On gemini-2.5-flash (list price $0.30 per million input, $2.50 per million output) one full scan of 5 stocks is roughly ₹0.086. A thousand campaigns would still be under ₹100. It does not cost ₹1,000 per campaign, and the common failure mode is the opposite of what people fear: the risk is surprise volume, not price per call. The real controls are Max AI calls per scan (caps calls per run), the per-symbol per-day cache (researching the same stock twice in a day is billed once), and provider rate limits. Gemini keys from Google AI Studio also include a free daily request quota, so light testing can cost nothing at all.

Measured spend is shown on Settings → AI usage & cost: real token counts taken from each provider response, spend per campaign, and the most recent calls. Set USD_INR_RATE to your card rate so the rupee figure matches your statement. Your provider invoice remains authoritative.

11. Step-by-step: paper campaign, then a live order

Stage 1 — paper, with real prices.

  1. SettingsAI / Research: choose gemini, paste the key, save, then press Test AI provider. Confirm AI research status shows the provider.
  2. SettingsPrice feed: set Price source to replay and Replay data source to csv so the campaign can actually exit on its own using the history you fetched.
  3. BacktestFetch fresh data for your symbols (if you have not already).
  4. Dashboard → create the campaign: Paper Trading, budget, target, stop, minimum confidence, max positions, price category, sector, and Automation level = full_auto if you want it to trade by itself.
  5. Open the campaign and press Research / Start. Watch the activity feed: every rating, every rejection reason, and each order appear in order.
  6. Let the monitor loop run. With the replay feed, positions will hit their target or stop and close themselves; each exit appears in the feed with its net P&L after charges and slippage.
  7. Judge it: real or placeholder research? What did the AI reasons say? Did anything beat a simple buy & hold? Compare against a backtest over the same symbols before believing it.

Stage 2 — going live, deliberately. Live orders stay impossible until all five gates are green (Settings → Live trading safety gates): ALLOW_LIVE_TRADING=true, LIVE_TRADING_ACK exactly I_UNDERSTAND_LIVE_TRADING_RISK, ANGEL_STATIC_IP_REGISTERED=true, all four Angel One credentials present, and the whitelisted IPv4 saved as ANGEL_STATIC_IP so drift can be detected.

  1. Read section 12 and register your server’s static IP with Angel One — the panel in Settings shows exactly which address that is. Then fill in ANGEL_API_KEY, ANGEL_CLIENT_CODE, ANGEL_PASSWORD and the ANGEL_TOTP_SECRET seed (not the 6-digit code), plus the same IPv4 as ANGEL_STATIC_IP.
  2. Press Test Angel One login. It signs in and reads your balance but never places an order, so it is safe while live is still locked.
  3. Switch Price source to angel and confirm Test price feed passes — live exits depend on real prices.
  4. Open the gates one at a time, until the header shows LIVE UNLOCKED.
  5. Start with a deliberately small budget and Max positions of 1, and Automation level = approval so you press the button for every order until you trust it.
  6. Place one order, then verify it on the broker’s own order book against the campaign’s order log. Charges shown here are estimates; the contract note is authoritative.
  7. Only then move to full_auto. Keep Notifications on and keep the Halt all trading button within reach — it blocks new buys everywhere while still allowing exits.

12. Deploying it: laptop, LAN or VPS

The correct values for the broker differ completely depending on where this runs, and a machine behind a router cannot know its own public address. So Settings → Where this app is running detects it and shows its reasoning.

ShownWhat it is and why you need it
Detected environmentA best-effort label (cloud_vps, container, behind_nat, public_host) with a confidence level and the evidence behind it. Cloud hosts are identified from the hypervisor’s own identity string; containers from /.dockerenv, cgroups and Kubernetes variables. A home machine behind NAT is genuinely unprovable, so it is labelled at medium confidence rather than guessed at.
Public IPThe address the internet sees — the one your broker will see. Found via a keyless HTTPS lookup, because behind a router the machine only knows its private address. Clear PUBLIC_IP_LOOKUP_URL if you would rather not call a third party; detection then reports it as unverified.
Local IPThis machine’s address inside its own network (e.g. 192.168.1.24). Useful on a LAN, and never the address to whitelist with a broker.
MAC addressThe physical hardware address of each adapter, read from getmac on Windows or /sys/class/net on Linux. Useful for identifying the machine on a network, for MAC-based DHCP reservations (so a home IP stops changing), and for your own records.

What to type into the portal. The SmartAPI “Add App” form has five fields, and the panel gives the value for each of them for one deployment, not a menu: App Name, Redirect URL, Post back URL (blank), Primary Static IP, Secondary Static IP (blank). It picks local or VPS from how you are reaching the app, and you can switch the target if you are filling the form in for a server you have not moved to yet. Press Copy beside any value and paste it straight in.

The Redirect URL is required by the form. This app authenticates with TOTP, so it never calls that URL — but the path /auth/callback is a real route on this server, so what you register resolves instead of 404ing. A registered URL that is a dead end is a trap: it looks correct until someone tries the web login flow. The static IP is the same value whether you run locally or on a VPS, and that is the part most setups get wrong: Angel One whitelists the address your orders leave from, so an app on a laptop places orders from the home connection’s public IP. Locally that address changes, and the portal allows only one static-IP change per week — which is why a laptop is fine for testing and a poor foundation for live orders.

Ignore the X-ClientPublicIP header. The installed SmartAPI SDK (1.5.5) sets that header to a hardcoded IP inside a finally block — and a finally always runs — so the value it reports is not your machine's address. If you ever see an unfamiliar IP in a broker support ticket, that is why. Angel One enforces the whitelist against the source IP your orders actually come from, which is the address the panel detects. The panel checks the installed SDK for this and warns you when it finds it, so the correction disappears by itself if upstream fixes it.

Static IP, and why drift matters. Angel One now requires orders to come from a whitelisted static IPv4. Only order and GTT calls need it — login, market data and historical data work from any address. So a drifting IP produces the worst possible failure: everything looks healthy, and only order placement fails. Save the address as ANGEL_STATIC_IP and this app compares it against reality on every Settings visit, warning you the moment they diverge. Two further details worth knowing: only IPv4 is supported (an IPv6-only egress cannot be registered), and after registering you should make one successful API call from that exact IP within 24–48 hours to confirm it.

ScenarioWhat to do
Laptop, testing only — or a local run you keep usingLeave live trading locked and use the sheet’s local answers. A home public IP is usually dynamic and often shared behind CGNAT, so it is a poor basis for a live setup; the panel says so rather than quietly handing you an address that will stop working.
Home or office server, live tradingAsk your ISP for a static IPv4, or reserve the LAN address by MAC and use a VPN with a fixed egress IP. Then register that public IP, save it as ANGEL_STATIC_IP, and confirm the app reports it as matching. A mobile hotspot or a router reboot will otherwise break order placement while login keeps working.
VPSPut TLS in front (Caddy or Nginx) so you can register an https:// redirect URL, set PUBLIC_BASE_URL to that domain, whitelist the VPS’s public IPv4, and keep AUTH_ENABLED on. Never leave the dashboard password at its default.
Container or KubernetesWhitelist the egress IP of the cluster, which is often not the node IP and sometimes not stable. Confirm with Test deployment & static IP before trusting it.

Press Test deployment & static IP in Settings → Test connections to re-run detection on demand. It fails loudly when the IP your broker will see no longer matches the registered one, because that is the failure that matters.

13. Editing settings and clearing data

Every field has a ✕ button. It empties a text field, or restores a number, switch or dropdown to the value declared in config.py — a number cannot be blank, so “clear” reasonably means “back to the default”. Marked fields turn amber and say what will happen; press undo to cancel. Nothing is written until you press Save settings. Read-only fields get no button because they are rejected server-side.

A subtlety worth knowing, because it explains a bug you could otherwise hit: a secret field left blank means “keep the current value”, which is why it is not the same as pressing ✕. Blank protects a stored key from being wiped by an unrelated save. ✕ is the explicit instruction to remove it.

The Danger zone (Settings, at the bottom) is the only place that deletes data:

ButtonWhat it removes
Download backup (JSON)Every row from every table as JSON. Do this first — it is the only way back.
Clear all trading dataCampaigns, trades, orders, research recommendations, campaign chat, campaign events, backtest runs, AI usage records and the audit log. Never touches .env, and never places a broker order.
Close positions, then clearSubmits an exit for every open position, waits for it to be recorded, then clears. Refused while live trading is enabled.
Clear everything + reset settingsThe above, and every setting returns to its default in config.py — including API keys and broker credentials.

A tick box also deletes the downloaded data/history/*.csv price files, so backtests and replay runs start from nothing.

Two safety rules, both deliberate. Each button needs two clicks — the first arms it and explains what will happen, the second performs it — so no single stray click can destroy anything, and there is no magic string to type. And a clear is refused while any position is open or pending: deleting those rows would not close anything, it would only lose track of money still on the market. Forcing past that is itself refused while live trading is enabled.

One design note the app takes seriously: .env rewrites drop duplicate keys rather than updating only the first one. With two lines for the same key it is whichever the loader reads last that wins, so a save could report success, look correct in the running process, and then silently revert on the next restart.

14. Operating it safely

ControlWhat it does
Halt all tradingBlocks opening positions on every campaign by switching off auto-buy and clearing TRADING_ENABLED. Exits stay allowed, so a halt can never trap you in a position. The change is written to .env and survives a restart.
Halt + close all positionsThe same halt, then submits an exit for every open position immediately.
Resume tradingRe-allows entries. Each campaign keeps its own auto-buy state, so re-enable that separately if you want it.
Refresh prices nowForces one price update for open positions outside the normal schedule.
Reset replay feedRewinds the replay price source to its first bar.
Export trades / orders CSVDownloads the full trade and order history for records or tax. A per-campaign export is on each campaign page.
Auto-refreshPolls the summary endpoint so prices, P&L and the market pill stay current without reloading. Interval is DASHBOARD_REFRESH_SECONDS; 0 disables it.
Login lockoutAfter AUTH_MAX_FAILURES bad logins from one IP, that IP is refused with HTTP 429 for AUTH_LOCKOUT_SECONDS. A successful login clears the counter.

15. Price feed and paper realism

Why a feed matters. Target, stop-loss and trailing-stop rules are evaluated when a price arrives. If prices only arrive when you click a button, the campaign cannot exit on its own. Setting QUOTE_SOURCE makes it autonomous.

SourceBehaviour
noneDefault. Manual price ticks only. Safe, but nothing is automatic.
replayWalks one daily bar per poll through data/history/<SYMBOL>.csv, falling back to the synthetic generator so it works immediately. This is the easiest way to watch the exit rules actually fire end to end.
angelReal last-traded prices from Angel One, batched into one market-data call per poll. Requires working broker credentials.

Slippage. PAPER_SLIPPAGE_BPS moves every paper fill against you by that many basis points — buys fill slightly higher, sells slightly lower. At 0 a round trip is free, which flatters results; the 5 bps default models a realistic spread. The backtester uses the same broker, so the same friction applies there.

Notifications. With NOTIFY_ENABLED on, alerts go to a webhook, Telegram and/or email. NOTIFY_EVENTS selects which events fire, using keys like position_opened, position_closed, daily_loss_limit, global_halt and error. Sends are best-effort: a failing channel is reported but never blocks a trade.

16. Known limitations