A PRODUCT NOTE ON CONTROLLED MARKET AUTOMATION
Why a trading bot should be allowed to do nothing
Most trading bots are designed around execution. niles starts from a different premise: refusal is part of a valid decision.
Product note · July 2026
Producing a prediction and authorizing an action are different problems. Trading systems need to handle both without treating one as the other.
A model can estimate the probability of an outcome. It cannot, by itself, decide whether a system should act on that estimate. The order may be too large. The market may be too thin. The account may be out of sync. Two strategies may have reached opposing conclusions. A useful prediction can still produce a bad trade.
That distinction is the starting point for niles. It does not treat every signal as a reason to move money. The system must be able to explain why it traded, why it refused, and which evidence supported either result.
The question behind the system
Automated trading demos tend to focus on the exciting part: a model finds an opportunity and an order appears. The difficult work sits between those two events. Market data has to be current. The opportunity has to be tradable. Independent methods need to agree. Capital limits have to hold across the portfolio. The venue has to confirm what happened.
The design question is straightforward: can a small trading system make the quality of the control path matter as much as the quality of the prediction?
niles is a working answer. It scans prediction markets on Polymarket and a configured stock and ETF universe through Alpaca. Eligible short entries are available behind a separate disabled-by-default gate. It can run in dry-run mode or submit live orders when the operator has enabled that path. The same decision process applies in both modes.
A prediction describes what may happen. Authorization decides whether the system is permitted to act.
Every opportunity starts as a candidate
The main design choice is that a market opportunity enters the system as a candidate, not an instruction. That sounds like a small distinction, but it changes the behavior of the entire application.
A candidate can be rejected before a model sees it because the market is closed, the spread is too wide, liquidity is weak, or the asset is outside the approved universe. It can survive those screens and still stop because a model failed, its confidence was too low, or the model budget was exhausted. It can have a strong probability estimate and still stop because the strategies disagree. It can pass all of that and still fail a risk or account-state check.
Each refusal is recorded with a reason. “No trade” becomes an observable decision instead of an empty space in the activity log.
- 01Observe
Collect current prices, liquidity, history, and market activity.
- 02Evaluate
Apply deterministic screens, probability estimates, and strategy signals.
- 03Authorize
Check agreement, capital limits, account state, and execution conditions.
- 04Act
Persist the intent, simulate or submit, and reconcile the result.
How the decision is built
The process begins with evidence. For Polymarket, that includes current prices, order-book depth, spread, resolution time, market category, and the activity of selected wallets with a repeatable track record. For Alpaca, it includes price action, volume, event context, market hours, liquidity, and the current account state.
Deterministic screens run first. They are cheap, explicit, and easy to audit. A disabled venue, unsupported asset, closed market, weak order book, or excessive estimated slippage should not consume model budget. Removing those candidates early keeps the more expensive reasoning focused on opportunities that could actually become trades.
The candidates that remain receive a probability case. The system records the estimated probability, confidence, thesis, prompt version, provider, and cost. Claude and OpenAI can produce separate decision records. A provider failure does not disappear into a blended score. It remains a failed input.
Focused strategies then evaluate different parts of the case. Arbitrage looks for inconsistent pricing across related outcomes. Convergence looks for the market moving toward the model estimate. Whale-copy logic treats qualified wallet activity as a directional signal. The stock and ETF strategy evaluates its own price, volume, liquidity, and account constraints.
Agreement determines how much of the proposed position can continue. Two or more aligned signals can support a full risk-approved position. One signal supports half. Directional conflict means no trade. Strategy output informs authorization; it does not bypass it.
Why the gates matter
A good thesis is not enough to place an order. Before live execution, Poly Bot checks the operator, the market data, the model decision, strategy agreement, cumulative risk, and the state of the venue account. Every required gate has to pass.
The risk layer applies position limits, daily-loss limits, allocation limits, open-position limits, market-hours rules, and Alpaca account and borrow eligibility together. Position sizing uses a fractional Kelly calculation as an input, caps the fraction, and then applies the absolute limits. A mathematically attractive size does not override a configured boundary.
Execution has its own boundary. The bot writes an idempotent order intent before submission and reconciles its view with the venue. Unknown or mismatched venue state blocks another order. Reported performance comes from confirmed balances, positions, and fills. Simulated and unfilled orders do not become actual results.
The goal is not to trade as much as possible. The goal is to know which decisions earned the right to run.
What the product does not claim
niles does not guarantee returns, and it does not make automated trading safe. Models can be wrong. Historical wallet behavior can stop repeating. Market structure can change faster than a strategy adapts. A valid control path limits how the system acts; it does not remove market risk.
The current Alpaca scope is narrow: long stocks and ETFs plus explicitly enabled easy-to-borrow U.S. equity shorts. Options, crypto, hard-to-borrow locates, margin-funded long purchases, and unsupported asset classes are refused. A venue does not become eligible because credentials exist. The operator must enable it, select the permitted account mode, and set the exposure limits.
Those constraints are part of the product, not temporary obstacles around it. Automation becomes easier to trust when its authority is visible and finite.
How to try it
The dashboard exposes the current operating mode, candidate funnel, model decisions, refusals, risk settings, audit events, orders, and venue-confirmed results. Start in dry-run mode. Review what the bot would have done, inspect the refusal reasons, and change the limits before considering live execution.
The public product overview contains the interactive five-stage method guide for anyone who wants the algorithm details. Dashboard access uses GitHub to identify approved operators. Market and model credentials are not shared with GitHub.
niles is designed to make automated decisions legible. The system can act, but it must also be able to stop, refuse, and explain why.