{"id":21044132,"url":"https://github.com/drift-labs/drift-sim","last_synced_at":"2025-05-15T17:32:38.834Z","repository":{"id":37241961,"uuid":"501023181","full_name":"drift-labs/drift-sim","owner":"drift-labs","description":null,"archived":false,"fork":false,"pushed_at":"2022-11-29T13:55:51.000Z","size":24379,"stargazers_count":8,"open_issues_count":0,"forks_count":13,"subscribers_count":2,"default_branch":"master","last_synced_at":"2023-03-11T19:41:25.331Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Jupyter Notebook","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/drift-labs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-06-07T22:28:35.000Z","updated_at":"2023-01-15T07:22:19.000Z","dependencies_parsed_at":"2023-01-21T08:04:52.917Z","dependency_job_id":null,"html_url":"https://github.com/drift-labs/drift-sim","commit_stats":null,"previous_names":[],"tags_count":null,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drift-labs%2Fdrift-sim","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drift-labs%2Fdrift-sim/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drift-labs%2Fdrift-sim/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drift-labs%2Fdrift-sim/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/drift-labs","download_url":"https://codeload.github.com/drift-labs/drift-sim/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225365756,"owners_count":17462973,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-19T14:15:40.232Z","updated_at":"2024-11-19T14:15:40.829Z","avatar_url":"https://github.com/drift-labs.png","language":"Jupyter Notebook","readme":"## Drift-Sim: Simulation Framework for Drift-v2\n\nThe goals of the drift-sim repository is \n- research and prototype fast with a python implementation of the DAMM\n- backtest events against the smart-contract protocol and view the results overtime \n\n## Overview\n\n### Prototyping in Python \n\nThe first component of the simulations include a python implementation of Drift's \nDAMM - most of the math/implementation used is also used in the python SDK. This \nincludes Agents (which interact with the DAMM), Events (which are produced on each \ninteraction with the DAMM), and State (the market, user, etc. structures). A full write\nup on the python simulation setup can be found [here](https://www.notion.so/driftprotocol/Drift-Simulation-Framework-Guide-9bcff2bddf37445aa39c696bc3bfa705). The code of the python \nsimulations can be found in `sim/`. \n\n### Backtesting Events against the Protocol \n\nWhile running agents against the python simulation we produce event files which list all the \nactions taken. For example, one looks like: \n```\nevent_name,timestamp,parameters\ndeposit_collateral,0.0,\"{\"\"deposit_amount\"\": 1998590197697, \"\"user_index\"\": 0, \"\"username\"\": \"\"LP\"\"}\"\nadd_liquidity,142.0,\"{\"\"market_index\"\": 0, \"\"token_amount\"\": 42554684114, \"\"user_index\"\": 1}\"\nsettle_lp,183.0,\"{\"\"market_index\"\": 0, \"\"user_index\"\": 1}\"\nopen_position,227.0,\"{\"\"direction\"\": \"\"long\"\", \"\"market_index\"\": 0, \"\"quote_amount\"\": 790100000, \"\"user_index\"\": 2}\"\nremove_liquidity,10000000000227.0,\"{\"\"lp_token_amount\"\": -1, \"\"market_index\"\": 0, \"\"user_index\"\": 1}\"\nclose_position,10000000000228.0,\"{\"\"market_index\"\": 0, \"\"user_index\"\": 1}\"\n...\n```\n\nThese events are then backtested on the protocol in `backtest/main.py` with the following event loop\nwhich loops through each event and then executes it. \n\n```python \nfor i in tqdm(range(len(events))):\n  ix: TransactionInstruction\n  if event.event_name == DepositCollateralEvent._event_name:\n      continue\n\n  elif event.event_name == MidSimDepositEvent._event_name:\n      event = Event.deserialize_from_row(MidSimDepositEvent, event)\n      assert event.user_index in user_chs, 'user doesnt exist'\n      ch: SDKClearingHouse = user_chs[event.user_index]\n      ix = await event.run_sdk(ch, admin_clearing_house, spot_mints)\n      ix_args = event.serialize_parameters()\n      print(f'=\u003e {event.user_index} depositing...')\n\n  elif event.event_name == OpenPositionEvent._event_name: \n      event = Event.deserialize_from_row(OpenPositionEvent, event)\n      assert event.user_index in user_chs, 'user doesnt exist'\n\n      ch: SDKClearingHouse = user_chs[event.user_index]\n      ix = await event.run_sdk(ch, init_leverage, oracle_program, adjust_oracle_pre_trade=False)\n      if ix is None: continue\n      ix_args = place_and_take_ix_args(ix[1])\n      print(f'=\u003e {event.user_index} opening position...')\n\n  elif event.event_name == ClosePositionEvent._event_name: \n      event = Event.deserialize_from_row(ClosePositionEvent, event)\n      assert event.user_index in user_chs, 'user doesnt exist'\n\n      ch: SDKClearingHouse = user_chs[event.user_index]\n      ix = await event.run_sdk(ch, oracle_program, adjust_oracle_pre_trade=True)\n      if ix is None: continue\n      ix_args = place_and_take_ix_args(ix[1])\n      print(f'=\u003e {event.user_index} closing position...')\n```\n\n### How we track the state on backtests\n\nTo backtest against the protocol we load the drift program onto a local validator \nwhich includes a geyser plugin that records the account states in a postgresql db. \nAfter each sim, we parse the database's accounts using AnchorPy and export them to a .csv \nformat. The postgresql geyser plugin is the `solana-accountsdb.../` folder.\n\n### Adding New Events\n\nto include new events one would need to \n- create a new Event class in  `sim/events.py` which implements `run` (what it should do in the python \nimplementation) and `run_sdk` (what it should do with tha actual protocol)\n- and implement a new branch: `elif event.event_name == NEW_EVENT._event_name:` in the event loop \n\nNot required but usually you would also add an Agent which would produce the event you want and run a simulation with it -- see `scripts/workspace/` files to understand how it works with other agents. For example in simple.py, we create an agent which will Open and Close a position multiple times, add it to the list of agents, \nand then run the agents against the python implementation with the `run_trial(agents, ch, path)` call. \n\n```python \nagent = MultipleAgent(\n    lambda: OpenClose.random_init(max_t[market_index], user_idx, market_index, short_bias=0.5),\n    n_times, \n)\nagents.append(agent)\n\n# !! \nrun_trial(agents, ch, path)\n```\n\n## Dev Setup\n\n## install python packages \n```bash\n# creates a virtualenv called \"venv\"\npython3.10 -m venv venv\nsource venv/bin/activate\npip install -r requirements.txt\n# setup other submodules\nbash setup.sh \n```\n\n## install postgresql \n\nrequirements / setup help:\n- you'll need python 3.10\n- to satisfy the requirements.tx you may need to install some \n- on mac OS, you can use homebrew\n  - `brew install postgresql`\n\n## file structure \n\n- `scripts/workspace/`: folder to produce events.csv/experiments by using agents or specific events against python protocol\n- `backtest/main.py`: run an events.csv/experiment against the actual rust protocol \n- `sim/`: python simulation files (agents, events, python clearing_house, etc.)\n- `solana-accountsdb-...`: geyser plugin to record changes in program account throughout the backtest and analyze the change in state\n- `driftpy`: drift python sdk\n- `experiments/`: folder to store initial data + events to start backtest in `init/` and the state over time in `results/` (after running backtest/main.py)\n\n## backtest\n\n```bash\ncd scripts/workspace/\npython simple.py # generate events.csv files of a simple market (results in experiments/init/simple)\ncd ../../backtest \npython main.py --events ../experiments/init/simple -t no_oracle_guards # backtest the events against the v2 protocol \nls ../experiments/results/simple/no_oracle_guards # behold the results \n```\n\n## run the python simulation tests \n\n`python test.py` \n\n## update scripts\n\n```\ngit submodule update --remote --merge\npip install driftpy/ --upgrade\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdrift-labs%2Fdrift-sim","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdrift-labs%2Fdrift-sim","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdrift-labs%2Fdrift-sim/lists"}