@senpi/runtime 3.0.0-dev.openclaw-upgrade-mai.20260623210452 → 3.0.0-dev.runtime-phase-2.20260623210537
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -10
- package/dist/actions/decision-engine.d.ts.map +1 -1
- package/dist/actions/decision-engine.js +0 -3
- package/dist/actions/decision-engine.js.map +1 -1
- package/dist/actions/open-position/open-position.action.d.ts.map +1 -1
- package/dist/actions/open-position/open-position.action.js +2 -6
- package/dist/actions/open-position/open-position.action.js.map +1 -1
- package/dist/cli/guide-commands.d.ts.map +1 -1
- package/dist/cli/guide-commands.js +56 -43
- package/dist/cli/guide-commands.js.map +1 -1
- package/dist/cli/senpi-commands.d.ts.map +1 -1
- package/dist/cli/senpi-commands.js +108 -0
- package/dist/cli/senpi-commands.js.map +1 -1
- package/dist/constants/dsl/index.d.ts +0 -2
- package/dist/constants/dsl/index.d.ts.map +1 -1
- package/dist/constants/dsl/index.js +0 -2
- package/dist/constants/dsl/index.js.map +1 -1
- package/dist/dsl/engine-client/config-mapping.d.ts +0 -7
- package/dist/dsl/engine-client/config-mapping.d.ts.map +1 -1
- package/dist/dsl/engine-client/config-mapping.js +2 -16
- package/dist/dsl/engine-client/config-mapping.js.map +1 -1
- package/dist/dsl/events/handlers.d.ts +2 -18
- package/dist/dsl/events/handlers.d.ts.map +1 -1
- package/dist/dsl/events/handlers.js +213 -302
- package/dist/dsl/events/handlers.js.map +1 -1
- package/dist/dsl/monitor/create-monitor.d.ts +0 -15
- package/dist/dsl/monitor/create-monitor.d.ts.map +1 -1
- package/dist/dsl/monitor/create-monitor.js +9 -44
- package/dist/dsl/monitor/create-monitor.js.map +1 -1
- package/dist/dsl/monitor/process-one-position.d.ts.map +1 -1
- package/dist/dsl/monitor/process-one-position.js +1 -24
- package/dist/dsl/monitor/process-one-position.js.map +1 -1
- package/dist/dsl/plugin/index.d.ts +1 -16
- package/dist/dsl/plugin/index.d.ts.map +1 -1
- package/dist/dsl/plugin/index.js +4 -35
- package/dist/dsl/plugin/index.js.map +1 -1
- package/dist/dsl/plugin/options.d.ts +0 -18
- package/dist/dsl/plugin/options.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -4
- package/dist/index.js.map +1 -1
- package/dist/runtime/create-scanner-module.d.ts +3 -4
- package/dist/runtime/create-scanner-module.d.ts.map +1 -1
- package/dist/runtime/create-scanner-module.js +5 -14
- package/dist/runtime/create-scanner-module.js.map +1 -1
- package/dist/runtime/create-scanner-providers-for-run.d.ts.map +1 -1
- package/dist/runtime/create-scanner-providers-for-run.js +1 -12
- package/dist/runtime/create-scanner-providers-for-run.js.map +1 -1
- package/dist/runtime/load-runtime-config.js +1 -1
- package/dist/runtime/load-runtime-config.js.map +1 -1
- package/dist/runtime/map-strategies-registration.js +8 -7
- package/dist/runtime/map-strategies-registration.js.map +1 -1
- package/dist/runtime/map-strategies.d.ts.map +1 -1
- package/dist/runtime/map-strategies.js +3 -12
- package/dist/runtime/map-strategies.js.map +1 -1
- package/dist/runtime/reconcile-state.d.ts +0 -44
- package/dist/runtime/reconcile-state.d.ts.map +1 -1
- package/dist/runtime/reconcile-state.js +44 -80
- package/dist/runtime/reconcile-state.js.map +1 -1
- package/dist/runtime/risk-guard.d.ts.map +1 -1
- package/dist/runtime/risk-guard.js +12 -17
- package/dist/runtime/risk-guard.js.map +1 -1
- package/dist/runtime/runtime-schema.d.ts +995 -2855
- package/dist/runtime/runtime-schema.d.ts.map +1 -1
- package/dist/runtime/runtime-schema.js +40 -133
- package/dist/runtime/runtime-schema.js.map +1 -1
- package/dist/runtime/runtime.d.ts +0 -26
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +5 -233
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/runtime/scanner-registry.d.ts +1 -1
- package/dist/runtime/scanner-registry.d.ts.map +1 -1
- package/dist/runtime/scanner-registry.js +12 -3
- package/dist/runtime/scanner-registry.js.map +1 -1
- package/dist/runtime/supervisor/long-running-supervisor.d.ts.map +1 -1
- package/dist/runtime/supervisor/long-running-supervisor.js +1 -1
- package/dist/runtime/supervisor/long-running-supervisor.js.map +1 -1
- package/dist/runtime/supervisor/orphan-sweep.js +1 -1
- package/dist/runtime/supervisor/orphan-sweep.js.map +1 -1
- package/dist/runtime/supervisor/supervisor-utils.d.ts +1 -1
- package/dist/runtime/supervisor/supervisor-utils.d.ts.map +1 -1
- package/dist/runtime/supervisor/supervisor-utils.js +1 -1
- package/dist/runtime/supervisor/supervisor-utils.js.map +1 -1
- package/dist/runtime-api/intake/intake-mount.d.ts.map +1 -1
- package/dist/runtime-api/intake/intake-mount.js +36 -28
- package/dist/runtime-api/intake/intake-mount.js.map +1 -1
- package/dist/runtime-api/intake/process-signal-post.d.ts.map +1 -1
- package/dist/runtime-api/intake/process-signal-post.js +0 -0
- package/dist/runtime-api/intake/process-signal-post.js.map +1 -1
- package/dist/runtime-api/intake/scanner-launcher.d.ts +4 -18
- package/dist/runtime-api/intake/scanner-launcher.d.ts.map +1 -1
- package/dist/runtime-api/intake/scanner-launcher.js +3 -24
- package/dist/runtime-api/intake/scanner-launcher.js.map +1 -1
- package/dist/runtime-api/intake/types.d.ts +0 -6
- package/dist/runtime-api/intake/types.d.ts.map +1 -1
- package/dist/runtime-api/routes/signals.schema.d.ts +0 -1
- package/dist/runtime-api/routes/signals.schema.d.ts.map +1 -1
- package/dist/runtime-api/routes/signals.schema.js +0 -5
- package/dist/runtime-api/routes/signals.schema.js.map +1 -1
- package/dist/scanners/external/liquidation-watchdog/README.md +107 -0
- package/dist/scanners/external/liquidation-watchdog/liquidation-watchdog.yaml +48 -0
- package/dist/scanners/external/liquidation-watchdog/producer.mjs +336 -0
- package/dist/scanners/external/momentum/README.md +148 -0
- package/dist/scanners/external/momentum/momentum.yaml +116 -0
- package/dist/scanners/external/momentum/producer.mjs +251 -0
- package/dist/scanners/external/scaffold/__main__.py +24 -65
- package/dist/scanners/external/scaffold/delivery.py +22 -56
- package/dist/scanners/external/scaffold/entrypoint_loader.py +48 -42
- package/dist/scanners/external/scaffold/journal.py +2 -13
- package/dist/scanners/external/scaffold/scaffold.py +128 -159
- package/dist/scanners/external/scaffold/signal_envelope.py +34 -177
- package/dist/scanners/external/shared/ingest.mjs +112 -0
- package/dist/scanners/external-scanner-receiver.d.ts +0 -6
- package/dist/scanners/external-scanner-receiver.d.ts.map +1 -1
- package/dist/scanners/external-scanner-receiver.js +1 -14
- package/dist/scanners/external-scanner-receiver.js.map +1 -1
- package/dist/scripts/run-dsl-standalone-live.d.ts +1 -1
- package/dist/scripts/run-dsl-standalone-live.js +3 -5
- package/dist/scripts/run-dsl-standalone-live.js.map +1 -1
- package/dist/senpi/client.d.ts +0 -12
- package/dist/senpi/client.d.ts.map +1 -1
- package/dist/senpi/client.js +2 -31
- package/dist/senpi/client.js.map +1 -1
- package/dist/state/state-manager.d.ts +0 -17
- package/dist/state/state-manager.d.ts.map +1 -1
- package/dist/state/state-manager.js +0 -28
- package/dist/state/state-manager.js.map +1 -1
- package/dist/strategy/strategy-state.d.ts.map +1 -1
- package/dist/strategy/strategy-state.js +1 -7
- package/dist/strategy/strategy-state.js.map +1 -1
- package/dist/tracking/constants.d.ts.map +1 -1
- package/dist/tracking/constants.js +0 -2
- package/dist/tracking/constants.js.map +1 -1
- package/dist/types/dsl/index.d.ts +1 -1
- package/dist/types/dsl/index.d.ts.map +1 -1
- package/dist/types/scanner.d.ts +0 -7
- package/dist/types/scanner.d.ts.map +1 -1
- package/examples/README.md +89 -0
- package/examples/scanners-consumer-quickstart.mjs +134 -0
- package/examples/scanners-emerging-movers-v4.mjs +287 -0
- package/examples/scanners-liquidation-watchdog.mjs +341 -0
- package/examples/scanners-live-mcp.mjs +208 -0
- package/examples/scanners-multi-strategy.mjs +165 -0
- package/examples/scanners-position-tracker-e2e.mjs +225 -0
- package/examples/scanners-scheduled-events.mjs +96 -0
- package/examples/scanners-senpi-provider-client.mjs +182 -0
- package/examples/scanners-single-strategy.mjs +198 -0
- package/examples/strategies/README.md +12 -17
- package/examples/strategies/dsl-showcase.yaml +68 -0
- package/examples/strategies/dsl.yaml +51 -0
- package/examples/strategies/fox-minimal-loosened.yaml +240 -0
- package/examples/strategies/fox-minimal.yaml +242 -0
- package/examples/strategies/minimal.yaml +46 -0
- package/examples/strategies/momentum/how-it-works.md +48 -0
- package/examples/strategies/momentum/momentum-guarded.yaml +161 -0
- package/examples/strategies/risk-showcase.yaml +93 -0
- package/examples/strategies/viper.yaml +67 -0
- package/examples/strategies/wolf.yaml +72 -0
- package/examples/yamls/sample-with-dsl-and-emerging-movers.yaml +123 -0
- package/package.json +1 -1
- package/dist/runtime/reconcile-decide.d.ts +0 -73
- package/dist/runtime/reconcile-decide.d.ts.map +0 -1
- package/dist/runtime/reconcile-decide.js +0 -166
- package/dist/runtime/reconcile-decide.js.map +0 -1
- package/dist/runtime/reconcile-run.d.ts +0 -62
- package/dist/runtime/reconcile-run.d.ts.map +0 -1
- package/dist/runtime/reconcile-run.js +0 -173
- package/dist/runtime/reconcile-run.js.map +0 -1
- package/dist/scanners/external/scaffold/ctx.py +0 -78
- package/dist/scanners/external/scaffold/requirements.txt +0 -11
- package/dist/scanners/external/scaffold/senpi_mcp.py +0 -250
- package/dist/scanners/external/scaffold/state_manager.py +0 -175
- package/dist/utils/keyed-mutex.d.ts +0 -37
- package/dist/utils/keyed-mutex.d.ts.map +0 -1
- package/dist/utils/keyed-mutex.js +0 -77
- package/dist/utils/keyed-mutex.js.map +0 -1
- package/examples/strategies/iguana/README.md +0 -135
- package/examples/strategies/iguana/recipe.yaml +0 -137
- package/examples/strategies/iguana/scanners/scan.py +0 -243
- package/examples/strategies/iguana/scanners/scoring.py +0 -152
- package/examples/strategies/raptor/README.md +0 -156
- package/examples/strategies/raptor/recipe.yaml +0 -154
- package/examples/strategies/raptor/scanners/scan.py +0 -349
- package/examples/strategies/raptor/scanners/scoring.py +0 -452
- package/examples/strategies/spider/README.md +0 -97
- package/examples/strategies/spider/scalp/recipe.yaml +0 -129
- package/examples/strategies/spider/scalp/scanners/scan.py +0 -219
- package/examples/strategies/spider/scalp/scanners/scoring.py +0 -179
- package/examples/strategies/spider/swing/recipe.yaml +0 -141
- package/examples/strategies/spider/swing/scanners/scan.py +0 -334
- package/examples/strategies/spider/swing/scanners/scoring.py +0 -184
- package/examples/strategies/turbine/README.md +0 -167
- package/examples/strategies/turbine/recipe-runners.yaml +0 -123
- package/examples/strategies/turbine/recipe-volume.yaml +0 -129
- package/examples/strategies/turbine/scanners/scan.py +0 -283
- package/examples/strategies/turbine/scanners/scoring.py +0 -190
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
"""TURBINE — pure rotation/direction/spread functions (port of turbine-producer.py v3.2.2).
|
|
2
|
-
|
|
3
|
-
Ported VERBATIM from senpi-skills/turbine/scripts/turbine-producer.py (choose_direction,
|
|
4
|
-
pick_rotation_asset, spread parsing) and turbine_config.py (normalize_coin_key). No I/O, no
|
|
5
|
-
MCP, no daemon — pure and unit-testable. `scan.py` fetches per-asset market data via
|
|
6
|
-
ctx.senpi_mcp and hands it to these helpers.
|
|
7
|
-
|
|
8
|
-
Both turbine legs (volume + runners) share THIS scoring module: the source ran the identical
|
|
9
|
-
volume-rotation alpha on both wallets and let the wallet boundary (DSL preset + sizing) select
|
|
10
|
-
behavior. So there is no per-leg branch here — only sizing/exit differ, and those live in the
|
|
11
|
-
recipe YAMLs, not in the signal logic.
|
|
12
|
-
|
|
13
|
-
Source thresholds preserved exactly:
|
|
14
|
-
- Universe MAIN = [BTC, ETH, SOL, HYPE]; XYZ = [xyz:BRENTOIL, xyz:GOLD, xyz:SPX].
|
|
15
|
-
- Direction = funding fade: LONG_CROWDED/LONG_HEAVY -> SHORT (funding_fade_short),
|
|
16
|
-
SHORT_CROWDED/SHORT_HEAVY -> LONG (funding_fade_long), else random LONG/SHORT
|
|
17
|
-
(alternate_neutral).
|
|
18
|
-
- Rotation: probabilistic pool pick (random.random() < xyz_weight -> XYZ pool, else MAIN),
|
|
19
|
-
then a deterministic rotation index inside the pool; skip held + 90s post-close cooldown;
|
|
20
|
-
fall through to the OTHER pool if the chosen one is exhausted.
|
|
21
|
-
- Spread gate: main <= spread_main_bps (3), xyz <= spread_xyz_bps (10). spread_bps from the
|
|
22
|
-
top-of-book mid: ((ask - bid) / mid) * 10000.
|
|
23
|
-
"""
|
|
24
|
-
|
|
25
|
-
import random
|
|
26
|
-
import time
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
# ── Universe (shared by both wallets) ──
|
|
30
|
-
|
|
31
|
-
VOLUME_XYZ = ["xyz:BRENTOIL", "xyz:GOLD", "xyz:SPX"]
|
|
32
|
-
VOLUME_MAIN = ["BTC", "ETH", "SOL", "HYPE"]
|
|
33
|
-
|
|
34
|
-
POST_CLOSE_COOLDOWN_SECONDS = 90
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
def is_xyz(asset):
|
|
38
|
-
return asset.startswith("xyz:")
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
def normalize_coin_key(coin):
|
|
42
|
-
"""Canonicalize a coin string for held_keys / cooldown sets.
|
|
43
|
-
|
|
44
|
-
Port of turbine_config.normalize_coin_key (v3.2.2): preserve the xyz: prefix so that
|
|
45
|
-
main:HYPE and xyz:HYPE are distinct slot occupiers. Lowercase the prefix, uppercase the
|
|
46
|
-
symbol; bare symbols are uppercased.
|
|
47
|
-
"""
|
|
48
|
-
if not coin:
|
|
49
|
-
return ""
|
|
50
|
-
s = coin.strip()
|
|
51
|
-
if ":" in s:
|
|
52
|
-
prefix, _, symbol = s.partition(":")
|
|
53
|
-
return f"{prefix.lower()}:{symbol.upper()}"
|
|
54
|
-
return s.upper()
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
def safe_float(v, d=0.0):
|
|
58
|
-
try:
|
|
59
|
-
return float(v)
|
|
60
|
-
except (TypeError, ValueError):
|
|
61
|
-
return d
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
# ── Direction: funding fade (verbatim from producer.choose_direction) ──
|
|
65
|
-
|
|
66
|
-
def choose_direction(regime, rng=random):
|
|
67
|
-
"""Funding fade. Crowded longs -> SHORT, crowded shorts -> LONG, flat -> coin flip.
|
|
68
|
-
|
|
69
|
-
Returns (direction, thesis). `rng` is injectable for deterministic tests; the source used
|
|
70
|
-
the module-level `random`.
|
|
71
|
-
"""
|
|
72
|
-
r = (regime or "").upper()
|
|
73
|
-
if r in ("LONG_CROWDED", "LONG_HEAVY"):
|
|
74
|
-
return "SHORT", "funding_fade_short"
|
|
75
|
-
if r in ("SHORT_CROWDED", "SHORT_HEAVY"):
|
|
76
|
-
return "LONG", "funding_fade_long"
|
|
77
|
-
return rng.choice(["LONG", "SHORT"]), "alternate_neutral"
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
# ── Spread parsing (verbatim from producer.query_asset_data) ──
|
|
81
|
-
|
|
82
|
-
def _lvl_px(lvl):
|
|
83
|
-
if isinstance(lvl, dict):
|
|
84
|
-
return safe_float(lvl.get("px", lvl.get("price", 0)))
|
|
85
|
-
if isinstance(lvl, list) and lvl:
|
|
86
|
-
return safe_float(lvl[0])
|
|
87
|
-
return 0.0
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
def parse_asset_data(resp):
|
|
91
|
-
"""Extract bid/ask/mid/spread_bps + funding regime from a market_get_asset_data response.
|
|
92
|
-
|
|
93
|
-
Returns a dict or None when the order book is missing / one-sided / non-positive (the
|
|
94
|
-
source treated all of these as 'skip this asset'). Mirrors producer.query_asset_data
|
|
95
|
-
exactly: top-of-book levels, mid = (bid+ask)/2, spread_bps = ((ask-bid)/mid)*10000.
|
|
96
|
-
"""
|
|
97
|
-
if not resp or not isinstance(resp, dict):
|
|
98
|
-
return None
|
|
99
|
-
ad = resp.get("data", resp)
|
|
100
|
-
if not isinstance(ad, dict):
|
|
101
|
-
return None
|
|
102
|
-
ob = ad.get("order_book") or ad.get("orderBook") or {}
|
|
103
|
-
levels = ob.get("levels", [])
|
|
104
|
-
if not isinstance(levels, list) or len(levels) < 2:
|
|
105
|
-
return None
|
|
106
|
-
bids, asks = levels[0], levels[1]
|
|
107
|
-
if not bids or not asks:
|
|
108
|
-
return None
|
|
109
|
-
bid = _lvl_px(bids[0])
|
|
110
|
-
ask = _lvl_px(asks[0])
|
|
111
|
-
if bid <= 0 or ask <= 0:
|
|
112
|
-
return None
|
|
113
|
-
mid = (bid + ask) / 2.0
|
|
114
|
-
spread_bps = ((ask - bid) / mid) * 10000 if mid > 0 else 999
|
|
115
|
-
|
|
116
|
-
funding_regime = (
|
|
117
|
-
ad.get("funding_regime") or ad.get("fundingRegime") or "UNKNOWN"
|
|
118
|
-
).upper()
|
|
119
|
-
funding_annualized_pct = safe_float(
|
|
120
|
-
ad.get("funding_annualized_pct") or ad.get("fundingAnnualizedPct") or 0
|
|
121
|
-
)
|
|
122
|
-
return {
|
|
123
|
-
"bid": bid,
|
|
124
|
-
"ask": ask,
|
|
125
|
-
"mid": mid,
|
|
126
|
-
"spread_bps": round(spread_bps, 3),
|
|
127
|
-
"funding_regime": funding_regime,
|
|
128
|
-
"funding_annualized_pct": funding_annualized_pct,
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
def spread_ok(asset, spread_bps, spread_main_bps, spread_xyz_bps):
|
|
133
|
-
"""Spread gate: xyz assets get the wider xyz cap, everything else the main cap."""
|
|
134
|
-
max_spread = spread_xyz_bps if is_xyz(asset) else spread_main_bps
|
|
135
|
-
return spread_bps <= max_spread
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
# ── Rotation pick (verbatim from producer.pick_rotation_asset) ──
|
|
139
|
-
|
|
140
|
-
def pick_rotation_asset(rot_idx, xyz_weight, held_set, last_closed, now=None, rng=random):
|
|
141
|
-
"""Pick the next rotation asset.
|
|
142
|
-
|
|
143
|
-
Probabilistic pool pick (random.random() < xyz_weight -> XYZ pool, else MAIN) + a
|
|
144
|
-
deterministic rotation index inside the chosen pool. Skips assets already held and assets
|
|
145
|
-
closed within POST_CLOSE_COOLDOWN_SECONDS (90s). Falls through to the OTHER pool if the
|
|
146
|
-
chosen one is exhausted. Returns (asset|None, new_rot_idx).
|
|
147
|
-
|
|
148
|
-
`now`/`rng` are injectable for deterministic tests; the source used time.time() / random.
|
|
149
|
-
"""
|
|
150
|
-
if now is None:
|
|
151
|
-
now = time.time()
|
|
152
|
-
|
|
153
|
-
def _try_pool(pool, idx):
|
|
154
|
-
n = len(pool)
|
|
155
|
-
for _ in range(n):
|
|
156
|
-
candidate = pool[idx % n]
|
|
157
|
-
idx = (idx + 1) % n
|
|
158
|
-
coin_key = normalize_coin_key(candidate)
|
|
159
|
-
if coin_key in held_set:
|
|
160
|
-
continue
|
|
161
|
-
last = last_closed.get(coin_key, {})
|
|
162
|
-
if last and (now - last.get("ts", 0)) < POST_CLOSE_COOLDOWN_SECONDS:
|
|
163
|
-
continue
|
|
164
|
-
return candidate, idx
|
|
165
|
-
return None, idx
|
|
166
|
-
|
|
167
|
-
use_xyz = rng.random() < xyz_weight
|
|
168
|
-
pool = VOLUME_XYZ if use_xyz else VOLUME_MAIN
|
|
169
|
-
asset, rot_idx = _try_pool(pool, rot_idx)
|
|
170
|
-
if asset is not None:
|
|
171
|
-
return asset, rot_idx
|
|
172
|
-
|
|
173
|
-
other = VOLUME_MAIN if use_xyz else VOLUME_XYZ
|
|
174
|
-
asset, rot_idx = _try_pool(other, rot_idx)
|
|
175
|
-
return asset, rot_idx
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
def clamp_leverage(desired, venue_max):
|
|
179
|
-
"""Clamp desired leverage to the asset's Hyperliquid venue max.
|
|
180
|
-
|
|
181
|
-
Turbine's source used a fixed 5x and relied on the runtime to clamp per-asset. We carry the
|
|
182
|
-
same defensive clamp the spider port uses so a low-venue-cap asset never over-levers.
|
|
183
|
-
"""
|
|
184
|
-
try:
|
|
185
|
-
venue = int(venue_max)
|
|
186
|
-
except (TypeError, ValueError):
|
|
187
|
-
venue = desired
|
|
188
|
-
if venue <= 0:
|
|
189
|
-
venue = desired
|
|
190
|
-
return max(1, min(int(desired), venue))
|