Position State
Published Last updated
Key Takeaway
Position state is the bot's real-time record of whether it holds an open trade and, if so, the entry price, stop-loss level, and timestamp at which the position was entered.
Learn These First
What Is Position State?
Position state is the bot's real-time record of whether it holds an open trade and, if so, the entry price, stop-loss level, and timestamp at which the position was entered.
How Position State Works
Frequently Asked Questions
What is position state in a trading bot and why is it needed?
Position state is the persistent record a trading bot maintains about whether it currently holds an open trade. Without it, the bot has no way to know whether it is already in a position when evaluating signals on the next candle. In J21's RSI Signal Bot, position state is a dictionary tracking four values: whether the bot is in a position, the entry price, the stop-loss price, and the entry timestamp. The exit signal function requires the stored entry and stop prices to determine whether the price has reached the take-profit target or stop-loss level established when the trade was originally entered.
How does position state update when a trade opens and closes?
When a trade opens — entry signal returns true and `in_position` is False — the main loop calls enter_position, updating the state: `in_position` becomes True, `entry_price` is set to the current close, `stop_price` is calculated from per-trade risk parameters, and `entry_time` records the timestamp. When a trade closes — the exit signal returns true — the trade details are recorded to the results log, then the state is reset: `in_position` becomes False and all price fields return to None. This reset is critical — omitting it leaves the bot in a ghost position state that prevents all subsequent entries.
How is position state different from signal logic in a trading bot?
Signal logic and position state serve different roles. Signal logic is stateless — it evaluates whether conditions on a single candle meet entry or exit criteria and returns a boolean, with no memory of previous candles. Position state is persistent — it carries trade information forward across candle evaluations, storing what happened when a trade opened so exit functions have the context they need. Signal logic provides the decisions; position state provides the memory that makes those decisions meaningful. Together they implement the complete trade lifecycle from signal detection through management to closure and reset.
Common Misconceptions About Position State
Position state is only needed for live trading — backtesting does not require it.
Position state is required in backtesting as much as in live trading. A backtesting loop iterates through thousands of candles evaluating entry and exit conditions at each step. Without position state, the loop cannot prevent double-entry — entering a new trade while already in one — or correctly calculate exit prices and P&L based on the entry price established when the trade opened. Position state in the backtesting loop is what makes the simulated trade lifecycle structurally correct — without it, backtesting produces performance metrics that bear no relationship to how the strategy would actually operate in real market conditions.
A database or external file should be used to store position state for reliability in live trading.
For J21's single-strategy, session-based bot, in-memory position state using a Python dictionary is the appropriate architecture. The state only needs to persist for one trading session — when the bot restarts between sessions it should have no open positions due to the session window's close-all discipline. External database storage introduces additional dependencies and failure modes without reliability benefits for a single-session bot. Database state persistence becomes relevant in multi-strategy bots where state must survive process restarts — a J22+ architectural concern not required for J21's scope.
Position state should be stored inside the signal logic functions to keep related code together.
Storing position state inside signal logic functions violates the architectural separation that makes the bot's modules independently testable. Signal logic functions should be pure — the same inputs always produce the same outputs with no side effects. If position state lives inside a signal function, the function's output depends on internal history, making it impossible to test with simple input/output verification. A bug in the signal function could also corrupt the position state, creating compound errors far harder to isolate and debug than bugs in modules with clearly separated responsibilities and no shared internal state.