jetblack-fixengine


Namejetblack-fixengine JSON
Version 1.0.0a5 PyPI version JSON
download
home_pagehttps://github.com/rob-blackbourn/jetblack-fixengine
SummaryA pure Python implementation of the FIX protocol
upload_time2023-04-06 09:54:55
maintainer
docs_urlNone
authorRob Blackbourn
requires_python>=3.8,<4.0
licenseApache-2.0
keywords fix fix-engine
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # jetblack-fixengine

A pure python asyncio FIX engine.

## Status

This is work in progress.

## Installation

The package can be install from the pie store.

```bash
pip install jetblack-fixengine
```

## Overview

This project provides a pure Python, asyncio implementation of
a FIX engine, supporting both initiators and acceptors.

The engine uses the [jetblack-fixparser](https://github.com/rob-blackbourn/jetblack-fixparser)
package to present the FIX messages a plain Python objects. For example, a `LOGON` message
can be sent as follows:

```python
await send_message({
    'MsgType': 'LOGON',
    'MsgSeqNum': 42,
    'SenderCompID': 'ME',
    'TargetCompID': 'BANK OF SOMEWHERE',
    'SendingTime': datetime.now(timezone.utc),
    'EncryptMethod': "NONE",
    'HeartBtInt': 30
})
```

### FIX Protocols

The FIX protocol is a combination of *well known* messages (like `LOGON`)
and *custom* messages (like an order to buy or sell). The protocol
has evolved through a number of different versions providing new features.

Because of this the protocols are provided by config files. Historically
`XML` was used. While this is supported, `yaml` is preferred and some
example protocols are provided in the
[etc](https://github.com/rob-blackbourn/jetblack-fixengine/tree/master/etc)
folder.

Currently supported versions are 4.0, 4.1, 4.2, 4.3, 4.4.

### Initiators

An initiator is a class which inherits from `FIXApplication`, and implements a
few methods, and has access to `send_message` from the `fix_engine`. Here is an example.

```python
import asyncio
import logging
from pathlib import Path
from typing import Mapping, Any

from jetblack_fixparser import load_yaml_protocol
from jetblack_fixengine import (
    FileStore,
    start_initiator,
    InitiatorConfig,
    FIXApplication,
    FIXEngine
)

LOGGER = logging.getLogger(__name__)


class MyInitiator(FIXApplication):
    """An instance of the initiator"""

    async def on_logon(
            self,
            _message: Mapping[str, Any],
            fix_engine: FIXEngine
    ) -> None:
        LOGGER.info('on_logon')

    async def on_logout(
            self,
            _message: Mapping[str, Any],
            fix_engine: FIXEngine
    ) -> None:
        LOGGER.info('on_logout')

    async def on_application_message(
            self,
            _message: Mapping[str, Any],
            fix_engine: FIXEngine
    ) -> None:
        LOGGER.info('on_application_message')


app = MyInitiator()
config = InitiatorConfig(
    '127.0.0.1',
    9801,
    load_yaml_protocol(Path('etc') / 'FIX44.yaml'),
    'INITIATOR1',
    'ACCEPTOR',
    FileStore(Path('store'))
)

logging.basicConfig(level=logging.DEBUG)

asyncio.run(
    start_initiator(app, config)
)
```

### Acceptor

The acceptor works in the same way as the initiator. Here is an example:

```python
import asyncio
import logging
from pathlib import Path
from typing import Mapping, Any

from jetblack_fixparser import load_yaml_protocol
from jetblack_fixengine import (
    FileStore,
    start_acceptor,
    AcceptorConfig,
    FIXApplication,
    FIXEngine
)


LOGGER = logging.getLogger(__name__)


class MyAcceptor(FIXApplication):
    """An instance of the acceptor"""

    async def on_logon(
            self,
            _message: Mapping[str, Any],
            _fix_engine: FIXEngine
    ) -> None:
        LOGGER.info('on_logon')

    async def on_logout(
            self,
            _message: Mapping[str, Any],
            _fix_engine: FIXEngine
    ) -> None:
        LOGGER.info('on_logout')

    async def on_application_message(
            self,
            _message: Mapping[str, Any],
            _fix_engine: FIXEngine
    ) -> None:
        LOGGER.info('on_application_message')


logging.basicConfig(level=logging.DEBUG)

app = MyAcceptor()
config = AcceptorConfig(
    '0.0.0.0',
    9801,
    load_yaml_protocol(Path('etc') / 'FIX44.yaml'),
    'ACCEPTOR',
    'INITIATOR1',
    FileStore(Path("store"))
)

asyncio.run(
    start_acceptor(
        app,
        config
    )
)
```

Note that throwing the exception `LogonError` from `on_logon` will reject
the logon request.

### Stores

The engines need to store their state. Two stores are currently provided:
a file store (`FileStore`) and sqlite (`SqlStore`).

## Implementation

The engines are implemented as state machines. This means they can be
tested without the need for IO.

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/rob-blackbourn/jetblack-fixengine",
    "name": "jetblack-fixengine",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.8,<4.0",
    "maintainer_email": "",
    "keywords": "fix,fix-engine",
    "author": "Rob Blackbourn",
    "author_email": "rob.blackbourn@googlemail.com",
    "download_url": "https://files.pythonhosted.org/packages/06/45/5613673f3851bd74e91dd979ec08c275b86645b1b32e1518ab44ed2a2786/jetblack-fixengine-1.0.0a5.tar.gz",
    "platform": null,
    "description": "# jetblack-fixengine\n\nA pure python asyncio FIX engine.\n\n## Status\n\nThis is work in progress.\n\n## Installation\n\nThe package can be install from the pie store.\n\n```bash\npip install jetblack-fixengine\n```\n\n## Overview\n\nThis project provides a pure Python, asyncio implementation of\na FIX engine, supporting both initiators and acceptors.\n\nThe engine uses the [jetblack-fixparser](https://github.com/rob-blackbourn/jetblack-fixparser)\npackage to present the FIX messages a plain Python objects. For example, a `LOGON` message\ncan be sent as follows:\n\n```python\nawait send_message({\n    'MsgType': 'LOGON',\n    'MsgSeqNum': 42,\n    'SenderCompID': 'ME',\n    'TargetCompID': 'BANK OF SOMEWHERE',\n    'SendingTime': datetime.now(timezone.utc),\n    'EncryptMethod': \"NONE\",\n    'HeartBtInt': 30\n})\n```\n\n### FIX Protocols\n\nThe FIX protocol is a combination of *well known* messages (like `LOGON`)\nand *custom* messages (like an order to buy or sell). The protocol\nhas evolved through a number of different versions providing new features.\n\nBecause of this the protocols are provided by config files. Historically\n`XML` was used. While this is supported, `yaml` is preferred and some\nexample protocols are provided in the\n[etc](https://github.com/rob-blackbourn/jetblack-fixengine/tree/master/etc)\nfolder.\n\nCurrently supported versions are 4.0, 4.1, 4.2, 4.3, 4.4.\n\n### Initiators\n\nAn initiator is a class which inherits from `FIXApplication`, and implements a\nfew methods, and has access to `send_message` from the `fix_engine`. Here is an example.\n\n```python\nimport asyncio\nimport logging\nfrom pathlib import Path\nfrom typing import Mapping, Any\n\nfrom jetblack_fixparser import load_yaml_protocol\nfrom jetblack_fixengine import (\n    FileStore,\n    start_initiator,\n    InitiatorConfig,\n    FIXApplication,\n    FIXEngine\n)\n\nLOGGER = logging.getLogger(__name__)\n\n\nclass MyInitiator(FIXApplication):\n    \"\"\"An instance of the initiator\"\"\"\n\n    async def on_logon(\n            self,\n            _message: Mapping[str, Any],\n            fix_engine: FIXEngine\n    ) -> None:\n        LOGGER.info('on_logon')\n\n    async def on_logout(\n            self,\n            _message: Mapping[str, Any],\n            fix_engine: FIXEngine\n    ) -> None:\n        LOGGER.info('on_logout')\n\n    async def on_application_message(\n            self,\n            _message: Mapping[str, Any],\n            fix_engine: FIXEngine\n    ) -> None:\n        LOGGER.info('on_application_message')\n\n\napp = MyInitiator()\nconfig = InitiatorConfig(\n    '127.0.0.1',\n    9801,\n    load_yaml_protocol(Path('etc') / 'FIX44.yaml'),\n    'INITIATOR1',\n    'ACCEPTOR',\n    FileStore(Path('store'))\n)\n\nlogging.basicConfig(level=logging.DEBUG)\n\nasyncio.run(\n    start_initiator(app, config)\n)\n```\n\n### Acceptor\n\nThe acceptor works in the same way as the initiator. Here is an example:\n\n```python\nimport asyncio\nimport logging\nfrom pathlib import Path\nfrom typing import Mapping, Any\n\nfrom jetblack_fixparser import load_yaml_protocol\nfrom jetblack_fixengine import (\n    FileStore,\n    start_acceptor,\n    AcceptorConfig,\n    FIXApplication,\n    FIXEngine\n)\n\n\nLOGGER = logging.getLogger(__name__)\n\n\nclass MyAcceptor(FIXApplication):\n    \"\"\"An instance of the acceptor\"\"\"\n\n    async def on_logon(\n            self,\n            _message: Mapping[str, Any],\n            _fix_engine: FIXEngine\n    ) -> None:\n        LOGGER.info('on_logon')\n\n    async def on_logout(\n            self,\n            _message: Mapping[str, Any],\n            _fix_engine: FIXEngine\n    ) -> None:\n        LOGGER.info('on_logout')\n\n    async def on_application_message(\n            self,\n            _message: Mapping[str, Any],\n            _fix_engine: FIXEngine\n    ) -> None:\n        LOGGER.info('on_application_message')\n\n\nlogging.basicConfig(level=logging.DEBUG)\n\napp = MyAcceptor()\nconfig = AcceptorConfig(\n    '0.0.0.0',\n    9801,\n    load_yaml_protocol(Path('etc') / 'FIX44.yaml'),\n    'ACCEPTOR',\n    'INITIATOR1',\n    FileStore(Path(\"store\"))\n)\n\nasyncio.run(\n    start_acceptor(\n        app,\n        config\n    )\n)\n```\n\nNote that throwing the exception `LogonError` from `on_logon` will reject\nthe logon request.\n\n### Stores\n\nThe engines need to store their state. Two stores are currently provided:\na file store (`FileStore`) and sqlite (`SqlStore`).\n\n## Implementation\n\nThe engines are implemented as state machines. This means they can be\ntested without the need for IO.\n",
    "bugtrack_url": null,
    "license": "Apache-2.0",
    "summary": "A pure Python implementation of the FIX protocol",
    "version": "1.0.0a5",
    "split_keywords": [
        "fix",
        "fix-engine"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "65084b7fccb7858e9c287a087b751038dc1d866bf521e2e03eb7c990189735eb",
                "md5": "3b46798e3a8183cfaa60a6b87e6a437f",
                "sha256": "5b5728bafcf9ec92a90ee29a9acd9f6783aa69b20a64a51de2c48b68233918f9"
            },
            "downloads": -1,
            "filename": "jetblack_fixengine-1.0.0a5-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "3b46798e3a8183cfaa60a6b87e6a437f",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8,<4.0",
            "size": 40229,
            "upload_time": "2023-04-06T09:54:58",
            "upload_time_iso_8601": "2023-04-06T09:54:58.337906Z",
            "url": "https://files.pythonhosted.org/packages/65/08/4b7fccb7858e9c287a087b751038dc1d866bf521e2e03eb7c990189735eb/jetblack_fixengine-1.0.0a5-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "06455613673f3851bd74e91dd979ec08c275b86645b1b32e1518ab44ed2a2786",
                "md5": "60cc171a92767e735ec7bdc4c3e29f18",
                "sha256": "1cfcc80be8e9866921f6d8b42f67227afac317eb95148801e91a322db810ba1a"
            },
            "downloads": -1,
            "filename": "jetblack-fixengine-1.0.0a5.tar.gz",
            "has_sig": false,
            "md5_digest": "60cc171a92767e735ec7bdc4c3e29f18",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8,<4.0",
            "size": 29051,
            "upload_time": "2023-04-06T09:54:55",
            "upload_time_iso_8601": "2023-04-06T09:54:55.208593Z",
            "url": "https://files.pythonhosted.org/packages/06/45/5613673f3851bd74e91dd979ec08c275b86645b1b32e1518ab44ed2a2786/jetblack-fixengine-1.0.0a5.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-04-06 09:54:55",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "github_user": "rob-blackbourn",
    "github_project": "jetblack-fixengine",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "jetblack-fixengine"
}
        
Elapsed time: 0.05421s