namespace BlueLaminate.Core.Options; /// /// Which StatTrak universes the finder searches. The two input pools are disjoint and /// never mix in a contract: non-ST inputs (normal ∪ souvenir) produce a normal output, /// ST inputs produce an ST output. /// public enum StatTrakMode { /// Search both the non-ST and ST universes (default). Both, /// Only the non-ST universe (normal + souvenir inputs → normal output). NonStatTrakOnly, /// Only the StatTrak universe (ST inputs → ST output). StatTrakOnly, } /// /// How to rank surviving candidates. /// public enum TradeupRanking { /// By worst-case (minimum across outputs) net profit — low variance. WorstCaseProfit, /// By expected net profit across the output distribution. ExpectedProfit, } /// /// Tuning for the tradeup finder, bound from the Tradeups configuration section. /// Defaults are sensible for CS2 marketplaces (15% sell fee) and a conservative v1 /// (guaranteed-profit only). Everything here is economics/policy — none of it lives in /// the CLI. /// public sealed class TradeupOptions { public const string SectionName = "Tradeups"; /// Number of inputs per contract. v1 supports 10-input weapon tradeups only. public int ContractSize { get; set; } = 10; /// /// Fraction of the sale price taken as marketplace commission when selling an output /// (0.15 = 15%). Applied to the realised sell price. /// public decimal SellFeeRate { get; set; } = 0.15m; /// /// Fraction shaved off the lowest active ask to model undercutting it for a quick /// sale (0.01 = list 1% under the cheapest competitor). Applied before the fee. /// public decimal UndercutRate { get; set; } = 0.01m; /// /// Bucket width used to discretise normalised input fractions for the /// cardinality-constrained selection DP. Smaller = finer output-float resolution at /// higher cost. 0.005 resolves the wear boundaries to within 0.005 of output float. /// public decimal FractionBucket { get; set; } = 0.005m; /// /// When true (v1 default) only contracts whose worst-case output still clears input /// cost survive — a guaranteed profit. When false, any positive-EV contract survives. /// public bool GuaranteedOnly { get; set; } = true; /// Minimum net profit (in the listing currency) for a candidate to be reported. public decimal MinProfit { get; set; } = 0m; /// How surviving candidates are ordered. public TradeupRanking Ranking { get; set; } = TradeupRanking.WorstCaseProfit; /// Which StatTrak universes to search. public StatTrakMode StatTrak { get; set; } = StatTrakMode.Both; /// /// Currency listings must be in to be comparable. The finder ignores listings in /// other currencies rather than converting (v1 keeps a single money space). /// public string Currency { get; set; } = "USD"; /// /// When a proposed output has fewer than this many active listings in our data, its /// stored lowest-ask is fragile, so the finder re-prices it from the live CSFloat API. /// public int CsFloatThinOutputThreshold { get; set; } = 10; /// /// Enables the live CSFloat re-pricing of thin outputs. Silently inert when no CSFloat /// API key is configured. /// public bool UseCsFloatForThinOutputs { get; set; } = true; /// /// Hard cap on live CSFloat lookups per search, so the re-pricing pass can't blow the /// API rate-limit budget. Distinct (skin, ST, wear band) lookups are cached within a run. /// public int CsFloatMaxLookups { get; set; } = 120; /// /// Enables the multi-collection search: alongside the single-collection pass, it mixes /// inputs from any collections at a rarity tier to maximise expected profit. Off keeps the /// finder single-collection only. /// public bool MultiCollection { get; set; } = true; /// /// Step of the output-float target grid the multi-collection search sweeps. Each grid /// point is an independent, parallelised chunk (one knapsack over the tier's pool), so a /// finer grid is more thorough but does more work. 0.02 ≈ 50 chunks per tier × ST. /// public decimal MultiCollectionFloatGrid { get; set; } = 0.02m; /// /// How many distinct multi-collection contracts to keep per (rarity tier, StatTrak), best /// expected-profit first, after de-duplicating by collection mix. Caps result volume. /// public int MultiCollectionPerTier { get; set; } = 8; }