-
Notifications
You must be signed in to change notification settings - Fork 2
Radius Scan
Radius Scan is the core Flipper mode:
- buy from sell orders in a buy-side radius,
- sell into buy orders in a sell-side radius,
- rank and filter opportunities with fee-aware and depth-aware math.
This mode is for fast inter-system flips.
Same-location maker trading is handled by Station Trading.
If you need a practical setup walkthrough with examples, see:
POST /api/scan- streamed NDJSON response:
- progress messages
- final
resultpayload with rows +cache_meta
Request is parsed through parseScanParams, then executed by scanner.Scan(...).
Input scope parameters:
-
system_name(anchor) buy_radiussell_radius-
min_route_security(0,0.45,0.5,0.7) ignored_system_ids
Engine builds two system envelopes:
- buy-side systems (where sell orders are sourced)
- sell-side systems (where buy orders are sourced)
Ignored systems are removed from both envelopes before scanning.
If either side becomes empty, scan returns no rows.
Scanner derives region sets from the two system envelopes, then starts parallel streams:
- source sell orders:
-
FetchRegionOrders(region, "sell")filtered to buy-side systems
-
- destination buy orders:
-
FetchRegionOrders(region, "buy")filtered to sell-side systems
-
- destination sell orders:
- extra sell-book fetch for S2B/BfS split consistency
If include_structures=true and access token exists:
- scanner also discovers source-side structure IDs
- fetches private structure sell orders via
FetchStructureOrders - merges them into source sell book (deduplicated by
orderID)
For each type:
- keep cheapest sell per source location (plus depth/count info)
- keep highest buy per destination location (plus depth/count info)
This collapses large raw orderbooks into location-level best candidates.
Fee multipliers:
buyCostMult = 1 + (buyBroker + buyTax)/100
sellRevenueMult = 1 - (sellBroker + sellTax)/100
Unified mode:
- buy side: broker only
- sell side: broker + sales tax
Split mode:
- explicit buy/sell broker and buy/sell tax fields
Per-unit economics:
effectiveBuyPrice = sellPrice * buyCostMult
effectiveSellPrice = buyPrice * sellRevenueMult
profitPerUnit = effectiveSellPrice - effectiveBuyPrice
margin = profitPerUnit / effectiveBuyPrice * 100
Pairs are rejected if:
- non-positive profit
- margin below
min_margin - same location
- target marketplace constraints (if set) not matched
Initial units are constrained by:
- cargo (
floor(cargo_capacity / item_volume)) - source depth (
sell.VolumeRemain) - destination depth (
buy.VolumeRemain) -
max_investment(floor(max_investment / effectiveBuyPrice))
Route checks:
- origin -> buy system
- buy system -> sell system
Pathing uses security-aware shortest path.
Unreachable routes are dropped.
Row jump metrics:
BuyJumpsSellJumpsTotalJumpsProfitPerJump
Dedup key:
(typeID, buyLocationID, sellLocationID)
For duplicate keys, row with higher TotalProfit is kept.
Before heavy enrichment:
- results sorted by
TotalProfitdesc - capped to
MaxUnlimitedResults = 5000
Scanner runs depth simulation on exact buy/sell locations:
- computes expected fill prices from orderbook depth
- finds largest profitable executable quantity (
findSafeExecutionQuantity)
If safe qty is zero, row is removed.
If safe qty is smaller than requested:
-
UnitsToBuyis reduced -
TotalProfit/ProfitPerJumpare recomputed
Execution fields filled:
-
ExpectedBuyPrice,ExpectedSellPrice -
ExpectedProfit,RealProfit -
FilledQty,CanFill -
SlippageBuyPct,SlippageSellPct RealMarginPercent
Rows are then re-sorted by RealProfit (depth-aware KPI).
After enrichment:
- station names are prefetched and resolved
- unresolved location IDs fallback to
Structure @ <system>
Server-side post handling:
- if
include_structures=false, structure rows are removed - market-disabled item types are always removed
When structure name resolution via auth fails for specific structures, unresolved entries can be filtered out.
For each row, history is fetched for sell-side region + type:
-
DailyVolume(7-day average) -
Velocity(daily_volume / listed_quantity) -
PriceTrend(Theil-Sen based 7-day trend) HistoryAvailable
From history volume and destination book depth:
S2BPerDayBfSPerDayS2BBfSRatio
Split model enforces mass balance:
S2BPerDay + BfSPerDay = DailyVolume
Daily executable throughput is bounded by both sides:
sellablePerDay = min(UnitsToBuy, S2BPerDay, BfSPerDay)
Daily profit:
- uses execution-aware per-unit profit when available
- falls back to top-book
ProfitPerUnitotherwise
If any history-dependent filter is active, rows without history are dropped.
Applied filters:
min_daily_volumemin_s2b_per_daymin_bfs_per_daymin_s2b_bfs_ratiomax_s2b_bfs_ratio
Final payload is returned to API handler, then persisted to scan history and used for watchlist alert checks.
Main fields:
SystemCargo m3Buy RadiusSell RadiusMin Margin
Fees:
- unified fees (
sales_tax_percent,broker_fee_percent) - split fees (
buy_*,sell_*) -
Fetch from ESIbutton can auto-fill fees from character trade skills
Structures and blacklist:
-
Include Structurestoggle - system blacklist button (
ignored_system_ids)
Advanced panel:
min_route_securitymin_daily_volumemax_investmentmin_s2b_per_daymin_bfs_per_daymin_s2b_bfs_ratiomax_s2b_bfs_ratio
Built-in flipper presets:
- conservative
- normal
- aggressive
Preset behavior:
- tab-scoped
- user-bound fields like
ignored_system_idsare not imported from shared presets
Radius tab has auto-refresh toggle.
Logic:
- checks cache every 15s
- rescans only when
next_expiry_atis reached - cooldown prevents loop spam on unchanged stale snapshot (90s)
Table shows:
- cache badge countdown
- stale marker
- reboot cache button
Reboot cache clears order cache and asks user to rescan.
Radius results support:
- sorting
- per-column filters
- group by item
- column show/hide + reordering (persisted)
- CSV export
- copy table
- pinned rows
- hidden rows manager (
done/ignored, persisted in backend) - context menu actions
Context menu includes:
- copy item/stations/route
- open external market links
- add/remove watchlist
- execution planner popup
- build batch popup
- in-game actions (when logged in): open market, set waypoint
Batch Builder:
- takes one route as anchor (same buy/sell route)
- fills cargo using highest ISK/m3 candidates first
- supports finite cargo or unlimited mode
- can copy manifest text to clipboard
{
"system_name": "Jita",
"ignored_system_ids": [],
"cargo_capacity": 5000,
"buy_radius": 5,
"sell_radius": 10,
"min_margin": 5,
"sales_tax_percent": 8,
"broker_fee_percent": 3,
"split_trade_fees": false,
"min_daily_volume": 0,
"max_investment": 0,
"min_s2b_per_day": 0,
"min_bfs_per_day": 0,
"min_s2b_bfs_ratio": 0,
"max_s2b_bfs_ratio": 0,
"min_route_security": 0.45,
"include_structures": false
}-
min_marginis enforced on execution-aware margin, not only top-book spread. -
RealProfitis the primary depth-aware value;TotalProfitcan be optimistic. -
DailyProfitis throughput-limited by both side flows (min(S2B, BfS)). - Structure support is best with ESI login because private structure data and names require auth.
- 🏠 Home
- 📘 Getting Started
- ⚙️ Configuration
- 🎨 Theme System