{"id":21290023,"url":"https://github.com/mtingers/cxgame","last_synced_at":"2025-03-15T16:12:06.174Z","repository":{"id":145403294,"uuid":"230713068","full_name":"mtingers/cxgame","owner":"mtingers","description":"Cryptocurrency Exchange Game","archived":false,"fork":false,"pushed_at":"2020-01-02T18:14:44.000Z","size":95,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-01-22T06:11:50.197Z","etag":null,"topics":["bitcoin","cryptocurrency","cryptocurrency-exchanges","cryptocurrency-trading-bot","educational","game","learning-exercise"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mtingers.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-12-29T06:37:01.000Z","updated_at":"2020-02-13T16:32:54.000Z","dependencies_parsed_at":"2023-03-29T18:34:04.534Z","dependency_job_id":null,"html_url":"https://github.com/mtingers/cxgame","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtingers%2Fcxgame","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtingers%2Fcxgame/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtingers%2Fcxgame/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtingers%2Fcxgame/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mtingers","download_url":"https://codeload.github.com/mtingers/cxgame/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243754094,"owners_count":20342542,"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":["bitcoin","cryptocurrency","cryptocurrency-exchanges","cryptocurrency-trading-bot","educational","game","learning-exercise"],"created_at":"2024-11-21T12:44:27.432Z","updated_at":"2025-03-15T16:12:06.152Z","avatar_url":"https://github.com/mtingers.png","language":"Python","readme":"# cxgame: A Cryptocurrency Exchange Game\n\ncxgame is a fake cryptocurrency exchange that has a few goals in mind:\n1. Educational: Learn or test out new programmatic trading strategies.\n2. A game: Battle other bots to test your skills.\n\n# Components\n\ncxgame has 4 primary components:\n1. `cxgame.server.CxExchange` -- The exchange server\n2. `cxgame.server.CxFeed` -- The broadcast channel. Exchange activity is\n    broadcasted to all connected clients here (e.g. orders, server messages)\n3. `cxgame.client.CxClient` -- The API for creating your own client to\n    communicate with the CxExchange server.\n4. `cxgame.server.CxServer` -- Wraps and controls `CxExchange` and `CxFeed`.\n\ncxgame can run in various modes (time limit, endless, whitelisted users, etc).\nSee the documentation below for server and client examples. Also take a look\nat the `examples/` directory for more information.\n\n# Contributing\n\nIf you find missing features or bugs, please open an issue or a pull\nrequest.\n\n# Install\n\nNo PyPI package as of yet. Install using:\n1. `python3 -m venv  venv`\n2. `source venv/bin/activate`\n3. `pip install -r requirements.txt`\n4. `python setup.py install`\n\nAfter install, the command `cxserve` will be available. Running it starts the\nexchange and feed servers with default options (see: `cxgame.server.main()`).\n\n# The Exchange \u0026 Feed Servers (cxgame.server.CxServer)\n\nThe primary websocket servers that run the exchange and broadcast feed:\n\n1. Registration and authentication. Stores user credentials.\n2. Stores user wallets (USD and crypto).\n3. Sets the (mid) market price.\n4. Handles limit orders (buy, sell, cancel).\n5. Handles market orders (buy \u0026 sell at market price).\n6. Stores past completed order detail.\n7. Stores past filled orders (order matches).\n8. Sends information on the feed channel to broadcast messages to clients.\n\n## Init Options\n\n`CxServer()` __init__ options:\n\n* exchange_port -- Websocket `CxExchange` listen port.\n  default: 9877 (int)\n\n* feed_port -- Websocket `CxFeed` listen port.\n  default: 9876 (int)\n\n* bind -- Address(es) to listen on.\n  default: 0.0.0.0 (str)\n\n* usd_start -- New users will start with this much USD in their wallet.\n  default: 10000.00 (Decimal, int, str, or float. Auto-converts to Decimal.)\n\n* crypto_start -- New users will start with this much crypto in their wallet.\n  default: 10.0 (Decimal, int, str, or float. Auto-converts to Decimal.)\n\n* user_limit -- The max amount of users allowed to connect.\n  default: None (int)\n\n* time_limit -- Exchange will run for this amount of time (in seconds).\n  default: None (int)\n\n* whitelist -- A whitelist of users allowed to connect. All users must be\n  connected before the exchange will run.\n  default: None (list[str])\n\n* pem_file -- Path to SSL key/cert file.\n  default: None (str)\n\n* ssl_verify -- Specify if SSL connections/certs are verified (set to False for\n  self signed).\n  default: True (bool)\n\n* admin_secret -- The admin password. Required to run certain commands like\n  shutdown.\n  default: admin (str)\n\n* is_started -- Tells the server to accept commands or not. If False, commands\n  are rejected until the 'start' command is issued.\n  default: True (bool)\n\nNOTE: `CxServer` is a wrapper that passes down options to `CxExchange` and\n`CxFeed`.\n\n## Running A Server\n\nThe command `cxserve` can be used to launch the exchange \u0026 feed server threads\nand comes with command line option parsing.\n\nTo manually run a server, it can be done a few ways. Look at\n`examples/server.py` for a more in-depth example.\n\n# Exchange and Client Commands\n\nThe following is a list and example of the exchange server's commands. These\nare also implemented on the client side `CxClient`, as shown in the examples.\n\nNOTE: The response is a `Response()` class from `cxgame.client.Response`. It\ncontains these variables:\n1. status -- True or False\n2. msg -- Free text response. Helpful for debugging errors.\n3. data -- The data line. It has a varying type in the response and depends on\n   the type method that was called.\n4. raw -- The raw json string returned from the server. For debugging purposes.\n\n## What is the `r()` Helper Method?\n\nThe `CxClient.r()` helper method is a shortcut that wraps `websockets.connect`\nand is short for `run`.\n\nIt does create a new connection on every call, so not ideal for long running\nclients and defeats the purpose of a websocket, but useful for testing or\ndemonstration purposes. See the `cxgame/client.py` source code `r()` and\n`runcmd()` methods for more explanation.\n\n## register\nRegister a new user on the exchange. The response will contain a token for\nfuture authentication.\n\n```python\nfrom cxgame.client import CxClient\n```\n\n```python\ncx = CxClient(user='new-username123', uri='ws://mtingers.com:9877')\nresponse = cx.r('register')\nprint(response.status, response.msg)\n\n# If successful, store the token for later auth\nif response.status:\n    token = response.data\n\n```\n\n## auth\n```python\ncx = CxClient(user='root', uri='ws://mtingers.com:9877', token='123...')\nresponse = cx.r('auth')\n```\n\n## bcast\nBroadcasts a message on the feed server:\n```python\nresponse = cx.r('broadcast', 'Hello, World!')\n```\n\n## buy\nPlaces a maker limit buy order:\n```python\nprice = '999.99'\nsize = '1.5'\nresponse = cx.r('buy', price, size)\nprint('order:', response.data)\n```\n\n## buy_market\nPlaces a market buy order. This attempts to match limit sell orders that are\nthe closest in price at the time of the market order:\n```python\namount = '999.99' # The amount of your wallet's USD to use for this buy.\nresponse = cx.r('buy_market', amount)\nprint('order:', response.data)\n```\n\n## sell\nPlaces a maker limit sell order:\n```python\nprice = '1000.01'\nsize = '1.5'\nresponse = cx.r('sell', price, size)\n```\n\n## sell_market\nPlaces a market sell order. This attempts to match limit buy orders that are\nthe closest in price at the time of the market order:\n```python\namount = '2.25' # The amount of your wallet's crypto to use for this sell.\nresponse = cx.r('sell_market', amount)\n```\n\n## price\n```python\nmid_market_price = cx.r('price').data\n```\n\n## orders\nGet your open orders:\n```python\nmy_orders = cx.r('orders').data\nfor order in my_orders:\n    print('id={} price={}'.format(order['id'], order['price']))\n```\n\n## all_orders\nGet all open orders (all users):\n```python\nall_orders = cx.r('all_orders').data\nfor order in all_orders:\n    print('user={} id={} price={}'.format(\n        order['user'], order['id'], order['price'])\n    )\n```\n\n## wallets\nGet your current wallets for USD and crypto:\n```python\nwallets = cx.r('wallets').data\nprint('crypto={} usd={}'.format(wallets['crypto'], wallets['usd']))\n```\n\n## cancel\nCancel an order, by order ID:\n```python\ncancelled = cx.r('cancel', order_id)\n```\n\n## fills\nGet your fills. This is orders that were matched partially or full:\n```python\nmy_fills = cx.r('fills').data\nfor fill in my_fills:\n    print(fill)\n```\n\n## completed\nGet your completed orders. These are orders that were completed/filled.\n```python\nmy_completed_orders = cx.r('completed').data\nfor order in my_completed_orders:\n    print(order)\n```\n## audit\nFor debugging and admin use. Runs an audit on all order status to detect bugs\nin the code (invalid states).\n\n## shutdown\n```python\ncx = CxClient(user='root', uri='ws://mtingers.com:9877', token='123...')\nresponse = cx.r('auth')\nresponse = cx.r('shutdown', 'adminpassword123')\n```\n\n## start\n```python\ncx = CxClient(user='root', uri='ws://mtingers.com:9877', token='123...')\nresponse = cx.r('auth')\nresponse = cx.r('start', 'adminpassword123')\n```\n\n## pause\n```python\ncx = CxClient(user='root', uri='ws://mtingers.com:9877', token='123...')\nresponse = cx.r('auth')\nresponse = cx.r('pause', 'adminpassword123')\n```\n\n# Test Servers\n\nAn open test exchange is running at: `ws://mtingers.com:9877`\nThe feed for this server is at: `ws://mtingers.com:9876`\n\n\n# TODO\n\n1. Add admin user auth\n2. Finish mypy typing\n3. Finish docstrings\n4. Add logging\n5. Add state saving\n6. Add tests\n7. Add PyPI\n8. Add server CLI arg parsing\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmtingers%2Fcxgame","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmtingers%2Fcxgame","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmtingers%2Fcxgame/lists"}