{"id":22609085,"url":"https://github.com/bitfinexcom/bfx-hf-strategy-py","last_synced_at":"2025-04-11T06:21:51.414Z","repository":{"id":37600433,"uuid":"154824258","full_name":"bitfinexcom/bfx-hf-strategy-py","owner":"bitfinexcom","description":null,"archived":false,"fork":false,"pushed_at":"2022-06-21T21:41:15.000Z","size":247,"stargazers_count":40,"open_issues_count":15,"forks_count":30,"subscribers_count":16,"default_branch":"master","last_synced_at":"2024-04-16T10:46:49.169Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bitfinexcom.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-10-26T11:29:52.000Z","updated_at":"2023-12-22T15:20:55.000Z","dependencies_parsed_at":"2022-08-25T22:11:45.009Z","dependency_job_id":null,"html_url":"https://github.com/bitfinexcom/bfx-hf-strategy-py","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/bitfinexcom%2Fbfx-hf-strategy-py","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitfinexcom%2Fbfx-hf-strategy-py/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitfinexcom%2Fbfx-hf-strategy-py/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitfinexcom%2Fbfx-hf-strategy-py/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bitfinexcom","download_url":"https://codeload.github.com/bitfinexcom/bfx-hf-strategy-py/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228747451,"owners_count":17966323,"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-12-08T15:10:51.906Z","updated_at":"2024-12-08T15:10:52.491Z","avatar_url":"https://github.com/bitfinexcom.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Honey Framework for Python\r\nThis repo serves as a framework for creating trading bots/strategies on the Bitfinex platform. It consists of a set of order methods and helps with backtests on historical candle/trade data, which can be transitioned seamlessly to trading on the live markets.\r\n\r\nStrategies written using this framework must define a set of update methods, called on each tick (with either a trade or a candle), along with a set of indicators which are automatically updated on each tick. The indicators are made available to the strategy methods, and can be queried to direct trading behavior.\r\n\r\n\r\nInstall bfx-hf-indicators-py:\r\n```sh\r\ngit clone https://github.com/bitfinexcom/bfx-hf-indicators-py\r\ncd bfx-hf-indicators-py\r\nexport PYTHONPATH=\"$(pwd):$PYTHONPATH\"\r\n```\r\n\r\nRun example ema_cross backtest:\r\n```sh\r\n# in bfx-strategy-hf-py\r\ncd examples\r\npython3 ema_cross.py\r\n```\r\n\r\n## Features\r\n- Execute on Live or with backtest data\r\n- Realtime data feeds\r\n- Simple interface\r\n- Quick websocket connections\r\n- Open/Close/Update positions\r\n\r\n## Quickstart\r\n\r\n### Defining a strategy\r\nTo define a trading strategy, first we have to create a new object that implements the `hfstrategy` class. Then we need to decide on a set of indicators to use and bind them to the classes `indicators` variable. Strategies created with it can be used with bfx-hf-backtest or with the exec method to run on the live market. An example strategy follows below:\r\n```python\r\nfrom hfstrategy import Strategy\r\nfrom bfxhfindicators import EMA\r\n\r\nclass EMAStrategy(Strategy):\r\n  indicators = {\r\n    'emaL': EMA([100]),\r\n    'emaS': EMA([20])\r\n  }\r\n\r\n  async def onEnter(self, update):\r\n    # Do something\r\n\r\n  async def onUpdateLong(self, update):\r\n    # Do something\r\n```\r\nThe above strategy defines two EMA indicators, emaL and emaS, with periods of 100 and 20 respectively, and 3 update methods; In total, 5 update methods are available:\r\n\r\n- `onEnter` - called when no position is open\r\n- `onUpdateLong` - called when a long position is open\r\n- `onUpdateShort` - called when a short position is open\r\n- `onUpdate` - called when any position is open\r\n- `onPriceUpdate` - called on every tick\r\n\r\n### Update Handlers\r\n\r\nAll update handlers must be asynchronous, and receive an update json object which has the following fields:\r\n\r\n- `type` - 'candle' or 'trade', indicating which fields are available\r\n- `mts` - Timestamp, in ms\r\n- `price` - Candle or trade price (depends on candlePrice strategy setting)\r\nfor candles, open, high, low, close, and vol are provided\r\n\r\nStrategy state is stored in the strategy object (`self`) and can be queried for historical candle data, indicators \u0026 indicator values, open positions, and previous strategy trades. For an example, see the EMA cross example `onEnter` handler below.\r\n\r\n```python\r\nasync def onEnter(self, update):\r\n  iv = self.indicatorValues()\r\n  emaS = self.indicators['emaS']\r\n\r\n  s = iv['emaS']\r\n  l = iv['emaL']\r\n  if emaS.crossed(l):\r\n    if s \u003e l:\r\n      await self.openLongPositionMarket(\r\n        mtsCreate=update['mts'], price=update['price'], amount=0.1)\r\n    else:\r\n      await self.openShortPositionMarket(\r\n        mtsCreate=update['mts'], price=update['price'], amount=0.1)\r\n\r\n```\r\n\r\n### Managing positions\r\n\r\nThe hfstrategy class exposes a bunch of asynchronous methods to help open/close/update any positions:\r\n\r\n- `open_long_position_market(*args, **kwargs)`\r\n- `open_long_position_limit(*args, **kwargs)`\r\n- `open_long_position(*args, **kwargs)`\r\n- `open_short_position_market(*args, **kwargs)`\r\n- `open_short_position_limit(*args, **kwargs)`\r\n- `open_short_position(*args, **kwargs)`\r\n- `open_position(*args, **kwargs)`\r\n- `update_long_position_market(*args, **kwargs)`\r\n- `update_long_position_limit(*args, **kwargs)`\r\n- `update_long_position(*args, **kwargs)`\r\n- `update_short_position_market(*args, **kwargs)`\r\n- `update_short_position_limit(*args, **kwargs)`\r\n- `update_short_position(*args, **kwargs)`\r\n- `update_position(*args, **kwargs)`\r\n- `close_position_market(*args, **kwargs)`\r\n- `close_position_limit(*args, **kwargs)`\r\n- `close_position(*args, **kwargs)`\r\n\r\nThe price and mtsCreate timestamp must both be provided to all update handlers, even those operating with MARKET orders, in order to record the price and timestamp during backtests. If these are not provided, backtests run via bfx-hf-backtest will fail.\r\n\r\n# Backtesting\r\n\r\nThe Honey Framework comes packed with 4 different executors which can be used to run backtests from various different sources of data and to also execute the strategy on the a live trading account. First we need to import and initialize the Executor class.\r\n\r\n```python\r\nfrom hfstrategy import Executor\r\nexe = Executor(strategy)\r\n```\r\n\r\n### Offline\r\n\r\nThe offline executor accepts the file location of candle data that is store locally. It then begins to run the candle data through the strategy in the same way that the strategy would receive the data if it was running on live data.\r\n\r\n```python\r\nexe.offline(file='btc_candle_data.json', tf='1hr')\r\n```\r\n\r\nOnce the executor has finished it will display a matplotlib visualization of the orders/positions that the strategy created. The chart shows long orders as a green arrow, short orders as a red arrow and position closes as a blue dot. When using an executor that runs forever such as live or backtest_live, pressing CTR-C to kill the script will trigger the chart to render.\r\n\r\n![alt text](https://i.ibb.co/47jL0xL/chart-pic.png \"Back-testing chart example\")\r\n\r\n### Fetching Candles via REST and Backtesting with Local SQLite Storage\r\n\r\nAlternatively you can fetch and locally store the required data from the Bitfinex REST API. The data is cached in a local SQLite database.\r\n\r\n```python\r\nimport time\r\nimport asyncio\r\nnow = int(round(time.time() * 1000))\r\nthen = now - (1000 * 60 * 60 * 24 * 36) # 36 days ago\r\n\r\nloop = asyncio.get_event_loop()\r\nloop.run_until_complete(exe.with_local_database(then, now))\r\n```\r\n\r\n### Live backtesting\r\n\r\nLive backtesting allows you to run the strategy with realtime data pulled from the Bitfinex api but with the order management still being simulated. We recommend that you use this method before running your strategy on a live account.\r\n\r\n```python\r\nexe.backtest_live()\r\n```\r\n\r\n### Live trading\r\n\r\nFinally, once you have tested your strategy and are happy to begin making live trades you can run the strategy using the live executor. For this you will need your api key and secret from your Bitfinex account.\r\n\r\n```python\r\nAPI_KEY=\"\u003cMY_API_KEY\u003e\"\r\nAPI_SECRET=\"\u003cMY_API_SECRET_KEY\u003e\"\r\nexe.live(API_KEY, API_SECRET)\r\n```\r\n\r\n## Examples\r\n\r\nFor more info on how to use this framework please navigate to `/examples` where you will find 3 example strategies including an advanced implementation.\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbitfinexcom%2Fbfx-hf-strategy-py","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbitfinexcom%2Fbfx-hf-strategy-py","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbitfinexcom%2Fbfx-hf-strategy-py/lists"}