T09 · Insecure Skill Coding Practices
- Location
trader.py:45- Finding
Documented Liquidity and Portfolio Exposure Safeguards Are Not Enforced
- Content
View full analysis
Vulnerability Details
File Location:
trader.py:45-49,trader.py:410-432,trader.py:479, andtrader.py:516
Vulnerability Type: Missing liquidity filtering and portfolio-level exposure enforcement
Risk Level: HighThe implementation declares configurable minimum-volume, maximum-position, and maximum-open-position controls, but it does not fully enforce them.
python MAX_POSITION = float(os.environ.get("SIMMER_MAX_POSITION", "40")) MIN_VOLUME = float(os.environ.get("SIMMER_MIN_VOLUME", "3000")) MAX_SPREAD = float(os.environ.get("SIMMER_MAX_SPREAD", "0.10")) MIN_DAYS = int(os.environ.get( "SIMMER_MIN_DAYS", "7")) MAX_POSITIONS = int(os.environ.get( "SIMMER_MAX_POSITIONS", "10"))The trade counter is initialized for every invocation and only counts successful orders placed during that invocation:
python # Determine regime placed = 0 if fear_index > FEAR_THRESHOLD: # PANIC regime: markets are oversold by fear -- buy the most oversold safe_print( f" [regime] PANIC (fear={fear_index:.0%} > {FEAR_THRESHOLD:.0%}) " f"-- looking for oversold markets to buy" ) # Find all markets below YES_THRESHOLD, sorted by probability (most oversold first) oversold = [] for m in markets: p = float(m.current_probability) if p <= YES_THRESHOLD: oversold.append(m) oversold.sort(key=lambda m: float(m.current_probability)) safe_print(f" [panic] {len(oversold)} oversold markets (p <= {YES_THRESHOLD:.0%})") for m in oversold: if placed >= MAX_POSITIONS: breakEquivalent per-run checks are used in the complacency and neutral regimes:
python for m in overpriced: if placed >= MAX_POSITIONS: breakpython for m in markets: if placed >= MAX_POSITIONS: breakTechnical Analys
...[truncated 2258 chars]
- Remediation
View remediation
Remediation Suggestions
-
Apply the volume filter before signal generation and trading:
python volume = getattr(market, "volume", None) if not isinstance(volume, (int, float)) or volume < MIN_VOLUME: return None, 0, "Market volume is below the configured minimum"Use the actual volume field and units defined by the SDK.
-
Query open positions and pending orders before submitting any trade. Count existing positions toward
MAX_POSITIONS. -
Calculate remaining capacity for each market:
python remaining = max(0, MAX_POSITION - existing_market_exposure - pending_exposure) size = min(size, remaining)Skip the trade when the remaining capacity is below the venue's minimum order size.
-
Enforce a portfolio-wide capital or notional limit in addition to the per-market limit.
-
Refresh portfolio state after every successful order. Where supported, use atomic SDK or venue-side risk limits to prevent concurrent runs from bypassing local checks.
-
Prevent overlapping executions with a process lock or distributed lock when scheduled operation is enabled.
-
Add automated tests covering existing positions, pending orders, repeated invocations, low-volume markets, and concurrent executions.
-
