# Stress testing of Omnipool model. "Toxic asset problem" potential solutions ###### Created by InventAndChill Link to model https://en.smath.com/cloud/worksheet/zw6gkNDB ## Data preparation Using API from one of lead data providers **2-3 month of tick data** has been downloaded and prepared for direct using from python in pandas data frame format. **Data is available for all course participants.** Available tickers are AAVE ADA ATOM BTC DOGE ***DOT*** ETH ***KSM*** UNI XMR Example of DOT data is here ![](https://cdn.discordapp.com/attachments/892816252689596458/895684988551450654/DOT_data.png) ## Link between formulas in code and traditional representation For more effective code understanding almost all formulas from cadcad model has been converted into traditional form and **provided to all course participants** ![](https://cdn.discordapp.com/attachments/866902570911662120/899203774059532328/Formulas.png) ## Tracing of Omnipool CADCAD model calculations Tracing print inserted into each part of CADCAD model where some calculations are performed. It is very useful for understanding and checking of model. Aslo it helps with providing of numerical examples. For each formula there is numerical representation Tracing example for R to R swap (a=1, delta_Ri=7777): ``` running file: run.py -----Running of file: sys_params.py Ci = 1 initial_price_j = asset_initial_values['j']['Q']/asset_initial_values['j']['R'] 2.0=2000000/1000000 Cj = ( initial_price_j * (asset_initial_values['j']['R'])**(temp_a+1) ) / ( asset_initial_values['i']['Q']*asset_initial_values['i']['R'] ) 1.0=2.0*(1000000)**(1.0+1))/(2000000*1000000)) Y = ( Ci * asset_initial_values['i']['R']**(-temp_a) + Cj * asset_initial_values['j']['R']**(-temp_a) )**(-1/temp_a) 500000.0= (1*1000000**(-1.0) + 1.0 * 1000000**(-1.0))**(-1/1.0) C = asset_initial_values['i']['S'] * asset_initial_values['j']['S']**2 1000000000000=10000*10000**2 {'UNI_Qi': 2000000, 'UNI_Ri': 1000000, 'UNI_Si': 10000, 'UNI_Qj': 2000000, 'UNI_Rj': 1000000, 'UNI_Sj': 10000, 'UNI_ij': 1000000, 'UNI_ji': 1000000, 'UNI_Sij': 1000000000000, 'Ri': 1000000, 'Ci': 1, 'Si': 10000, 'Rj': 1000000, 'Cj': 1.0, 'Sj': 10000, 'Sq': 20000, 'Q': 4000000, 'H': 4000000, 'Y': 500000.0,} initial_price_in_Q(R, C, Q, Y, a) R=1000000 | C=1 | Q=4000000 | Y=500000.0 | a=1.0 initial P = (Q * Y**(a)) * (C / R**(a+1)) 2.0 = (4000000 * 500000.0**(1.0)) * (1 / 1000000**(1.0+1)) initial_price_in_Q(R, C, Q, Y, a) R=1000000 | C=1.0 | Q=4000000 | Y=500000.0 | a=1.0 initial P = (Q * Y**(a)) * (C / R**(a+1)) 2.0 = (4000000 * 500000.0**(1.0)) * (1.0 / 1000000**(1.0+1)) {'q_sold': 7777, 'ri_sold': 7777, 'ri_deposit': 0, 'q_deposit': 0, 'Si_burn': 0, 'action_id': 'R_Swap', 'agent_id': 5, 'asset_id': 'i', 'direction': 'ij', 'direction_q': 'test_r_for_r', 'purchased_asset_id': 'j',} r_to_r_pool threshold = Ri**(-a) + (Ck/Ci)*Rk**(-a) - (Ri + delta_Ri)**(-a) 1.0077169850075958e-06 = 1000000**(-1.0) + (1.0/1)*1000000**(-1.0) -(1000000 + 7777)**(-1.0) delta_Rk = ( (Ci/Ck)*Ri**(-a) - (Ci/Ck)*(Ri + delta_Ri)**(-a) + Rk**(-a) )**(-1/a) - Rk -7657.889191515045 = ( (1/1.0)*1000000**(-1.0) - (1/1.0)*(1000000 + 7777)**(-1.0) + 1000000**(-1.0) )**(-1/1.0) - 1000000 R added to pool of i = 7777 R removed from pool of j = 7657.889191515045 Pool before {'i': {'R': 1000000, 'S': 1000000, 'C': 1, 'P': 2.0, 'dP': 0}, 'j': {'R': 1000000, 'S': 1000000, 'C': 1.0, 'P': 2.0}} Pool after r_to_q_pool {'i': {'R': 1007777, 'S': 1000000, 'C': 1, 'P': 2.0, 'dP': 0}, 'j': {'R': 1000000, 'S': 1000000, 'C': 1.0, 'P': 2.0}} Pool after q_to_r_pool {'i': {'R': 1007777, 'S': 1000000, 'C': 1, 'P': 2.0, 'dP': 0}, 'j': {'R': 992342.110808485, 'S': 1000000, 'C': 1.0, 'P': 2.0}} R to R swap called threshold = Ri**(-a) + (Ck/Ci)*Rk**(-a) - (Ri + delta_Ri)**(-a) 1.0153157783830303e-06 = 1007777**(-1.0) + (1.0/1)*992342.110808485**(-1.0) -(1007777 + 7777)**(-1.0) update_price_a key:i R=1007777 | P=2.0 | C=1 P_new = (Q * Y**(a)) * (C / R**(a+1)) 1.9692511636848313 = (4000000 * 500000.0**(1.0)) * (1 / 1007777**(1.0+1)) dP = P_new - P -0.03074883631516867 = 1.9692511636848313 - 2.0 update_price_a key:j R=992342.110808485 | P=2.0 | C=1.0 P_new = (Q * Y**(a)) * (C / R**(a+1)) 2.030987043745598 = (4000000 * 500000.0**(1.0)) * (1.0 / 992342.110808485**(1.0+1)) dP = P_new - P 0.03098704374559791 = 2.030987043745598 - 2.0 Total execution time: 0.24s ``` ## Symbolic math model of Omnipool in SMath For deep understanding of Omnipool mechanics it was decided to create Smath model. SMath is free analog of MathCAD, programm with central interface is an interactive notebook in which equations and expressions are created and manipulated in the same graphical format in which they are presented (WYSIWYG). Everything is available in Desktop and Web version It is very useful that you can change any variable and all other variables and outputs will change immediately like in Excel. Extremely useful because model implementation is in the same form as in **omnipool whitepaper** As a comment for each important formula there is Python and traditional implementation In addition to CADCAD model, several features like **slippage calculation** were implemented **Example for R to R swap with a=1 and delta_Ri=7777.** Results are same as from CADCAD model **(You can check that resuts are same as with CADCAD tracing before)**: > How it looks like ![](https://gcdn.pbrd.co/images/GEk9nxYzLzTV.gif) > Input parameters and initial calculations ![](https://i.ibb.co/z5F0VxL/1.png) > Checking threshold, calculating amount of token received, slippage for Omnipool and Uniswap, new pool parameters ![](https://gcdn.pbrd.co/images/H6KU99gECUVd.png) > Checking threshold, update prices, final checks ![](https://gcdn.pbrd.co/images/FG2l3WrdIvSo.png) ## Omnipool model behavior with different input parameters. Sensitivity analysis of parameter "a" Here is results of omnipool R to R swap for different a > Modelling results with different a=[0.95 0.99 1 1.01 1.05] and delta_Ri=7777 ![](https://gcdn.pbrd.co/images/WlI9dWYjHloj.png) > Difference between Tests and Test 3 (a=1) ![](https://gcdn.pbrd.co/images/c5qETpnGd9Ih.png) We can make **several conclusions** based on sensitivity analisys: * For increasing a we have decreasing Y * For increasing a we have decreasing delta_Rj. For some point near a>1 we start get less j token than i token we send to pool * a=1 -> initial token prices are equal. a>1 -> initial Pi<Pj. a<1 -> initial Pi>Pj **Slippage conclusions:** * For all a, Omnipool slippage is higher than UniSwap slippage, twice higher on average * Higher a -> less slippage and closer to UniSwap level slippage ## Omnipool model behavior stress test under extreme conditions Here is results of omnipool R to R swap for different extreame conditions. Lets assume 2 scenarios 1. Asset i become toxic asset and market participant want to sell it for j. Size is equal to 100% of i in the pool. a=1 (Test 6) 2. Asset i completely lose value and market participant want to sell it for j. Size is equal to 1000% of i in the pool. a=1 (Test 7) > Modelling results with extream add of i to pool (100% and 1000% of i pool size) ![](https://gcdn.pbrd.co/images/taasMc4Mjrlv.png) We can make **several conclusions** based on stress test analysis: * For increasing delta_Ri we get increasing Omnipool delta_Rj, and max level expected around -500 000 (50% of j in pool). For uniswap max delta_Rj lever is closer to -1 000 000 (100% of j in pool) * Slippage is higher for omnipol model * Dramatic price change * In case if asset i loose value it is still possible for market participant to remove value from pool in a short time by selling huge ampunt of i asset * We need fee mechanism for stopping drain of value from pool in case of market distress ## Potential way to resolve part of "Toxic asset problem" using volatility-dependent fee Omnipool model will contain a lot of differet assets. If one of this assets will become toxic, market participants will start to sell this asset in exchange for assets with value. If we will not stop this process using some type of triggers or dynamic fee changing, market participants will add to pool toxic asset with no value and will receive good assets in exchange. Result of it will be draining value from pool and loosing funds of liquidity providers Developed solution should satisfy several requierements: * It should not be computantional intensive, because every calculation on blockchain costs a lot of funds * Good reaction in case of price decreasing of potential toxic asset * Using only on-chain data One of potential fee implementation is to add denominator for delta_Rj. As an example we can say that amount of fee should dramatically increase in case of relative price decrease more or around -0.2 (20%) in Q or other. Price can be determined as pool price specified amount of blocks ago vs price in current or previous block. Denominator can be selected as $$5000000*{RelativePriceChange}^8$$ 8 and 5000000 can be changed based on required max level of price decrease Results confirms that for small price movements there is not a lot of difference in token received with fee or not (-476 190 vs -476 097), but for price decrease around -0.2 denominator achive 13.8 and amout of token receive is dramatically decreasing (-476 190 vs -34 507) > Fee sructure ![](https://gcdn.pbrd.co/images/oF0eTS6VMdiS.png) * If it would be needed to make fee sensitive to several time periods and with different sensitivity, model can be easily changed * Here is an example with new delta_for_period2 (can be 5000 blocks for example) and new parameters 10 and 10 000 000. * If one of delta_for_period1 or delta_for_period2 will change more than we want, fee will increase dramatically, decreasing incentives for toxic asset selling >Modified fee ![](https://i.imgur.com/NFwnEzi.png) * Also we can add fee that will decrease delta_Rj with trade size relative to pool size without reliance on price movements # Futher developement * Similar models for Q to R, R to Q, Liquidity Add/Withdrawal which is very useful for model understanding and huge time saving for new researches * Model update with new specification of Omnipool (last available was V2) * Tests for potential vulnerabilities of model and finding new ways for improvement * Testing and implementing of new fee mechanisms * CADCAD Omnipool model modifications and development * Getting feedback from team * Taking part in development of “incentivized trading game” with involving of people * MOAR hydration :snake: :snake: :snake: :snake: :snake: