01 Watch it trade
The real rules, running on a simulated market.
The chart below generates a random price series and lets the bot's rules trade it one day at a time. It runs once and then stops, so you can study the whole run and every trade before starting another. Prices are made up, so the result changes on every run, and some runs lose money. The made-up market moves in rising and falling phases that last a couple of months, which is the kind of market this strategy is designed for. In a market with no direction it roughly breaks even. The entries, stops, targets, and position sizes are calculated exactly as the bot calculates them.
This Run, Start to Finish
| # | Side | In | Out | Entry | Exit | Closed by | Result |
|---|
Simulated prices for illustration. This is not a record of real or paper trading results, and it is not investment advice.
02 Year to date
How the rules would have done on real prices this year.
A backtest applies today's rules to past prices. It assumes every order fills at the planned price and ignores slippage, and it does not charge the cost of borrowing shares to short, so real results would differ. Past performance does not predict future results.
03 The rules
Every decision is written down before the trade.
When It Enters
It trades both directions. All five conditions must be true on the same day.
| Check | Long | Short |
|---|---|---|
| Trend | Price above the 50-day EMA, 21-day EMA rising | Price below the 50-day EMA, 21-day EMA falling |
| Setup | Dips to the 21-day EMA and closes above it | Rallies to the 21-day EMA and closes below it |
| RSI(14) | Between 40 and 60, turning up | Between 40 and 60, turning down |
| MACD (12, 26, 9) | Histogram rising | Histogram falling |
| Volume | Below its 20-day average, so the move against the trend is a quiet one | |
| Market | S&P 500 above its 50-day EMA | S&P 500 below its 50-day EMA |
The market check means it only goes long when the broad market is rising and only shorts when it is falling. The simulation above trades a single made-up stock, so it skips that check.
How Much It Trades
Shares = (account value × 1%) ÷ (distance from entry to stop). A wider stop means fewer shares, so every trade risks the same share of the account. Positions are capped at 20% of the account, with at most five open at once.
When It Exits
- Stop: 7% against the position, below a long or above a short, set at entry and stored with the trade.
- First target: close half at 5% in its favor and move the stop to the entry price, so the rest cannot lose.
- Second target: close the remainder at 10% in its favor.
- Trailing stop: after the first target, the stop follows 3% behind the best close.
- Time stop: if a trade is within 1.5% of entry after 10 trading days, close it and free the capital.
04 How it is built
Small Python modules, one job each.
The bot is written in Python and places orders through Alpaca's paper trading API, which fills simulated orders at live market prices. Each part of the system lives in its own file: signal generation, a second-stage data filter, risk and position sizing, portfolio and exit logic, order execution, logging, and performance tracking.
What a Code Review Changed
Auditing the first version turned up two bugs that mattered. Exits were recalculating the stop as a flat 2% instead of using the stop the trade was sized on, which closed trades early, and the profit target was fixed at 2%, too small for a swing trade. The fixes were to store each trade's stop at entry and reload it when checking exits, make targets configurable by strategy, add the volume filter, and add a daily loss limit. The rules on this page are the corrected design.
What I took from it. The hard part of a trading system is not finding signals. It is making sure the risk rules written on paper are the ones the code enforces.