[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-80731":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":9,"language":10,"languages":9,"totalLinesOfCode":9,"stars":11,"forks":12,"watchers":13,"openIssues":14,"contributorsCount":14,"subscribersCount":14,"size":14,"stars1d":14,"stars7d":15,"stars30d":16,"stars90d":14,"forks30d":14,"starsTrendScore":14,"compositeScore":17,"rankGlobal":9,"rankLanguage":9,"license":9,"archived":18,"fork":18,"defaultBranch":19,"hasWiki":20,"hasPages":18,"topics":21,"createdAt":9,"pushedAt":9,"updatedAt":22,"readmeContent":23,"aiSummary":24,"trendingCount":14,"starSnapshotCount":14,"syncStatus":15,"lastSyncTime":25,"discoverSource":26},80731,"imc-prosperity-4","Durpie-Git\u002Fimc-prosperity-4","Durpie-Git","Here are our insights and strategies from IMC Prosperity 4! We were #4 Globally and #1 Europe from 18,803 teams.",null,"Python",46,9,1,0,2,3,41.3,false,"main",true,[],"2026-06-12 04:01:29","![Team Banner](Figures\u002Fteam_banner.png)\n\n# Une Baguette Fromage 🥖🧀\n\nThis write-up shares the strategies, research, and infrastructure that brought us to **🏆 4th place globally and 🏆 1st place in Europe** out of 18,803 teams in **IMC Prosperity 4 (2026)**, a 5-round international quantitative trading competition with both algorithmic and manual challenges. Overall, our team was awarded **$3,500 prize money** for top performance and achieved a final PnL score of **1,386,318 XIREC**.\n\n\u003Ctable align=\"center\">\n  \u003Ctbody>\n    \u003Ctr>\n      \u003Ctd align=\"center\" valign=\"top\" width=\"200\">\n        \u003Ca href=\"https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fjasper-van-der-ende\u002F\">\n          \u003Cimg src=\"Figures\u002FJasper_pfp.jpg\" width=\"150\" alt=\"Jasper van der Ende\"\u002F>\n        \u003C\u002Fa>\n        \u003Cbr \u002F>\n        \u003Cp>\u003Cb>\u003Ca href=\"https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fjasper-van-der-ende\u002F\">Jasper van der Ende\u003C\u002Fa>\u003C\u002Fb>\u003C\u002Fp>\n      \u003C\u002Ftd>\n      \u003Ctd align=\"center\" valign=\"top\" width=\"200\">\n        \u003Ca href=\"https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fteun-schuur-1b0b29270\u002F\">\n          \u003Cimg src=\"Figures\u002FTeun_pfp.jpg\" width=\"150\" alt=\"Teun Schuur\"\u002F>\n        \u003C\u002Fa>\n        \u003Cbr \u002F>\n        \u003Cp>\u003Cb>\u003Ca href=\"https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fteun-schuur-1b0b29270\u002F\">Teun Schuur\u003C\u002Fa>\u003C\u002Fb>\u003C\u002Fp>\n      \u003C\u002Ftd>\n      \u003Ctd align=\"center\" valign=\"top\" width=\"200\">\n        \u003Ca href=\"https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fthomas-stges\u002F\">\n          \u003Cimg src=\"Figures\u002FThomas_pfp.jpg\" width=\"150\" alt=\"Thomas St Ges\"\u002F>\n        \u003C\u002Fa>\n        \u003Cbr \u002F>\n        \u003Cp>\u003Cb>\u003Ca href=\"https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fthomas-stges\u002F\">Thomas St Ges\u003C\u002Fa>\u003C\u002Fb>\u003C\u002Fp>\n      \u003C\u002Ftd>\n    \u003C\u002Ftr>\n  \u003C\u002Ftbody>\n\u003C\u002Ftable>\n\n\u003Ctable align=\"center\">\n  \u003Ctbody>\n    \u003Ctr>\n      \u003Ctd align=\"center\" valign=\"top\" width=\"200\">\n        \u003Ca href=\"https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fguilhem-doat-25bb66356\u002F\">\n          \u003Cimg src=\"Figures\u002FGuilhem_pfp2.jpg\" width=\"150\" alt=\"Guilhem Doat\"\u002F>\n        \u003C\u002Fa>\n        \u003Cbr \u002F>\n        \u003Cp>\u003Cb>\u003Ca href=\"https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fguilhem-doat-25bb66356\u002F\">Guilhem Doat\u003C\u002Fa>\u003C\u002Fb>\u003C\u002Fp>\n      \u003C\u002Ftd>\n      \u003Ctd align=\"center\" valign=\"top\" width=\"200\">\n        \u003Ca href=\"https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fdylan-c-6164b5323\u002F\">\n          \u003Cimg src=\"Figures\u002FDylan_pfp.jpg\" width=\"150\" alt=\"Dylan Conrad\"\u002F>\n        \u003C\u002Fa>\n        \u003Cbr \u002F>\n        \u003Cp>\u003Cb>\u003Ca href=\"https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fdylan-c-6164b5323\u002F\">Dylan Conrad\u003C\u002Fa>\u003C\u002Fb>\u003C\u002Fp>\n      \u003C\u002Ftd>\n    \u003C\u002Ftr>\n  \u003C\u002Ftbody>\n\u003C\u002Ftable>\n\n\u003Cbr\u002F>\n\nAs many top-performing teams from previous Prosperity iterations have done, we decided to publish this writeup to give back to the Prosperity community.\n\nWe believe Prosperity is one of the rare competitions where sharing approaches genuinely raises the bar for everyone. Every public writeup forces future participants — and IMC itself — to push the limits further. Previous teams’ writeups helped us tremendously during the competition, so this document is our attempt to continue that cycle.\n\nThat said, getting to the top was not just about getting lucky and finding a magical strategy. We systematically tested every possibility we could think of, building our own understanding of the markets IMC had created instead of blindly applying textbook techniques.\n\nOur goal with this document is not only to explain what worked, but also:\n- how we approached research,\n- how we validated ideas,\n- how we avoided overfitting,\n- and how we navigated an absurdly large search space under extreme time pressure.\n\n\u003Cbr\u002F>\n\n## IMC Prosperity 4\n\n![Team Banner](Figures\u002Fdashboard.png)\n\nIMC Prosperity 4 (2026) was a global quantitative trading competition held over five rounds across a two-week period, with more than 30,000 university students participating worldwide across nearly 19,000 teams.\n\nParticipants built trading algorithms to maximize profit in simulated securities and commodities markets populated by bots, market frictions, and hidden behavioral patterns. Across the competition, new products, mechanics, and sources of market structure were introduced each round, requiring teams to continuously adapt their strategies, models, and research workflows. In total, 64 products were traded throughout the competition, with 50 active in the final round alone.\n\nEach round also included a separate manual trading challenge focused on probabilistic reasoning, optimization, and strategic decision-making in uncertain, adversarial environments.\n\nThe competition covered a wide range of topics across quantitative trading and research, including:\n- market making,\n- statistical arbitrage,\n- microstructure analysis,\n- derivatives pricing,\n- signal extraction,\n- event-driven trading,\n- optimization,\n- simulation,\n- and game theory.\n\n\u003Cbr\u002F>\n\n## Structural Overview\n\n- [Tools & Infrastructure](#tools--infrastructure)\n- [Wall Mid](#wall-mid)\n- [On Vibe Coding](#on-vibe-coding)\n- [Algorithmic Challenge](#algorithmic-challenge)\n  - [Round 1](#round-1)\n  - [Round 2](#round-2)\n  - [Round 3](#round-3)\n  - [Round 4](#round-4)\n  - [Round 5](#round-5)\n- [Manual Challenge](#manual-challenge)\n  - [Round 1](#manual-round-1)\n  - [Round 2](#manual-round-2)\n  - [Round 3](#manual-round-3)\n  - [Round 4](#manual-round-4)\n  - [Round 5](#manual-round-5)\n- [FAQ](#faq)\n\n\u003Cbr\u002F>\n\n# Tools & Infrastructure\n\nOne of our earliest decisions was to make sure we did not rely solely on the native IMC website tester, as this was very slow processing and represented evaluation on only the first 10% of the most recent day's sample data, which could thus be very misleading (perhaps sometimes by design).\n\nInstead, we forked and heavily extended Jmerle's \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fjmerle\u002Fimc-prosperity-3-backtester\"> backtester\u003C\u002Fa> and \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fjmerle\u002Fimc-prosperity-3-visualizer\">visualizer\u003C\u002Fa> from IMC Prosperity 3.\n\nHaving a proper local environment was absolutely essential for us, especially because the round timers were brutal:\n- 72 hours per round during qualifications\n- 48 hours per round during finals\n\nThis leaves very little room for slow feedback loops.\n\nThe backtester gave us:\n- evaluation on multiple days of sample data,\n- local exchange simulation,\n- position limits,\n- fair value updates,\n- trader replay,\n- and rapid parameter testing\n\nwithout needing to constantly submit to the official platform.\n\nBeing able to run dozens of local simulations in minutes instead of waiting on the website queue was a massive advantage.\n\n\u003Cbr\u002F>\n\n## Dashboard\n\nOn top of the core backtester, we built a heavily customized dashboard environment.\n\n\u003Ctable>\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cstrong>Figure 1: Dashboard Overview\u003C\u002Fstrong>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cimg src=\"Figures\u002Fzoomed_out_dashboard.png\"\n       alt=\"Dashboard\"\n       width=\"100%\" \u002F>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cstrong>Figure 2: Analyzer Overview\u003C\u002Fstrong>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cimg src=\"Figures\u002Fanalysis_dashboard.png\"\n       alt=\"Analysis Dashboard\"\n       width=\"100%\" \u002F>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cem>Overview of the custom visualization dashboard used throughout the competition.\u003C\u002Fem>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftable>\n\nKey additions included:\n- Price and mid-price charts with fair value overlays\n- Volume profiles per product and timestamp\n- PnL attribution broken down per product\n- Visualization of counterparty trades\n- Position tracking over time\n- Dynamic graphing support for arbitrary indicators\n\nThe dashboard became one of our most important research tools throughout the competition.\n\nWe used it constantly for:\n- validating hypotheses,\n- spotting hidden behaviors,\n- understanding microstructure,\n- and debugging strategies.\n\n\u003Cbr\u002F>\n\n## Jupyter Workflow\n\nAlongside the dashboard, we relied heavily on Jupyter notebooks.\n\nThe notebooks acted as our scratchpad for:\n- exploratory analysis,\n- signal research,\n- residual analysis,\n- autocorrelation testing,\n- parameter optimization,\n- and visualization.\n\nWe found the separation between:\n- notebooks for fast experimentation,\n- and the dashboard for validation\n\nto be extremely effective.\n\n\u003Cbr\u002F>\n\n## Git Workflow\n\nWe also maintained a lightweight git branching structure.\n\nEach product family had its own branch, while the main branch only received tested competition-ready code.\n\nThis prevented the classic Prosperity failure mode:\nfixing one product at 3AM and accidentally breaking another one.\n\nVersion discipline ended up saving us repeatedly during later rounds.\n\n\u003Cbr\u002F>\n\n## A Note on Backtester Limitations\n\nOne thing we want to stress:\n\nLocal backtesting has real structural limitations.\n\nIgnoring them leads directly to overfit strategies that look incredible locally and collapse live.\n\nThe most important limitations we encountered were:\n- No market impact\n- Simplified orderbook dynamics\n- Imperfect bot behavior replication\n\nOur philosophy became:\n\n> Use the backtester as a filter, not as ground truth.\n\nIf a strategy failed locally, we discarded it.\n\nIf it passed locally, we still questioned it aggressively before trusting it live.\n\nStrategies with absurdly good backtests were usually overfit.\n\n\u003Cbr\u002F>\n\n# Wall Mid\n\nOne of the most important concepts throughout the competition was what we called the **Wall Mid**, originating from the IMC Prosperity 3 second-ranking team the [Frankfurt Hedgehogs](https:\u002F\u002Fgithub.com\u002FTimoDiehm\u002Fimc-prosperity-3).\n\nThe standard midpoint between best bid and best ask was often a terrible estimate of actual fair value.\n\nThis was because:\n- bots aggressively overbid,\n- undercutting constantly occurred,\n- and top-of-book prices were noisy.\n\nDuring testing on the official Prosperity platform, it became possible to indirectly infer the underlying fair value through unrealized PnL changes.\n\nBuying or selling tiny amounts and observing resulting PnL changes gave clues about where the simulator itself considered fair value to be.\n\nWe found that the best estimate consistently came from large persistent liquidity walls deeper in the book.\n\nThese walls:\n- remained stable,\n- appeared highly informed,\n- and often anchored around the simulator’s internal fair value.\n\nSo instead of using the naive midpoint, we:\n1. identified dominant liquidity walls,\n2. extracted bid and ask wall prices,\n3. and took the midpoint between those levels.\n\nThis produced a significantly cleaner and more predictive estimate of fair value.\n\n\u003Ctable>\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cstrong>Figure 3: Wall Mid vs Raw Mid (Ash-Coated Osmium)\u003C\u002Fstrong>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cimg src=\"Figures\u002Fash-coated-osmium-wallmid.png\"\n       alt=\"Wall Mid\"\n       width=\"100%\" \u002F>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cem>Comparison between noisy top-of-book midpoint and Wall Mid estimation.\u003C\u002Fem>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftable>\n\n\u003Cbr\u002F>\n\n# On Vibe Coding\n\nWe want to be honest about something that rarely makes it into writeups:\n\nA significant portion of our tooling and research was built through what the community now calls **vibe coding**.\n\nFast, iterative, heavily AI-assisted development became one of the most important tools during the competition.\n\nIn a competition like Prosperity, you simply cannot afford to spend:\n- six hours architecting perfect pipelines,\n- writing elegant abstractions,\n- or polishing infrastructure\n\nwhen there are only 30 hours left in a round.\n\nThe correct move is often:\n1. get something working quickly,\n2. validate the idea,\n3. then decide whether it deserves cleanup.\n\nConcretely, this included:\n- rapidly prototyping parsers,\n- building one-off scanners,\n- dynamically extending the dashboard,\n- generating parameter sweep harnesses,\n- and quickly validating statistical ideas.\n\nThe key discipline is knowing:\n- when AI-generated code is acceptable,\n- and when every line must be manually verified.\n\nWe kept a strict separation:\n- exploratory tooling could be messy,\n- production strategy code had to be understood completely.\n\nUsed correctly, vibe coding became an enormous force multiplier.\n\n\u003Cbr\u002F>\n\n# Algorithmic Challenge\n\n## Round 1\n\nRound 1 introduced two products, both with max position 80.\n\n### OSMIUM\n\nThe first product introduced was ASH_COATED_OSMIUM, which we simply called OSMIUM.\n\nOSMIUM was essentially:\n- large spread,\n- slowly mean reverting,\n- occasionally crossing the Wall Mid,\n- and highly suitable for market making.\n\nAfter a quick Augmented Dickey-Fuller test, we confirmed that it was stationary around approximately 10,000, with p-value below 0.0005.\n\n\u003Ctable>\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cstrong>Figure 4: OSMIUM Orderbook\u003C\u002Fstrong>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cimg src=\"Figures\u002Fash-coated-osmium-market.png\"\n       alt=\"OSMIUM\"\n       width=\"100%\" \u002F>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cem>Typical OSMIUM orderbook behavior.\u003C\u002Fem>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftable>\n\n#### Empty Book Behavior\n\nOne of the first major discoveries was what happened when one side of the book became empty; When quoting on an empty side, sometimes a taker showed up that took your quote.\n\nThis happened roughly 8% of the time, on both products.\n\nWe tested increasingly aggressive quotes and discovered that a spread of exactly 100 around previous Wall Mid maximized profitability while still getting filled.\n\nUsing rough averages:\n- trade frequency around 0.047,\n- average trade size around 5,\n- and captured spread around 100,\n\nthis gave about 23 expected PnL per empty-side event.\n\nOver a full day, that translated into roughly 18.6k expected PnL for OSMIUM alone.\n\n#### Final Strategy\n\nOur OSMIUM strategy became a relatively standard Avellaneda-Stoikov style market maker with inventory management.\n\nThe reserve price shifted linearly with inventory:\n\nS_r = 10000 - γQ\n\nwhere:\n- Q = inventory\n- γ controlled inventory pull strength\n\nWe found γ = 1\u002F12 to perform best.\n\nThe strategy:\n- penny quoted around fair value,\n- crossed spread when sufficiently favorable,\n- and widened aggressively when one side became empty.\n\nMore concretely, we used an inventory-adjusted reserve price of the form\n\nS_r = 10000 - gamma * Q\n\nwith gamma = 1\u002F12, so the adjustment at max inventory was roughly 6.7.\n\nWhen one side of the order book disappeared, we did not use the full width of 100 in production.\n\nInstead, we quoted a spread of 98 around Wall Mid as a small safety margin against Wall Mid estimation error.\n\n\u003Cbr\u002F>\n\n### INTARIAN_PEPPER_ROOT\n\nThe second asset was INTARIAN_PEPPER_ROOT, which we called PEPPER_ROOT.\n\nUnlike OSMIUM, it increased almost deterministically by 0.1 every tick.\n\n\u003Ctable>\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cstrong>Figure 5: PEPPER_ROOT Orderbook\u003C\u002Fstrong>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cimg src=\"Figures\u002Fintarian-pepper-root-market.png\"\n       alt=\"PEPPER_ROOT\"\n       width=\"100%\" \u002F>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cem>Typical PEPPER_ROOT orderbook behavior.\u003C\u002Fem>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftable>\n\nThe obvious strategy was:\n> buy and hold\n\nHowever, the average spread was around 14, which was too attractive to ignore for market making.\n\nThe problem was that market making a deterministically drifting product is less trivial than it first appears.\n\n#### Dynamic Programming Model\n\nFor Round 1, we modeled PEPPER_ROOT with dynamic programming.\n\nThe idea was to compute the optimal expected future value for every:\n- time step,\n- inventory level from -80 to 80,\n- spread state,\n- and trade-size realization.\n\nThe model used:\n- deterministic drift of 0.1 per tick,\n- per-side trade rate around 0.017,\n- and an empirical trade-size distribution centered around roughly 5.14.\n\nThis produced bid and ask thresholds describing the worst prices at which quoting was still positive EV.\n\nRather than putting the full Bellman derivation inline, the compiled formulation we used is shown below.\n\n\u003Ctable>\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cstrong>Figure 6: PEPPER_ROOT Bellman Compilation\u003C\u002Fstrong>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cimg src=\"Figures\u002Fbellman_compilation.png\"\n       alt=\"PEPPER_ROOT Bellman Compilation\"\n       width=\"100%\" \u002F>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cem>Bellman setup used to derive PEPPER_ROOT quote thresholds.\u003C\u002Fem>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftable>\n\nOnce we had the value function, the strategy became simple:\n- penny the best bid or ask when the corresponding threshold allowed it,\n- market take when the threshold crossed the opposite best quote,\n- and use the same empty-book quote of spread 98 when one side disappeared.\n\nThis first approach did not work quite as well as we hoped.\n\nSo instead of using the raw thresholds directly, we introduced:\n- a bid adjustment parameter,\n- an ask adjustment parameter,\n- and optimized both with a grid search over realized PnL.\n\nThe best values were:\n- bid adjustment = 4,\n- ask adjustment = 5.\n\nThis was clearly not perfect, and we later fixed the modeling issue properly in Round 2. But it still outperformed pure buy-and-hold.\n\nMoreover, the empty-book side behavior and corresponding \"hidden taker\" strategy identified on OSMIUM applied to PEPPER_ROOT as well, reliably generating additional PnL.\n\nRound 1 closed with a cumulative score of **207,308 XIREC**, good for **🏆 8th globally overall**. On the pure algorithmic leaderboard, we scored **119,313 XIREC** and finished **🏆 8th algorithmic**.\n\n\u003Cbr\u002F>\n\n## Round 2\n\n### Extra Market Access\n\nRound 2 introduced the ability to bid for “extra market access.”\n\nIf your bid was above the median submitted bid, you received access to an expanded market feed.\n\nThe catch was that this \"extra access\" only meant:\n- roughly 20% more quotes,\n- but not 20% more trades.\n\nThis was an intentional red herring.\n\nWhy would a rational team want to PAY for more market maker competition, let alone have more market maker competition at all (even if for free)? Under such a scenario, the spread on an asset at any given time could potentially decrease with more competition (it will certainly never increase), thus we would expect to earn less PnL from market making overall since our fills would be closer to the fair value. Furthermore, empty order book sides could now potentially have quotes present under this increased market access, thus also impairing our \"hidden taker\" quoting strategy that reliably printed PnL in round 1. The only potential upside to this was more taking opportunities for us when a maker crossed the fair value; however this was calculated to be an inconsequential upside compared to the massive PnL haircut we would receive on our other trading activities.\n\nThe obvious answer became:\n> bid zero.\n\nThough, we initially wanted to bid negative infinity since we expected other rational participants to bid 0 or lower as well (we wanted to avoid extra market access no matter what; and as an added bonus, if more than 50% of players thought like us and also bid negative infinity, we thought we could all win the round with infinite PnL). However, after we inquired about this to the IMC Prosperity team, it was later publicly clarified that negative bids would default to 0.\n\nYet, following the round, the IMC Prosperity team announced that the median bid among all participants was 50. So while we fortunately did not get extra market access as we had desired, the majority of participants did not identify that this was actually a net negative and still chose to bid a positive value.\n\n\u003Cbr\u002F>\n\n### Strategy Changes\n\nThe OSMIUM strategy itself did not materially change from Round 1.\n\nHowever, Round 2 exposed a weakness in our implementation.\n\nWe had hard-coded the fair value at 10,000, and that anchor did not hold perfectly on this round's data.\n\nAs a result, we spent too much time pinned at max inventory, which weakened both:\n- the mean reversion component,\n- and the market making component.\n\nLooking back, we should have added a fail-safe:\n- if inventory stayed maxed for long enough,\n- we should have gradually shifted our assumed fair value toward the observed market mid.\n\nThere was not any hint that this could've happened though, since in the complete historical data for OSMIUM, it's fair value was always 10,000.\n\nPEPPER_ROOT changed more meaningfully.\n\nIn Round 1, our dynamic programming model still relied on \"adjustment\" parameters to compensate for hidden modeling errors.\n\nWe did not like that.\n\nSo for Round 2 we fixed the DP formulation itself by explicitly incorporating:\n- spread distributions,\n- and the arrival of large-spread takers.\n\nThis produced much cleaner bid and ask thresholds and removed the need for the earlier bid\u002Fask adjustment parameters.\n\nRound 2 closed with a cumulative score of **528,132 XIREC**, good for **🏆 4th globally overall**. On the pure algorithmic leaderboard, we scored **102,954 XIREC** and finished **🏆 14th algorithmic**. The OSMIUM underperformance still made it clear that even a good structural model needed defensive safeguards.\n\n\u003Cbr\u002F>\n\n### Recurring Takers Research\n\nDuring the intermission period following Round 2, we performed broader research into generalized alpha sources.\n\nBy that point, the admins had already announced that OSMIUM and PEPPER_ROOT would not carry forward into the remaining Phase 2 rounds.\n\nSo the goal of this research was not to squeeze the last bit of PnL out of those products.\n\nThe goal was to identify product-agnostic alpha sources that might generalize into later rounds.\n\nThis led to one of our most interesting discoveries.\n\nAcross many instances on both OSMIUM and PEPPER_ROOT, takers reappeared:\n- at identical timestamps,\n- with identical side,\n- and with identical size,\n- on consecutive days.\n\nWe eventually identified the underlying mechanism:\n\nIf a taker appeared at:\n- timestamp t\n- on day d\n\nthen there was a very high probability the same taker appeared again:\n- at timestamp t\n- on day d+1\n\nThe effect appeared to be strongly one-day dependent:\n- day d takers had strong predictive power for day d+1,\n- but much less direct predictive power for day d+2 unless the same event also appeared on day d+1.\n\nSo we modeled these transitions as a Markov-style recurrence process across products and rounds.\n\n\u003Ctable>\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"50%\" align=\"center\">\n  \u003Cstrong>Figure 7: OSMIUM Taker Recurrence\u003C\u002Fstrong>\n\u003C\u002Ftd>\n\u003Ctd width=\"50%\" align=\"center\">\n  \u003Cstrong>Figure 8: PEPPER_ROOT Taker Recurrence\u003C\u002Fstrong>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"50%\" align=\"center\">\n  \u003Cimg src=\"Figures\u002Fmarkov_chain_osmium.png\"\n       alt=\"OSMIUM Markov Chain\"\n       width=\"100%\" \u002F>\n\u003C\u002Ftd>\n\u003Ctd width=\"50%\" align=\"center\">\n  \u003Cimg src=\"Figures\u002Fmarkov_chain_pepperroot.png\"\n       alt=\"PEPPER_ROOT Markov Chain\"\n       width=\"100%\" \u002F>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" colspan=\"2\" align=\"center\">\n  \u003Cem>Recurring taker probabilities across consecutive days for OSMIUM and PEPPER_ROOT.\u003C\u002Fem>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftable>\n\nThe round-to-round difference was especially noticeable:\n- this recurring-actor behavior was very strong in Round 2,\n- and virtually non-existent in Round 1.\n\nFor OSMIUM:\n- takers with size ≥ 7\n- repeated with ~97.7% probability.\n\n#### Monetizing This\n\nAt first glance, this does not obviously look monetizable.\n\nKnowing when a taker will arrive is only useful if the matching engine lets you reshape the book first.\n\nThat is exactly what the Prosperity simulator allowed.\n\nIf we predicted a large taker would arrive:\n1. we cleared all existing liquidity,\n2. leaving one side empty,\n3. then placed an extreme quote,\n4. which the taker would often immediately hit.\n\nThis effectively recreated hidden-taker opportunities.\n\nOf course, this came with a tradeoff:\n- clearing the book imposed an immediate adverse execution cost,\n- so the expected taker fill had to be strong enough to justify it.\n\nOperationally, the decision rule was just an expected-value filter.\n\nIf:\n- c_clear = immediate cost of clearing visible liquidity\n- p_repeat = probability that the recurring taker actually reappears\n- q = expected taker size\n- edge = expected edge captured per unit when our extreme quote gets hit\n\nthen we only triggered the setup when\n\n> p_repeat * q * edge > c_clear\n\nusually with an extra buffer for inventory risk and model error.\n\nSo the setup was not \"predict a taker, always clear the book.\"\nIt was \"predict a taker, estimate whether the expected refill value exceeds the certain cost of manufacturing the empty side, and only fire when that inequality is comfortably positive.\"\n\nAlthough the same recurrence decision-making framework applied across both OSMIUM and PEPPER_ROOT, the economic value was concentrated most heavily in the large OSMIUM takers in Round 2. Those events combined exceptionally high repeat probabilities with enough size that, after clearing the book and reposting, the expected refill value still comfortably exceeded the certain execution cost.\n\nIn backtests, had we identified and deployed this signal during Round 2 itself, we estimate it would have added roughly 70,000-100,000 XIREC of additional PnL, nearly doubling our algorithm's PnL for the round. Unfortunately, the same behavior did not persist into the final rounds, so while this intermission research did uncover a real alpha source, it did not become the generalized Phase 2 signal we had hoped for. Even so, it remained one of the most interesting findings from the project, and likely would have put us even farther ahead in Phase 1 had we discovered it in time.\n\n\u003Cbr\u002F>\n\n## Round 3\n\n### HYDROGEL_PACK\n\nHYDROGEL_PACK behaved similarly to OSMIUM:\n- slowly mean reverting,\n- average spread around 16,\n- and consistently liquid.\n\nThe main difference from OSMIUM was that HYDROGEL_PACK was somewhat more volatile, while never exhibiting the empty-book behavior that made OSMIUM so profitable.\n\nThat made the product relatively straightforward compared to what came next.\n\n\u003Ctable>\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cstrong>Figure 9: HYDROGEL_PACK Orderbook\u003C\u002Fstrong>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cimg src=\"Figures\u002Fhydrogel-pack-market.png\"\n       alt=\"HYDRO_GEL\"\n       width=\"100%\" \u002F>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cem>Typical HYDROGEL_PACK orderbook behavior.\u003C\u002Fem>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftable>\n\n\u003Cbr\u002F>\n\n### VELVETFRUIT_EXTRACT\n\nVELVETFRUIT_EXTRACT was also mean reverting, but with a much tighter spread of around 5 and significantly higher volatility.\n\nA simple Avellaneda-Stoikov market maker no longer worked well due to:\n- tighter spreads,\n- larger jumps,\n- and higher short-term volatility.\n\n\u003Ctable>\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cstrong>Figure 10: VELVETFRUIT_EXTRACT Orderbook\u003C\u002Fstrong>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cimg src=\"Figures\u002Fvelvetfruit-extract-market.png\"\n       alt=\"VELVETFRUIT-EXTRACT\"\n       width=\"100%\" \u002F>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cem>Typical VELVETFRUIT_EXTRACT orderbook behavior.\u003C\u002Fem>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftable>\n\nWe instead modeled the product as an Ornstein-Uhlenbeck process.\n\nEstimated parameters:\n- mean ≈ 5250\n- theta ≈ 0.15\n- sigma ≈ 9.8\n\nThis implied a long-term OU volatility of approximately\n\nOmega = sigma \u002F sqrt(2 * theta) ≈ 18\n\nThis became our primary threshold.\n\n#### Final Strategy\n\nThe resulting strategy became extremely simple:\n- buy below 5232\n- sell above 5268\n\nDespite its simplicity, this performed surprisingly well.\n\n\u003Cbr\u002F>\n\n### Options\n\nRound 3 also introduced 10 call options written on VELVETFRUIT_EXTRACT.\n\nInitially, we expected IV surface trading opportunities similar to Prosperity 3.\n\nHowever, analysis revealed:\n- implied volatility remained almost constant,\n- on a per-option basis,\n- throughout each day.\n\nThis largely killed the standard \"fit parabola → trade IV mispricing\" approach, since there was very little cross-strike relative-value dislocation to monetize.\n\n\u003Ctable>\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cstrong>Figure 11: IV smile\u003C\u002Fstrong>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cimg src=\"Figures\u002FIV-Smile.png\"\n       alt=\"IV SMILE\"\n       width=\"100%\" \u002F>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftable>\n\nInstead, we treated the options primarily as a way to express and leverage our mean-reversion view on the underlying. We estimated each option's fair value with Black-Scholes, using that strike's average implied volatility for the day, and then evaluated the option at the underlying OU thresholds around `5250 ± 18`. That gave us threshold prices for when calls were attractive to buy in bullish regimes or attractive to sell in bearish regimes.\n\nWe did also market-make one option, **VEV_4000**, because it was the only strike where quoting passively looked consistently worthwhile. It had enough trading activity and balanced enough two-sided flow to support inventory-managed market making, so we could quote around fair value while still controlling exposure. We did **not** extend the same MM approach to the other VEV products because they were generally worse quoting candidates: some did not trade often enough, some produced mostly one-sided fills, and some had spreads that were simply too small to justify the adverse-selection risk.\n\nWe also briefly investigated whether certain bot trades in lower strikes, especially **VEV_4000** near rolling extrema, were predictive of reversals. In retrospect, this was mostly an artifact of the underlying itself being mean reverting rather than a genuinely distinct signal, but it was still useful enough to inform parts of the live strategy.\n\nRound 3 closed with a cumulative score of **373,440 XIREC**, good for **🏆 3rd globally overall**. On the pure algorithmic leaderboard, we scored **298,730 XIREC** and finished **🏆 3rd algorithmic**.\n\n\u003Cbr\u002F>\n\n## Round 4\n\nRound 4 largely kept the Round 3 product set, but added trader Marks.\n\n### Monte Carlo Option Thresholds\n\nThis round pushed us to improve our voucher trading substantially.\n\nWe built a Monte Carlo framework that:\n- simulated future VELVETFRUIT_EXTRACT paths using our Ornstein-Uhlenbeck model\n- priced each voucher along those paths with Black-Scholes\n- kept a fixed implied volatility per voucher\n\nThis gave us a much more realistic estimate of the distribution of future option values than using a single OU threshold on the underlying.\n\nThe main reason this mattered was **Theta**.\n\nEven if the underlying reverted in the expected direction, the vouchers were constantly losing time value.\n\nSo the correct buy and sell thresholds could not be based only on expected terminal value:\n- they also had to compensate for time decay,\n- especially for the more out-of-the-money vouchers.\n\nWe therefore optimized thresholds directly on simulated PnL outcomes.\n\nOur final objective was:\n> E[PnL] - 0.25 Std(PnL)\n\nrather than maximizing Sharpe ratio.\n\nThis deliberately chose a more aggressive point on the risk-return frontier:\n- higher expected PnL,\n- but also materially higher variance.\n\nIn hindsight, this likely explains why Round 4 went worse for us than the previous round.\n\nWe do not think the approach was fundamentally wrong.\n\nIt was simply more exposed to bad short-run realization.\n\n### Mark Analysis\n\nMost Marks turned out to be far less informative than we initially hoped.\n\nThere was a lot of temptation to build broad Mark-conditioned strategies, but for all Marks the signal was either too weak, too unstable, or too hard to monetize in real time.\n\nSo, no Mark-based strategies made it into the final submission, and we instead focused on improving our existing market making and option trading strategies.\n\nRound 4 closed with a cumulative score of **602,022 XIREC**, good for **🏆 11th globally overall**. On the pure algorithmic leaderboard, we scored **191,652 XIREC** and finished **🏆 10th algorithmic**.\n\n\u003Cbr\u002F>\n\n## Round 5\n\nWhat made Round 5 incredibly complex was not necessarily the trading itself, but figuring out what actually mattered inside an absurdly large search space.\n\nThe surprise jump to 50 assets completely changed the way we approached research.\n\nPrevious rounds naturally pushed teams toward understanding a handful of products deeply.\n\nRound 5 instead tempted everyone into building giant correlation matrices and searching for structure everywhere at once.\n\nInitially, we did too.\n\nWe spent a large part of the first day building scanners and validators for:\n- cross-family correlations,\n- basket residuals,\n- rolling z-score deviations,\n- cointegration tests,\n- lead-lag relationships,\n- and microstructure imbalance signals.\n\nAnd to be honest, at first it looked like we had found basically unlimited alpha.\n\nEntire families appeared tightly linked.\nBaskets showed extreme mean reversion.\nProducts seemed to predict each other with almost suspicious precision.\nDozens of plots looked beautiful, and many strategies produced extremely strong in-sample backtests.\n\nThat made us more skeptical rather than less.\n\nOur biggest risk at that point was convincing ourselves that the market was far more structured than it really was.\n\nSo we forced proper out-of-sample validation:\n- fit on two days,\n- test on the third.\n\nThe result was a disaster.\n\nRelationships that looked statistically convincing immediately collapsed:\n- residuals became non-stationary,\n- hedge ratios changed sign,\n- correlations weakened or inverted,\n- and most cross-family pairs that had looked like statistical candy turned into rotten fruit instantly.\n\nWe think this is also why there were so many misleading \"huge alpha\" claims in Discord.\n\nIf you searched hard enough, it really was possible to find absurdly profitable backtests.\n\nThe hard part was finding relationships that actually survived out-of-sample.\n\n### What Survived\n\nIn the end, the live strategy was much simpler than our research notebook graveyard suggested.\n\nThe backbone was broad market making.\n\nJust making markets across many assets was already highly profitable, especially because much of the taker flow was effectively shared across products.\n\nIf we got filled, we often got filled in many assets at once, which reduced effective exposure at the portfolio level because the large basket of products was much less volatile than any single name.\n\nFor most products, that meant simply quoting aggressively inside the spread.\n\nFor a couple of families such as TRANSLATORS and GALAXY_SOUNDS, we used a slightly better Wall-Mid-style market maker with inventory skew.\n\nOn top of that baseline, only a few alpha layers survived the cut.\n\nThe family-level PnL attribution after the round reinforced that story.\n\nThe clearest winners were:\n- OXYGEN_SHAKES at about +669k\n- PEBBLES at about +22.4k\n- SNACKPACKS at about +19.1k\n- TRANSLATORS at about +11.7k\n- PANELS at about +9.3k\n- GALAXY_SOUNDS at about +5.5k\n\nThose were mostly families where either broad market making alone was already strong, or where the extra structure we kept live was at least directionally helpful.\n\nIn particular, OXYGEN_SHAKES were actually our main PnL source, which the 100-Jump alpha discussed below largely explains.\n\nThe weak spots were just as informative:\n- MICROCHIPS lost about 26.8k,\n- SLEEP_PODS lost about 14.0k,\n- UV_VISORS lost about 7.0k,\n- and ROBOTS lost about 4.3k.\n\nSo even though some of those families had research ideas we found statistically interesting, live attribution made it clear that not all of them translated into robust production alpha.\n\n### Residual Baskets\n\nMost of the grand cross-family structure was thrown out.\n\nOnly a handful of residual baskets were robust enough to keep live.\n\nThe final submission traded mean reversion on a small set of family combinations:\n- MICROCHIPS,\n- SLEEP_PODS,\n- SNACKPACKS,\n- and one DOMESTIC_ROBOTS basket.\n\nThese were implemented as weighted basket residuals with fixed mean and volatility thresholds, plus a killswitch for extreme dislocations.\n\nThis was a much narrower version of our original vision for the round.\n\nThe live attribution was mixed.\n\nSome families clearly did not justify the complexity:\n- MICROCHIPS finished deeply negative,\n- and SLEEP_PODS also lost meaningfully.\n\nThat is exactly the kind of result we had been worried about when so many residual relationships collapsed out-of-sample.\n\nSNACKPACKS were more nuanced.\n\nThe return structure there was genuinely interesting:\n- VANILLA and CHOCOLATE were about -0.92 correlated,\n- RASPBERRY and STRAWBERRY were negatively correlated with each other,\n- and the RASPBERRY-plus-STRAWBERRY basket showed structure against PISTACHIO.\n\n\u003Ctable>\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cstrong>Figure 12: SNACKPACK Correlation Structure\u003C\u002Fstrong>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cimg src=\"Figures\u002Fsnackpack_correlation.png\"\n       alt=\"SNACKPACK Correlation\"\n       width=\"100%\" \u002F>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cem>Correlation structure inside the SNACKPACK family.\u003C\u002Fem>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftable>\n\nWe did try basket trading and arbitrage around this.\n\nHowever, it did not end up being nearly as profitable as the cleanest live structures.\n\nSo although SNACKPACKS still finished strongly positive at about +19.1k, that was more a validation of the simpler final structure than of an elaborate family-arbitrage thesis.\n\n### 100-Jump Alpha\n\nThe cleanest standalone microstructure signal was what we internally called the **100-Jump alpha**.\n\n\u003Ctable>\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cstrong>Figure 13: 100-Jump Alpha\u003C\u002Fstrong>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cimg src=\"Figures\u002F100-Jump_alpha.png\"\n       alt=\"100-Jump Alpha\"\n       width=\"100%\" \u002F>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cem>Example of the short-horizon jump-and-revert behavior we exploited in Round 5.\u003C\u002Fem>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftable>\n\nThis pattern appeared on random products at random times, but in our live results the clearest and most important manifestation was OXYGEN_SHAKE_CHOCOLATE.\n\nWhat happened was that price would jump to the nearest round 100 level, such as 10.3k or 10.4k, and once it jumped there, the probability of quickly jumping back was far above 50%.\n\nSo in practice it behaved like a very short-horizon mean reversion signal.\n\nThe implementation was correspondingly simple:\n- for each product, detect a sufficiently large jump after a few stable ticks,\n- assume the move is likely to revert,\n- and immediately take liquidity on the opposite side.\n\nThis was one of the easiest real alphas to identify and monetize.\n\nIn hindsight, this also explains why OXYGEN_SHAKES ended up as our biggest winning family.\n\nBy contrast, ROBOTS still finished slightly negative overall at about -4.3k, so although the same effect did show up there in the historical data, it was not the main source of realized PnL.\n\n### UV_VISORS\n\nOur initial lead-lag research produced a lot of false positives, so by late Round 5 we were already suspicious of almost every such result.\n\nThen, in the final hours, we found one lead-lag structure in UV_VISORS that actually looked real.\n\nThe effect itself was modest: certain visor products appeared to turn, and roughly half a day later another visor product tended to follow,\n\nThat was not the kind of signal you build a huge standalone strategy around with 90 minutes left.\n\nSo we implemented the smallest thing that could plausibly monetize it: a regime overlay.\nIt either added or subtracted 1 tick from fair value on a couple of specific leader-lagger pairs.\n\nThis caused a lot of stress because it was found very late, but it did make it into the final bot.\n\nThe final attribution there was mildly negative, with UV_VISORS ending around -7.0k.\n\nSo we still think the structure was real, but the live implementation was too small and too late to become a major source of PnL.\n\n### PEBBLES\n\nPEBBLES turned out not to be one magical alpha with a clean verbal explanation.\n\nLooking at our final submission, the live PEBBLES strategy was really a synthetic family-pricing model with a few extra lagged signals layered on top.\n\nThe core fair value assumption was that the five PEBBLES products approximately summed to a stable anchor around 50,000.\n\nSo for any one product, we priced it synthetically as:\n- 50,000\n- minus the observed prices of the other four sizes.\n\nThat gave a synthetic fair value for each pebble size, after which we:\n- applied inventory skew,\n- quoted around that reservation price,\n- and took liquidity when the observed market was sufficiently far away.\n\nOn top of that, we added a few cross-size lag rules, for example:\n- PEBBLES_XS reacting to prior moves in PEBBLES_XL and PEBBLES_L,\n- PEBBLES_S reacting to prior moves in PEBBLES_M and PEBBLES_XS,\n- and PEBBLES_XL reacting to prior moves in PEBBLES_L.\n\nSome pebble sizes were therefore mostly plain synthetic market making, while others had a directional regime overlay from those lagged triggers.\n\nSo for our final alpha:\n> the PEBBLES alpha in our final bot was a synthetic basket fair-value model with a small amount of hand-tuned intra-family lead-lag logic, not one single elegant standalone edge.\n\nAttribution supports that interpretation quite well: PEBBLES ended up as our strongest Round 5 family at about +22.4k.\n\n### Final Strategy Philosophy\n\nIn the end:\n- we discarded most cross-family complexity,\n- kept only the most robust relationships,\n- relied heavily on broad market making,\n- and layered only a small number of specific alphas on top.\n\nIronically, a few components we still suspected might be slightly overfit ended up live anyway, simply because at some point you have to stop researching and submit.\n\nRound 5 closed with a cumulative score of **1,386,318 XIREC**, good for **🏆 4th globally overall**. On the pure algorithmic leaderboard, we scored **684,923 XIREC** and finished **🏆 4th algorithmic**.\n\n\u003Cbr\u002F>\n\n# Manual Challenge\n\n\u003Ca id=\"manual-round-1\">\u003C\u002Fa>\n## Round 1: An Intarian Welcome \n\n**The challenge:**\n\nThe first manual round was a one-shot auction optimization problem on two products: **DRYLAND_FLAX** and **EMBER_MUSHROOM**. For each product, we submitted a single limit order consisting of a price and quantity after all other orders were already fixed.\n\nThe exchange then selected a single clearing price that:\n- maximized traded volume,\n- and, in the event of a tie, chose the higher price.\n\nAll trades executed at the clearing price, and because we submitted last, we were always last in queue at any price level we joined. Any inventory we bought was then immediately sold back at a fixed price:\n- **DRYLAND_FLAX:** 30 per unit, no fee\n- **EMBER_MUSHROOM:** 20 per unit, with a 0.10 fee per unit traded\n\n**Our strategy**\n\nThe key insight was that we paid the **clearing price**, not our own bid. This meant bid price mattered mainly through its effect on queue position and on whether our order changed the clearing-price regime. Quantity mattered because it could push the auction into a new tie, which would then be resolved upward by the higher-price tie-break rule.\n\nTo solve this, we built an exact in-house auction simulator and brute-forced every feasible `(bid_price, quantity)` pair. For each candidate, we:\n- constructed the cumulative demand and supply curves at every price level,\n- computed the clearing price under the official auction rule,\n- allocated fills using price priority and then time priority,\n- and calculated profit as `fill × (buyback price − clearing price − fee)`.\n\nThis turned the problem into a clean optimization over discrete clearing-price transitions. In both products, the optimum ended up sitting exactly one unit below the quantity level that would have pushed the auction into the next, less profitable clearing-price regime.\n\n### **DRYLAND_FLAX**\n\nFor DRYLAND_FLAX, the optimal order was **9,999 units at price 30**, producing a profit of **9,999**.\n\nWithout our order, the auction cleared at `28` with `40,000` units traded. Adding `9,999` units of demand at `30` caused price `29` to tie for maximum traded volume at `40,000`, so the exchange selected `29` by the higher-price tie-break rule. This left us with a margin of `1` per unit.\n\nAt `10,000` units, price `30` also tied for maximum volume, so the clearing price jumped to `30`, eliminating all profit. The optimum therefore sat exactly one unit below that transition.\n\n### **EMBER_MUSHROOM**\n\nFor EMBER_MUSHROOM, the optimal order was **19,999 units at price 20**, producing a profit of **77,996.10**.\n\nThe baseline auction cleared at `15` with `86,000` units traded. Adding `19,999` units of demand pushed price `16` up to `91,000` traded, making it the unique best clearing level and leaving a margin of `3.90` per unit after fees.\n\nAt `20,000` units, price `17` also reached `91,000` traded, so the clearing price moved up again and profit dropped sharply. As with FLAX, the optimum sat just below the next clearing-price transition.\n\n**Final submission**\n\n- **DRYLAND_FLAX:** bid `30` for `9,999`\n- **EMBER_MUSHROOM:** bid `20` for `19,999`\n\n**Total profit: 87,995 XIREC**\n\nThis approach worked exactly as intended: we obtained the optimal submission for the challenge and finished **🏆 1st globally** on the manual leaderboard and **🏆 8th globally** overall for Round 1.\n\n\u003Cbr\u002F>\n\n\u003Ca id=\"manual-round-2\">\u003C\u002Fa>\n## Round 2: Invest & Expand\n\n**The challenge:**\n\nThe second manual round was a one-shot budget allocation problem. We were given `50,000` XIREC to distribute across three pillars — **Research**, **Scale**, and **Speed** — with the goal of maximizing final PnL.\n\nUnlike a standard static optimization problem, this challenge had a strategic component: while Research and Scale were deterministic functions of our own allocation, the value of Speed depended on how our choice ranked relative to the rest of the field. That turned the problem into a game-theoretic best-response exercise rather than a simple constrained maximization.\n\n**Key mechanics**\n\n- **Research** grew logarithmically from `0` to `200,000` as allocation increased from `0` to `100`.\n- **Scale** grew linearly from `0` to `7`.\n- **Speed** was rank-based across all teams:\n  - highest Speed received a `0.9` multiplier,\n  - lowest received `0.1`,\n  - everyone in between was scaled linearly by rank,\n  - equal allocations shared the same rank.\n- Total allocation could not exceed `100%`.\n- PnL = (Research × Scale × Speed) − Budget_Used\n\n**Our strategy**\n\nThe core of this challenge was estimating the field’s Speed distribution. Once Speed was fixed, the Research\u002FScale optimization was relatively straightforward: because Research was logarithmic and Scale was linear, the best non-Speed split was stable and heavily favored Scale after a modest Research allocation. The real uncertainty came from the rank-based Speed multiplier.\n\nTo approximate the crowd, we made a simple but effective assumption: many teams would rely on their preferred LLM for an initial recommendation. Rather than hand-picking a single crowd guess, we treated model outputs as a noisy but useful proxy for how a large fraction of the field might approach the problem.\n\nIn practice, we used the official challenge description as a seed prompt and generated six prompt variants corresponding to different player archetypes. We then queried several models, primarily GPT and Claude, repeatedly through their APIs, collected the resulting allocations, and compiled them into CSVs. This gave us empirical crowd priors for likely Speed choices under different LLM assumptions.\n\n\u003Ctable>\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cstrong>Figure 14: Speed Allocation Distribution Across Various LLMs\u003C\u002Fstrong>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cimg src=\"Figures\u002Fspeed_distribution.png\"\n       alt=\"Speed allocation distribution by model\"\n       width=\"100%\" \u002F>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftable>\n\n\u003Ctable>\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cstrong>Figure 15: GPT-5.4 Speed Allocation Distribution\u003C\u002Fstrong>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cimg src=\"Figures\u002Fdist_5_4.png\"\n       alt=\"GPT-5.4 speed allocation distribution\"\n       width=\"100%\" \u002F>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftable>\n\nWe then fed these sampled crowd distributions into our in-house brute-force optimizer. For each candidate Speed value from `0` to `100`, the optimizer estimated the corresponding expected rank-based multiplier against the sampled field, then enumerated every feasible integer `(Research, Scale)` pair satisfying the budget constraint and selected the allocation with the highest expected PnL. In our final decision, we searched for stable optimal parameter \"landscapes\" and weighed GPT 5.4 and Claude Opus 4.7 distributions most heavily, since they were the flagship public chatbot models at the time.\n\n**Final submission**\n\n- **Research:** `15`\n- **Scale:** `43`\n- **Speed:** `42`\n\n**Result**\n\nThis approach worked exceptionally well and generated us a PnL of **217,869 XIREC** for this manual challenge alone! As one of only a few teams to reach the optimal submission for this challenge, we finished **🏆 1st globally** in manual trading and **🏆 4th globally** overall for Phase 1 (Rounds 1 and 2).\n\n\u003Cbr\u002F>\n\n\u003Ca id=\"manual-round-3\">\u003C\u002Fa>\n## Round 3: The Celestial Gardeners' Guild\n\n**The challenge:**\n\nThe third manual round was a two-bid pricing problem against a population of counterparties with unknown reserve prices. Each counterparty’s reserve price was uniformly distributed between `670` and `920` in increments of `5`, and any units we bought could be resold the next trading day for a fixed fair value of `920`.\n\nAt first glance this looked like a simple expected-value problem, but the second bid introduced a strategic layer. While the first bid depended only on the reserve-price distribution, the value of the second bid also depended on how it compared with the **average second bid submitted by the rest of the field**.\n\n**Key mechanics**\n\n- We could submit **two bids**, `b1` and `b2`, with `b1 \u003C b2`.\n- If a counterparty’s reserve price was below `b1`, we traded at `b1`.\n- If the reserve price was between `b1` and `b2`, we traded at `b2`.\n- If `b2` was **above the field’s average second bid**, that second-bid trade earned the full margin `920 - b2`.\n- If `b2` was **below the field average**, the second-bid payoff was penalized by\n\n$$\n\\left(\\frac{920 - \\text{avg}(b_2)}{920 - b_2}\\right)^3\n$$\n\nThat penalty made the problem highly asymmetric: being slightly too low on the second bid could hurt much more than being slightly too high.\n\n**Our strategy**\n\nWe started by solving the single-agent version of the problem under the assumption that our second bid would not be penalized. That gave a useful baseline for how the two bids should relate to each other.\n\nThe key insight was that the two bids were **coupled**. The first bid could not be optimized independently of the second. If we write expected profit as the sum of profit from reserves filled at `b1` and profit from reserves filled only at `b2`, the unconstrained optimum implies a structure of the form:\n\n- `b1` should sit roughly halfway between the lower bound `670` and `b2`\n- the joint optimum lands near `(753, 837)`\n- on the discrete grid, the best unpenalized pairs sit around `(751, 835)` or `(751, 840)`\n\nThat baseline already showed why a naive midpoint-style first bid was wrong: maximizing the first leg in isolation left meaningful expected profit on the table.\n\nThe harder part was estimating where the field would place its second bid. Just as in Round 2, we treated this as a crowd-modeling problem. We generated multiple prompt variants based on the challenge description, queried LLMs repeatedly through their APIs, and used the resulting bid samples as a proxy for how many teams might reason about the game. This gave us an empirical distribution for likely second bids rather than forcing us to rely on a single guess.\n\n\u003Ctable>\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cstrong>Figure 16: Claude Opus 4.7 vs GPT 5.4 Second Bid Distributions\u003C\u002Fstrong>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cimg src=\"Figures\u002Fround3_b2_distribution_opus_vs_gpt54.png\"\n       alt=\"Second bid distributions for Claude Opus 4.7 and GPT 5.4\"\n       width=\"70%\" \u002F>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftable>\n\n\u003Ctable>\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cstrong>Figure 17: Claude Bid Distributions by Prompt Variant\u003C\u002Fstrong>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cimg src=\"Figures\u002Fbid_distribution_by_prompt_v2.png\"\n       alt=\"LLM bid distributions for first and second bids across prompt variants\"\n       width=\"70%\" \u002F>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftable>\n\nWe then fed these estimated average second-bid distributions into our in-house brute-force optimizer and, as we did for round 2's manual challenge, searched for stable optimal parameter \"landscapes\" across estimated distributions, weighing flagship models much more heavily. For every feasible integer pair `(b1, b2)`, it computed expected profit under the official reserve-price distribution and applied the penalty whenever `b2` fell below the estimated crowd mean. That turned the problem into a best-response search over the full two-dimensional bid grid.\n\nThe main conclusion was that while the unpenalized optimum sat near the low-`840`s, the cubic downside for underbidding the crowd justified submitting a second bid **slightly above** our estimated field average. We therefore shifted upward from the pure single-agent optimum and chose a more defensive pair.\n\n**Final submission**\n\n- **First bid:** `756`\n- **Second bid:** `852`\n\n**Result**\n\nThe realized average second bid was `859`, so our second bid ended up slightly below the field. Even so, the submission performed reasonably well and earned us a PnL of **74,710 XIREC**, which placed us **🏆 3rd globally** overall for Round 3 (note: leaderboard progress was reset following Round 2 since these were now finals, so this was effectively completely fresh performance).\n\n\u003Cbr\u002F>\n\n\u003Ca id=\"manual-round-4\">\u003C\u002Fa>\n## Round 4: Vanilla Just Isn't Exotic Enough\n\n**The challenge:**\n\nThe fourth manual round was a one-shot derivatives portfolio construction problem. We were given a menu of positions on **AETHER_CRYSTAL**: the underlying itself, vanilla calls and puts with 2-week and 3-week expiries, and several exotics, including a chooser option, a binary put, and a knock-out put. Unlike the earlier manual rounds, this was not a bidding or allocation problem. We had to decide which contracts to buy or sell at time zero and hold until expiry.\n\nWhat made the round difficult was that pricing was explicitly stochastic and path-dependent. The underlying was simulated on a discrete grid under GBM with annualized volatility of `251%`, and the final score was based on the **average PnL across 100 simulations**. That turned the challenge into a mix of derivative pricing, portfolio construction, and risk management rather than a simple expected-value maximization exercise.\n\n**Key mechanics**\n\n- All contracts were written on **AETHER_CRYSTAL**, with spot starting at `50`.\n- Vanilla options existed with **2-week** and **3-week** expiries.\n- A **chooser option** let the holder decide after 2 weeks whether the contract became a call or a put for the final week.\n- A **binary put** paid a fixed amount if the underlying finished below strike.\n- A **knock-out put** became worthless if the underlying ever crossed the barrier before expiry.\n- Positions were entered once at `t = 0` and held to expiry.\n- The official grading metric was **average PnL across 100 simulations**, so basket-level downside mattered just as much as standalone contract mispricing.\n- Barrier events were evaluated on the same discrete simulation steps used by the challenge, not in continuous time.\n- Contract size was fixed at `3000`, so even small pricing errors could create very large swings in PnL.\n\n**Our strategy**\n\nWe approached the round in two layers. First, we built fair-value models for every product in the menu. Vanillas were priced with Black-Scholes under the official volatility and time conventions, while the exotics were priced with Monte Carlo simulation on the same discrete grid used by the challenge. This gave us a clean edge estimate for each contract and immediately highlighted which products looked cheap or rich on a standalone basis.\n\nThe first lesson, however, was that pure expected-value optimization was not enough. If we simply bought every underpriced contract and sold every overpriced one at full size, the resulting basket carried enormous left-tail risk, especially through short convexity and path-dependent exposures. The highest-EV baskets were often economically correct in expectation but uncomfortable once evaluated under the actual 100-simulation scoring rule.\n\nWe therefore moved to a risk-aware portfolio search. Using simulated payoff paths for the full contract set, we evaluated baskets on the same batch-100 basis used by the competition and traced out an expected-value versus CVaR frontier. That made the trade-off explicit: the top of the frontier was relatively flat, so a modest sacrifice in modeled EV could buy a meaningful reduction in downside risk.\n\n\u003Ctable>\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cstrong>Figure 18: Round 4 Optimal EV vs CVaR Frontier\u003C\u002Fstrong>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cimg src=\"Figures\u002Fround4_optimal_ev_vs_cvar_curve.png\"\n       alt=\"Round 4 optimal EV versus CVaR frontier\"\n       width=\"100%\" \u002F>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftable>\n\nWe then expanded the optimization universe to include the underlying and all vanilla contracts, even when some had little standalone edge, because they were valuable as static hedges for the exotics. In particular, the chooser option could be replicated exactly by a **3-week at-the-money call plus a 2-week at-the-money put**, so the optimizer could use vanillas to hedge chooser exposure instead of treating it as a purely directional bet. This turned the problem into a basket-construction exercise rather than a simple ranking of individual mispricings.\n\nFrom there, we iterated between frontier analysis and basket cleaning. The goal was not to find the single most aggressive positive-EV portfolio, but to find a basket whose risk profile still made sense under the competition's averaging rule. The final submission kept the core mispriced positions, but paired the exotic shorts with vanilla hedges and removed some of the worst naked downside.\n\n\u003Ctable>\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cstrong>Figure 19: Round 4 Basket Outcome Distribution\u003C\u002Fstrong>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\n\u003Ctr valign=\"top\">\n\u003Ctd width=\"100%\" align=\"center\">\n  \u003Cimg src=\"Figures\u002Fround4_basket_distribution.png\"\n       alt=\"Round 4 basket outcome distribution\"\n       width=\"100%\" \u002F>\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftable>\n\n**Final submission**\n\n- **BUY** `22` `AC_50_C` at `12.05`\n- **BUY** `50` `AC_45_P` at `9.10`\n- **BUY** `50` `AC_50_P_2` at `9.75`\n- **BUY** `50` `AC_50_C_2` at `9.75`\n- **SELL** `50` `AC_50_CO` at `22.20`\n- **SELL** `50` `AC_40_BP` at `5.00`\n- **BUY** `500` `AC_45_KO` at `0.175`\n\n**Result**\n\nThis round was much tougher for us than the first three. Our submitted basket had a modeled expected PnL of **164,864 XIREC**, with a batch-100 CVaR 5% of -358,576 XIREC and a batch-100 5th percentile outcome of -259,614 XIREC. In other words, it captured about 97.4% of the maximum modeled EV on our frontier while taking only about 30.4% of the max-EV basket's CVaR 5% downside. However, the realized outcome was only **36,929 XIREC**, which dropped us to **🏆 11th globally overall** after Round 4.\n\nIn retrospect, we almost certainly over-hedged. The strongest baskets along the efficient frontier were highly correlated and differed mostly in hedge intensity, so a lighter risk constraint would probably have preserved more of the shared positive edge. Given that IMC was likely to evaluate the round using a reasonably representative seed rather than an extreme left-tail path, we think we paid too much to insure against outcomes that were unlikely to determine the final ranking. That trade-off may make sense in real portfolio risk management, but for this competition it likely reduced our upside far more than it improved our true expected result.\n\n\u003Cbr\u002F>\n\n\u003Ca id=\"manual-round-5\">\u003C\u002Fa>\n## Round 5: Extra! Extra! Read all about it!\n\n**The challenge:**\n\nThe fifth and final manual round was a one-day news-trading problem on a basket of Ignith goods. We were given a set of Ashflow Alpha headlines and had to choose which products to buy or sell, then hold that portfolio until the next day.\n\nWhat made this round difficult was that it was not enough to get the direction right. Realized returns depended partly on how the field positioned around each product, and trading costs rose quadratically with size. So the real problem was not just news interpretation, but deciding which headlines were still underpriced, which were already priced in, and how much size each idea could support after fees.\n\n**Key mechanics**\n\n- We had a total budget of **1,000,000 XIREC**.\n- We could go **long or short** each product.\n- Realized returns were not fixed; they could shift depending on aggregate participant positioning.\n- Fees increased quadratically with per-product size, so concentration became expensive very quickly.\n- Unused budget expired worthless, but forcing capital into weak ideas could still be worse than leaving some budget unallocated.\n\n**Our strategy**\n\nWe approached the round as a fee-aware cross-sectional news portfolio problem. For each headline, we estimated both **direction** and **rough magnitude**, then compared the setup with analogous product archetypes from **previous Prosperity competitions** that used similar news-driven manual rounds. Those earlier challenges were useful because many superficially dramatic headlines ended up being only modestly tradable once crowd positioning and pricing-in effects were taken into account.\n\nBecause the original challenge material was presented as an image rather than clean text, we also built an OCR pipeline to convert the news sheet into machine-readable text before analyzing it. That turned out to matter more than we expected. In one early OCR pass, the layout caused the label **Magma Ink** next to its product image to concatenate directly into the following headline, producing a misleading line that effectively read: \"*Magma Ink: Manufacturing halted after Obsidian Cutlery cuts through its own assembly line*.\" Left unchecked, that would have completely changed the story by making it look like **Magma Ink** had suffered the production halt rather than **Obsidian Cutlery**. We caught the issue during manual QA and corrected it, but it was a good reminder that blindly trusting OCR on an image-based prompt could easily produce the wrong portfolio. Whether that was a deliberate layout trap from IMC or just a quirk of our OCR pipeline, it materially changed how careful we had to be with preprocessing.\n\nThat led us to focus less on whether a headline sounded dramatic and more on whether the implied move was likely to be **large enough to overcome fees**. Since a position of `p%` of budget incurred a fee equal to `p%` of notional, larger positions needed much larger realized moves just to break even. This made sizing just as important as directional accuracy.\n\nAt the product level, our reasoning was as follows:\n\n- **Ashes of the Phoenix — SELL 8%**  \n  We expected the product to weaken because the resurfaced sourcing video created public scrutiny and the company response read as unconvincing. However, we did not expect a collapse: this was a consumer product rather than the company itself, and because the video had resurfaced rather than newly emerged, it was plausible that a meaningful part of the reputational damage was already known or partly priced in.\n\n- **Magma Ink — BUY 3%**  \n  We thought the launch was mildly positive, but likely not a huge surprise. The merger behind the product had already happened and the release had been heavily advertised, so much of the narrative was probably priced in already. We still leaned long because the turnout looked somewhat stronger than expected, suggesting some incremental upside.\n\n- **Volcanic Incense — SELL 5%**  \n  This looked like a classic **pump-and-dump** scheme. The Whiff Nostralico headline suggested a crowd-driven, personality-fueled spike rather than a durable fundamental repricing, so we preferred fading the move rather than chasing it. At the same time, because pump-and-dump dynamics can persist if the promoter keeps amplifying them, we kept the short relatively small.\n\n- **Lava Cake — SELL 25%**  \n  This was our clearest short. Confirmed lava contamination, an immediate sales halt, health-review risk, lawsuit risk, and vendors returning stock all pointed to the same conclusion: this was a direct and severe product-specific shock. Relative to the softer headlines elsewhere on the sheet, this looked like one of the few stories capable of generating a genuinely large one-day repricing, and that is exactly what happened.\n\n- **Pyroflex Cells — SELL 4%**  \n  The removal of the tax cut was a clean negative demand shock. It effectively raised end-user cost and threatened upgrade behavior, so the direction was fairly straightforwardly bearish. However, because the policy change and surrounding criticism had already been public for a while, we assumed a fair amount of the move was already priced in and kept the position modest.\n\n- **Obsidian Cutlery — BUY 20%**  \n  Our main thesis here w","该项目分享了在IMC Prosperity 4（2026年）国际量化交易竞赛中获得全球第四名及欧洲第一名的策略、研究和基础设施。项目核心功能包括算法交易和手动挑战，使用Python编写，涵盖了从数据处理到策略执行的全过程。技术特点体现在对多种交易策略的系统性测试与优化上，强调了团队合作和技术积累的重要性。适用于金融工程、算法交易领域的学习者和从业者参考借鉴，尤其是那些希望参加类似竞赛或提升量化交易技能的人士。","2026-06-11 04:01:48","CREATED_QUERY"]