{"id":13740128,"url":"https://github.com/ranaroussi/qtpylib","last_synced_at":"2026-01-14T07:50:07.966Z","repository":{"id":39032846,"uuid":"66001846","full_name":"ranaroussi/qtpylib","owner":"ranaroussi","description":"QTPyLib, Pythonic Algorithmic Trading ","archived":true,"fork":false,"pushed_at":"2021-09-22T05:54:46.000Z","size":39236,"stargazers_count":2249,"open_issues_count":68,"forks_count":524,"subscribers_count":139,"default_branch":"main","last_synced_at":"2025-12-27T00:08:23.525Z","etag":null,"topics":["algo-trading","algorithmic-trading","algotrading","backtester","interactive-brokers","interactivebrokers","quantitative-finance"],"latest_commit_sha":null,"homepage":"http://qtpylib.io","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/ranaroussi.png","metadata":{"files":{"readme":"README.rst","changelog":"CHANGELOG.rst","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"github":null,"patreon":"ranaroussi","open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2016-08-18T14:01:39.000Z","updated_at":"2025-12-26T20:08:54.000Z","dependencies_parsed_at":"2022-07-13T15:29:41.928Z","dependency_job_id":null,"html_url":"https://github.com/ranaroussi/qtpylib","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/ranaroussi/qtpylib","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ranaroussi%2Fqtpylib","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ranaroussi%2Fqtpylib/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ranaroussi%2Fqtpylib/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ranaroussi%2Fqtpylib/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ranaroussi","download_url":"https://codeload.github.com/ranaroussi/qtpylib/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ranaroussi%2Fqtpylib/sbom","scorecard":{"id":761118,"data":{"date":"2025-08-11","repo":{"name":"github.com/ranaroussi/qtpylib","commit":"2c1af0eef85fb3205d8fcefc41a421b074b371de"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.1,"checks":[{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Maintained","score":0,"reason":"project is archived","details":["Warn: Repository is archived."],"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":3,"reason":"Found 7/23 approved changesets -- score normalized to 3","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE.txt:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE.txt:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 14 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"15 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: PYSEC-2018-66 / GHSA-562c-5r94-xh97","Warn: Project is vulnerable to: PYSEC-2019-179 / GHSA-5wv5-4vpf-pj6m","Warn: Project is vulnerable to: PYSEC-2023-62 / GHSA-m2qf-hxjv-5gpq","Warn: Project is vulnerable to: PYSEC-2021-856 / GHSA-5545-2q6w-2gh6","Warn: Project is vulnerable to: GHSA-6p56-wp2h-9hxr","Warn: Project is vulnerable to: PYSEC-2019-108 / GHSA-9fq2-x9r6-wfmf","Warn: Project is vulnerable to: PYSEC-2021-857 / GHSA-f7c7-j99h-c22f","Warn: Project is vulnerable to: GHSA-fpfv-jqm9-f5jm","Warn: Project is vulnerable to: PYSEC-2017-1 / GHSA-frgw-fgh6-9g52","Warn: Project is vulnerable to: PYSEC-2020-73","Warn: Project is vulnerable to: GHSA-v9hf-5j83-6xpp","Warn: Project is vulnerable to: GHSA-9hjg-9r4m-mvj7","Warn: Project is vulnerable to: GHSA-9wx4-h78v-vm56","Warn: Project is vulnerable to: PYSEC-2023-74 / GHSA-j8r2-6x86-q33q","Warn: Project is vulnerable to: PYSEC-2018-28 / GHSA-x84v-xcm2-53pg"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-22T23:32:10.315Z","repository_id":39032846,"created_at":"2025-08-22T23:32:10.316Z","updated_at":"2025-08-22T23:32:10.316Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28413508,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T05:26:33.345Z","status":"ssl_error","status_checked_at":"2026-01-14T05:21:57.251Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["algo-trading","algorithmic-trading","algotrading","backtester","interactive-brokers","interactivebrokers","quantitative-finance"],"created_at":"2024-08-03T04:00:43.051Z","updated_at":"2026-01-14T07:50:07.931Z","avatar_url":"https://github.com/ranaroussi.png","language":"Python","funding_links":["https://patreon.com/ranaroussi"],"categories":["Python","Curated List"],"sub_categories":["Trading \u0026 Backtesting","交易与回测","Trading Frameworks (support backtesting and live trading)"],"readme":"QTPyLib, Pythonic Algorithmic Trading\n=====================================\n\n.. image:: https://img.shields.io/badge/python-3.4+-blue.svg?style=flat\n    :target: https://pypi.python.org/pypi/qtpylib\n    :alt: Python version\n\n.. image:: https://img.shields.io/pypi/v/qtpylib.svg?maxAge=60\n    :target: https://pypi.python.org/pypi/qtpylib\n    :alt: PyPi version\n\n.. image:: https://img.shields.io/pypi/status/qtpylib.svg?maxAge=60\n    :target: https://pypi.python.org/pypi/qtpylib\n    :alt: PyPi status\n\n.. image:: https://img.shields.io/travis/ranaroussi/qtpylib/main.svg?maxAge=1\n    :target: https://travis-ci.org/ranaroussi/qtpylib\n    :alt: Travis-CI build status\n\n.. image:: https://img.shields.io/badge/docs-latest-brightgreen.svg?style=flat\n    :target: http://qtpylib.io/docs/latest/?badge=latest\n    :alt: Documentation Status\n\n.. image:: https://img.shields.io/badge/Chat-Discord-%237289d6.svg?style=flat\u0026logo=discord\u0026maxAge=60\n    :target: https://discord.gg/7wEzsuV\n    :alt: Chat on Discord\n\n.. image:: https://img.shields.io/github/stars/ranaroussi/qtpylib.svg?style=social\u0026label=Star\u0026maxAge=60\n    :target: https://github.com/ranaroussi/qtpylib\n    :alt: Star this repo\n\n.. image:: https://img.shields.io/twitter/follow/aroussi.svg?style=social\u0026label=Follow\u0026maxAge=60\n    :target: https://twitter.com/aroussi\n    :alt: Follow me on twitter\n\n\\\n\nQTPyLib (**Q**\\ uantitative **T**\\ rading **Py**\\ thon **Lib**\\ rary)\nis a simple, **event-driven algorithmic trading library** written in Python,\nthat supports backtesting, as well as paper and live trading via\n`Interactive Brokers \u003chttps://www.interactivebrokers.com\u003e`_.\n\nI developed QTPyLib because I wanted for a simple,\nyet powerful, trading library that will let me focus on the\ntrading logic itself and ignore everything else.\n\n`Full Documentation » \u003chttp://www.qtpylib.io/\u003e`_\n\n`Changelog » \u003c./CHANGELOG.rst\u003e`_\n\n-----\n\n**Read about the future of QTPyLib here:**\nhttps://aroussi.com/post/the-future-of-qtpylib\n\n-----\n\nFeatures\n========\n\n- A continuously-running Blotter that lets you capture market data even when your algos aren't running.\n- Tick, Bar and Trade data is stored in MySQL for later analysis and backtesting.\n- Using pub/sub architecture using `ØMQ \u003chttp://zeromq.org\u003e`_ (ZeroMQ) for communicating between the Algo and the Blotter allows for a single Blotter/multiple Algos running on the same machine.\n- **Support for Order Book, Quote, Time, Tick or Volume based strategy resolutions**.\n- Includes many common indicators that you can seamlessly use in your algorithm.\n- **Market data events use asynchronous, non-blocking architecture**.\n- Have orders delivered to your mobile via SMS (requires a `Nexmo \u003chttps://www.nexmo.com/\u003e`_ or `Twilio \u003chttps://www.twilio.com/\u003e`_ account).\n- Full integration with `TA-Lib \u003chttp://ta-lib.org\u003e`_ via dedicated module (`see documentation \u003chttp://qtpylib.io/docs/latest/indicators.html#ta-lib-integration\u003e`_).\n- Ability to import any Python library (such as `scikit-learn \u003chttp://scikit-learn.org\u003e`_ or `TensorFlow \u003chttps://www.tensorflow.org\u003e`_) to use them in your algorithms.\n\n-----\n\nQuickstart\n==========\n\nThere are 5 main components to QTPyLib:\n\n1. ``Blotter`` - handles market data retrieval and processing.\n2. ``Broker`` - sends and process orders/positions (abstracted layer).\n3. ``Algo`` - (sub-class of ``Broker``) communicates with the ``Blotter`` to pass market data to your strategies, and process/positions orders via ``Broker``.\n4. ``Reports`` - provides real-time monitoring of trades and open positions via Web App, as well as a simple REST API for trades, open positions, and market data.\n5. Lastly, **Your Strategies**, which are sub-classes of ``Algo``, handle the trading logic/rules. This is where you'll write most of your code.\n\n\n1. Get Market Data\n------------------\n\nTo get started, you need to first create a Blotter script:\n\n.. code:: python\n\n    # blotter.py\n    from qtpylib.blotter import Blotter\n\n    class MainBlotter(Blotter):\n        pass # we just need the name\n\n    if __name__ == \"__main__\":\n        blotter = MainBlotter()\n        blotter.run()\n\nThen, with IB TWS/GW running, run the Blotter from the command line:\n\n.. code:: bash\n\n    $ python blotter.py\n\nIf your strategy needs order book / market depth data, add the ``--orderbook`` flag to the command:\n\n.. code:: bash\n\n    $ python blotter.py --orderbook\n\n\n2. Write your Algorithm\n-----------------------\n\nWhile the Blotter running in the background, write and execute your algorithm:\n\n.. code:: python\n\n    # strategy.py\n    from qtpylib.algo import Algo\n\n    class CrossOver(Algo):\n\n        def on_start(self):\n            pass\n\n        def on_fill(self, instrument, order):\n            pass\n\n        def on_quote(self, instrument):\n            pass\n\n        def on_orderbook(self, instrument):\n            pass\n\n        def on_tick(self, instrument):\n            pass\n\n        def on_bar(self, instrument):\n            # get instrument history\n            bars = instrument.get_bars(window=100)\n\n            # or get all instruments history\n            # bars = self.bars[-20:]\n\n            # skip first 20 days to get full windows\n            if len(bars) \u003c 20:\n                return\n\n            # compute averages using internal rolling_mean\n            bars['short_ma'] = bars['close'].rolling(window=10).mean()\n            bars['long_ma']  = bars['close'].rolling(window=20).mean()\n\n            # get current position data\n            positions = instrument.get_positions()\n\n            # trading logic - entry signal\n            if bars['short_ma'].crossed_above(bars['long_ma'])[-1]:\n                if not instrument.pending_orders and positions[\"position\"] == 0:\n\n                    # buy one contract\n                    instrument.buy(1)\n\n                    # record values for later analysis\n                    self.record(ma_cross=1)\n\n            # trading logic - exit signal\n            elif bars['short_ma'].crossed_below(bars['long_ma'])[-1]:\n                if positions[\"position\"] != 0:\n\n                    # exit / flatten position\n                    instrument.exit()\n\n                    # record values for later analysis\n                    self.record(ma_cross=-1)\n\n\n    if __name__ == \"__main__\":\n        strategy = CrossOver(\n            instruments = [ (\"ES\", \"FUT\", \"GLOBEX\", \"USD\", 201609, 0.0, \"\") ], # ib tuples\n            resolution  = \"1T\", # Pandas resolution (use \"K\" for tick bars)\n            tick_window = 20, # no. of ticks to keep\n            bar_window  = 5, # no. of bars to keep\n            preload     = \"1D\", # preload 1 day history when starting\n            timezone    = \"US/Central\" # convert all ticks/bars to this timezone\n        )\n        strategy.run()\n\n\nTo run your algo in a **live** enviroment, from the command line, type:\n\n.. code:: bash\n\n    $ python strategy.py --logpath ~/qtpy/\n\n\nThe resulting trades be saved in ``~/qtpy/STRATEGY_YYYYMMDD.csv`` for later analysis.\n\n\n3. Viewing Live Trades\n----------------------\n\nWhile the Blotter running in the background, write the dashboard:\n\n.. code:: python\n\n    # dashboard.py\n    from qtpylib.reports import Reports\n\n    class Dashboard(Reports):\n        pass # we just need the name\n\n    if __name__ == \"__main__\":\n        dashboard = Dashboard(port = 5000)\n        dashboard.run()\n\n\nTo run your dashboard, run it from the command line:\n\n.. code:: bash\n\n    $ python dashboard.py\n\n    \u003e\u003e\u003e Dashboard password is: a0f36d95a9\n    \u003e\u003e\u003e Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)\n\nNow, point your browser to http://localhost:5000 and use the password generated to access your dashboard.\n\n-----\n\n\n.. note::\n\n    You can find other examples in the ``qtpylib/examples directory``.\n    Please refer to the `Full Documentation \u003chttp://www.qtpylib.io/\u003e`_ to learn\n    how to enable SMS notifications, use the bundled Indicators, and more.\n\n\n\nInstallation\n============\n\nInstall using ``pip``:\n\n.. code:: bash\n\n    $ pip install qtpylib --upgrade --no-cache-dir\n\n\nRequirements\n------------\n\n* `Python \u003chttps://www.python.org\u003e`_ \u003e=3.4\n* `Pandas \u003chttps://github.com/pydata/pandas\u003e`_ (tested to work with \u003e=0.18.1)\n* `Numpy \u003chttps://github.com/numpy/numpy\u003e`_ (tested to work with \u003e=1.11.1)\n* `PyZMQ \u003chttps://github.com/zeromq/pyzmq\u003e`_ (tested to work with \u003e=15.2.1)\n* `PyMySQL \u003chttps://github.com/PyMySQL/PyMySQL\u003e`_ (tested to work with \u003e=0.7.6)\n* `pytz \u003chttp://pytz.sourceforge.net\u003e`_ (tested to work with \u003e=2016.6.1)\n* `dateutil \u003chttps://pypi.python.org/pypi/python-dateutil\u003e`_ (tested to work with \u003e=2.5.1)\n* `Nexmo-Python \u003chttps://github.com/Nexmo/nexmo-python\u003e`_ for SMS support (tested to work with \u003e=1.2.0)\n* `Twilio-Python \u003chttps://github.com/twilio/twilio-python\u003e`_ for SMS support (tested to work with \u003e=5.4.0)\n* `Flask \u003chttp://flask.pocoo.org\u003e`_ for the Dashboard (tested to work with \u003e=0.11)\n* `Requests \u003chttps://github.com/kennethreitz/requests\u003e`_ (tested to work with \u003e=2.10.0)\n* `IbPy2 \u003chttps://github.com/blampe/IbPy\u003e`_ (tested to work with \u003e=0.8.0)\n* `ezIBpy \u003chttps://github.com/ranaroussi/ezibpy\u003e`_ (IbPy wrapper, tested to work with \u003e=1.12.66)\n* Latest Interactive Brokers’ `TWS \u003chttps://www.interactivebrokers.com/en/index.php?f=15875\u003e`_ or `IB Gateway \u003chttps://www.interactivebrokers.com/en/index.php?f=16457\u003e`_ installed and running on the machine\n* `MySQL Server \u003chttps://www.mysql.com/\u003e`_ installed and running with a database for QTPyLib\n\n-----\n\nLegal Stuff\n===========\n\nQTPyLib is licensed under the **Apache License, Version 2.0**. A copy of which is included in LICENSE.txt.\n\nQTPyLib is not a product of Interactive Brokers, nor is it affiliated with Interactive Brokers.\n\n\n\nP.S.\n----\n\nI'm very interested in your experience with QTPyLib. Please drop me a note with any feedback you have.\n\n**Ran**\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Franaroussi%2Fqtpylib","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Franaroussi%2Fqtpylib","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Franaroussi%2Fqtpylib/lists"}