Read positions¶
Use position to decide which rule applies and read the current instrument's holding.
| Value | Meaning |
|---|---|
position.is_flat |
No quantity held. |
position.is_long |
Positive quantity. |
position.is_short |
Negative quantity. |
position.qty |
Signed quantity. |
position.entry_price |
Average entry price. |
position.unrealized_pnl |
Marked profit/loss. |
position.bars_held |
Bars since entry. |
def on_tick():
if len(close) < 20:
return
if position.is_flat and close[0] > mean(close, 20):
long(10)
elif position.is_long and close[0] < mean(close, 20):
close()
In explicit multi-symbol mode, use position["TCS"] to select a member. Writes happen through actions such as long, short and close, not by assigning a position property. position.size_to(0.20) targets a 20% equity fraction.
max_runup_pct and max_drawdown_pct use percentage numbers (5.0 means 5%); entry stop and size_pct use fractions. See position and account reference.
Single instrument versus explicit membership¶
In a single-instrument strategy, position.qty and action methods resolve the current instrument. In explicit multi-symbol mode, select a member with position["TCS"]; scalar actions and comparisons on an unscoped position are ambiguous.
bool(position) asks whether any position is open in multi-symbol mode. "TCS" in position asks whether that particular instrument has open quantity. Iterating position.items() visits open members; it does not enumerate the full eligible universe.
def on_tick():
member = position["TCS"]
if member.is_long and member.bars_held >= 10:
member.close()
This acts only on the selected member. It requires that instrument and its position state to be available in the strategy environment.
bars_held starts at zero on the fill bar, not the signal bar. With the default
next-open execution, an entry requested on Monday and filled on Tuesday has
age zero on Tuesday, one on Wednesday and two on Thursday. The age counts
processed feed bars, including bars for other instruments in an interleaved
feed; it is not a count of trading days or elapsed minutes. Skipped data gaps do
not advance it. Reducing the retained history does not reset this clock.
Current checkpoints preserve this logical-run clock, so a resumed run uses the same ages as a continuous run. Checkpoints from older versions did not record the clock separately: they infer it from saved history and cannot reconstruct an earlier truncated history exactly. Re-run from the original data when exact age-based exit parity is required for an old checkpoint.
Interpret values in their own units¶
A quantity of -10 is a short of ten units. entry_price is the average entry price, not the latest close. When flat it is zero, so check position state before using it as a divisor or protected price anchor.
position.value is signed quantity times the available price and can fall back to entry price. It is not positive gross exposure or guaranteed fresh P&L. entry_time can be absent and bar/runup/drawdown fields can be zero when tracking information is unavailable.
position.close(2) requests a two-unit partial close. position.size_to(0.20) requests a 20% equity target and can resize a continuing holding; it is not a 20% take-profit level. Update protections through set_stop/set_target/set_trail while open, as described in protection.