Imc Prosperity 4
No description available
Install / Use
npx skills add rmtf1111/imc-prosperity-4Installs into whichever agent you are using.
README
IMC Prosperity 4
Our team, rat_hunters finished #2 in IMC Prosperity 4, with a cumulative Phase-2 PnL of 1,459,764 XIRECs (Algo 1,220,042 + Manual 239,722). On the algorithmic challenge alone, we finished #3 globally at a 500 XIRECs difference from second place on algo.
Round 3 — Mean reversion
Algo PnL: +297,716 • Algo rank: #4
The first instinct for this round was to attempt some IV-based strategies. However, after realizing that the fluctuations in the IV accounted for ±2 moves in the price, we dropped the whole options business.
After this, Maxime started making positive PnL on both products with mean reversion and then it hit me - this is Prosperity, mean reversion MUST be the answer to all your problems. A quick analysis of VELVET_FRUIT and HYDROGEL_PACKS showed that they have negative autocorrelation, which could be explained by mean-reversion. If it looks like MR, walks like MR and it's Prosperity, it probably is MR.
Strategy: Our strategy for the two products was exactly the same - find a fair value (for VELVET_FRUIT: 5250, for HYDROGEL_PACKS: 9990); find a symmetric threshold for the deviation from fair value at which to enter a position (for VELVET_FRUIT: 28, for HYDROGEL_PACKS: 40); when the price crosses fair +- threshold send a signal to fill up your position respectively (this could take a few ticks). We had no liquidation upon reversion, just buy at lows and sell at highs (and of course, for VELVET_FRUIT, do the same for its respective options). 100 lines of code.
Round 4 — Mean reversion
Algo PnL: +221,170 • Algo rank: #3 • Rank for this round only: #20
Round 4 de-anonymized the trade tape: every fill carried a counterparty ID. However, we did not find anything interesting so we did not use any bot behaviour.
However, we noticed that for HYDROGEL_PACKS, downward excursions had a median peak of 20, while upward excursions had a median peak of 40. This meant that symmetric thresholds were suboptimal.
Strategy: Same as round 3, except we introduced asymmetric thresholds for HYDROGEL_PACKS - we used a buy threshold at -8 from fair and sell at +40 from fair price.
P.S: Despite being ranked #4 and #20 for Algo Round 3 and 4, we still ended up at #3 for Algo when combining the two rounds. I wonder why ;)
Round 5 — The New Prosperity!
Algo PnL: +701,157 • Algo rank: #3 • Rank for this round only: #8
After 5 hours of sleep I woke up at 7 am and the first thing I saw was our teammates on east coast saying we're in 2nd place. There were also 50 (fifty!) new products, split across 10 sectors and each had 5 products. Needless to say, against my best efforts, I couldn't go back to sleep. This wasn't just for fun anymore :)
Finding Nemo (Alpha).
First things first - we plotted first-order difference correlations within groups. This gave away almost all the alphas and the products we worked on the first day of Round 5. Below are the heatmaps that showed anything significant.
<p align="center"> <img src="images/heatmap_pebbles.png" width="46%" alt="Purification Pebbles diff-correlation"/> <img src="images/heatmap_robots.png" width="46%" alt="Domestic Robots diff-correlation"/> </p> <p align="center"> <img src="images/heatmap_oxygen_shakes.png" width="46%" alt="Liquid Breath Oxygen Shakes diff-correlation"/> <img src="images/heatmap_snackpacks.png" width="46%" alt="Protein Snack Packs diff-correlation"/> </p>Another interesting correlation finding was that Snackpacks as a sector was correlated with the rest of the market (and it was quite significant, at 0.22 correlation for first-order differences). Unfortunately, we did not have the time to explore this direction.
Pebbles — basket arbitrage
We noticed that Pebbles' prices summed up to 50,000 consistently with the exception of some steps where the sum deviated by ±15 and reverted immediately in the next tick. We found that it was rarely profitable to take a position on these deviations due to the spread. We realized that Market Making is a risk-free strategy here due to the bots always trading the same quantities at the same timestamps for all the pebbles simultaneously. We netted around 18k/day with Market Making and taking at the deviations when it was profitable, accounting for the spread.
Snackpacks - pairs trading
The very high negative correlation between SNACKPACK_VANILLA/SNACKPACK_CHOCOLATE might signal cointegration. However, if you ran ADF, the reported p-value was quite large. In particular, while high correlation can signal cointegration, it does not necessarily imply it. In fact, very high correlation probably rules out pairs trading - think about a stock that always copies or reverts the move of another one. Not too tradeable IMHO.
We found that the SNACKPACK_VANILLA − SNACKPACK_RASPBERRY spread is the cleanest mean-reverting signal in the family - second-to-best ADF p-value, median almost 0, and also ties together all the products. When the spread crossed ±100, we sent a signal to fill up our positions. Since SNACKPACK_CHOCOLATE was so negatively correlated with SNACKPACK_VANILLA and SNACKPACK_STRAWBERRY with SNACKPACK_RASPBERRY, we used the SNACKPACK_VANILLA-SNACKPACK_RASPBERRY signal to also take a respective SNACKPACK_STRAWBERRY-SNACKPACK_CHOCOLATE position. SNACKPACK_PISTACHIO was treated as an "excluded" product that we used market making on.
Lattice movements - the bread-winner
ROBOT_DISHES, ROBOT_IRONING, OXYGEN_SHAKE_EVENING_BREATH, and OXYGEN_SHAKE_CHOCOLATE exhibited a discrete-grid micro-structure: mid mostly walked in small ticks, but occasionally it started moving by ±100 positions. This could've been explained by the fact that the mid price was rounded to a point on a 100-wide lattice. By standard martingale arguments this would've implied that after a 100 swing one way the next swing would most likely be in the opposite direction. A quick empirical check confirmed this - after the price moved by ±100, the next move was ∓100, respectively, with 85% chance. The strategy at this point is trivial - whenever the price moves by +100 sell full inventory and when it moves by -100, buy full inventory.
Microchips — within-family lead-lag
The Microchip family is the only Round 5 group where a clean integer-lag signal exists between products. MICROCHIP_OVAL, MICROCHIP_SQUARE, MICROCHIP_RECTANGLE and MICROCHIP_TRIANGLE all followed MICROCHIP_CIRCLE at 50, 100, 150 and 200 lags, respectively. The correlation was rather weak - around 0.05. However, when aggregated over multiple steps it could've been a tradeable signal. To our surprise, when aggregating multiple differences, i.e. looking at MICROCHIP_RECTANGLE_{t+300} - MICROCHIP_RECTANGLE_{t+150} and MICROCHIP_CIRCLE_{t+150} - MICROCHIP_CIRCLE_t, the correlation jumped to 0.15. This should not happen if there were no other hidden structure for this family. We searched hard for the other systematic pattern, but failed to find it. For unfounded reasons we resorted to overfitting - we aggregated the price difference over larger windows than what was logical (i.e., looked at MICROCHIP_CIRCLE_{t+200} - MICROCHIP_CIRCLE_t to predict MICROCHIP_RECTANGLE_{t+400} - MICROCHIP_RECTANGLE_{t+200}) and swept for thresholds. Needless to say, we netted an embarrassing -25k on microchips as a group. Nonetheless, this was the most fun asset (class) of all of Prosperity - it really made us think and write down math. I would come back next year just for a round where we get another chance to trade such products.
General market making
Every Round 5 product that isn't claimed by the four strategies above gets a basic two-sided passive MM: post (best_bid + 1, best_ask − 1). The exclusion set in PROB_MM_EXCLUDED ensures the MM layer never fights another strategy when the logic gets too messy. One thing to mention about MM is that all products got traded at the same time, in the same quantities and in the same directions. Hence, we exposed ourselves to the overall movements of the market. However, we found the market to be overall stable, and we were equally exposed to gaining from directionality as we were to losing, so it seemed sensible to keep market making.
Overfitting
Round 3 and 4
I want to mention that the amount of overfitting reported in Discord was actually insane - z-scores, Bollinger (?), EMA, blah blah. Before implementing any of these you should have a solid reason. For example, if you take a rolling mean as your "fair price" and plot the residuals you will find that the latter was also mean-reverting. However, this holds true for almost any time series under the sun :). You would need a more rigorous analysis to claim that local mean-reversion would be more profitable than global mean-reversion that would necessarily have to include the stability of the rolling mean.
You should really think about what you are trading here - you are betting that the current price is too high for whatever happened in the past 100 ticks, and that it is going to revert, in say 1000 ticks. Then you are selling now, and then in 1000 ticks you would want to buy back because the rolling mean in 900 ticks will be lower than the price in 1000 ticks? Take a step back to think about what exactly you are doing. The rolling mean could've drifted as well - what if the rolling mean started dropping itself and the 1000th tick price was higher with respect to the rolling mean, but substantially lower than when you bought? If there are no fundamental statistics to confirm that you do not expose yourself to the rolling mean deviations then you should just assume overfit if the PnL on backtest is good.
Needless to say, I am not claiming that local mean-reversion is bad, all I am trying to communicate is that there needs to be concrete reasoning and logic to back this up. Better backtest results is not logic, it's
Related Skills
node-connect
385.5kDiagnose OpenClaw Android, iOS, or macOS node pairing, QR/setup code, route, auth, and connection failures.
blender-python-addon
40.5kBlender Python add-on rules for operators, panels, properties, registration, testing, and API-safe scripting
flutter-development-guidelines-cursorrules-prompt-file
40.5kCursor rules for Flutter development with MVVM architecture, Riverpod state management, Material widgets, and Dart style guidelines.
commit-push-pr
140.7kCommit, push, and open a PR
