{"id":13465409,"url":"https://github.com/enzoampil/fastquant","last_synced_at":"2025-05-14T20:09:58.250Z","repository":{"id":38617373,"uuid":"193922326","full_name":"enzoampil/fastquant","owner":"enzoampil","description":"fastquant — Backtest and optimize your ML trading strategies with only 3 lines of code!","archived":false,"fork":false,"pushed_at":"2023-09-15T10:23:58.000Z","size":49663,"stargazers_count":1664,"open_issues_count":82,"forks_count":257,"subscribers_count":49,"default_branch":"master","last_synced_at":"2025-05-05T04:33:07.670Z","etag":null,"topics":["algotrading","backtesting","cryptocurrency","data-science","financial-data-science","machine-learning","quantitative-finance","stocks","trading-strategies"],"latest_commit_sha":null,"homepage":"","language":"Jupyter Notebook","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/enzoampil.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2019-06-26T14:36:43.000Z","updated_at":"2025-05-03T15:58:02.000Z","dependencies_parsed_at":"2023-02-01T05:15:48.162Z","dependency_job_id":"37b17913-ab75-4c60-8fb1-eb68e310d28b","html_url":"https://github.com/enzoampil/fastquant","commit_stats":{"total_commits":838,"total_committers":25,"mean_commits":33.52,"dds":"0.46539379474940334","last_synced_commit":"23af5a44053d7c9ff71e021ced63a5590bdfc121"},"previous_names":["enzoampil/psequant"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enzoampil%2Ffastquant","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enzoampil%2Ffastquant/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enzoampil%2Ffastquant/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enzoampil%2Ffastquant/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/enzoampil","download_url":"https://codeload.github.com/enzoampil/fastquant/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254219374,"owners_count":22034397,"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":["algotrading","backtesting","cryptocurrency","data-science","financial-data-science","machine-learning","quantitative-finance","stocks","trading-strategies"],"created_at":"2024-07-31T15:00:29.136Z","updated_at":"2025-05-14T20:09:58.227Z","avatar_url":"https://github.com/enzoampil.png","language":"Jupyter Notebook","funding_links":[],"categories":["Jupyter Notebook","Backtest + live trading","Python","trading-strategies"],"sub_categories":["General purpose","Trading \u0026 Backtesting"],"readme":"# fastquant :nerd_face:\n[![Build Status](https://travis-ci.com/enzoampil/fastquant.svg?branch=master)](https://travis-ci.com/enzoampil/fastquant)\n[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black)\n[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/enzoampil/fastquant/master/LICENSE)\n[![Downloads](https://pepy.tech/badge/fastquant)](https://pepy.tech/project/fastquant)\n## Bringing backtesting to the mainstream\n\n**fastquant** allows you to easily backtest investment strategies with as few as 3 lines of python code. Its goal is to promote data driven investments by making quantitative analysis in finance accessible to everyone.\n\nTo do this type of analysis without coding, you can also try out [Hawksight](https://hawksight.co/), which was just recently launched! :smile:\n\nIf you want to interact with us directly, you can also reach us on the [Hawksight discord](https://discord.gg/BHMCw2C6VP). Feel free to ask about fastquant in the #feedback-suggestions and #bug-report channels.\n\n\n## Features\n1. Easily access historical stock data\n2. Backtest and optimize trading strategies with only 3 lines of code\n\n\u003csup\u003e`*` - Both Yahoo Finance and Philippine stock data data are accessible straight from fastquant\u003csup\u003e\n\nCheck out our blog posts in the fastquant [website](https://enzoampil.github.io/fastquant-blog/) and this intro [article](https://towardsdatascience.com/backtest-your-trading-strategy-with-only-3-lines-of-python-3859b4a4ab44?source=friends_link\u0026sk=ec647b6bb43fe322013248fd1d473015) on Medium!\n\n## Installation\n\n### Python\n\n```\npip install fastquant\nor\npython -m pip install fastquant\n```\n\n## Get stock data\nAll symbols from [Yahoo Finance](https://finance.yahoo.com/) and Philippine Stock Exchange ([PSE](https://www.pesobility.com/stock)) are accessible via `get_stock_data`.\n\n### Python\n\n```\nfrom fastquant import get_stock_data\ndf = get_stock_data(\"JFC\", \"2018-01-01\", \"2019-01-01\")\nprint(df.head())\n\n#           dt  close\n#   2019-01-01  293.0\n#   2019-01-02  292.0\n#   2019-01-03  309.0\n#   2019-01-06  323.0\n#   2019-01-07  321.0\n```\n\n## Get crypto data\nThe data is pulled from Binance, and all the available tickers are found [here](https://coinmarketcap.com/exchanges/binance/).\n\n### Python\n\n```\nfrom fastquant import get_crypto_data\ncrypto = get_crypto_data(\"BTC/USDT\", \"2018-12-01\", \"2019-12-31\")\ncrypto.head()\n\n#             open    high     low     close    volume\n# dt                                                          \n# 2018-12-01  4041.27  4299.99  3963.01  4190.02  44840.073481\n# 2018-12-02  4190.98  4312.99  4103.04  4161.01  38912.154790\n# 2018-12-03  4160.55  4179.00  3827.00  3884.01  49094.369163\n# 2018-12-04  3884.76  4085.00  3781.00  3951.64  48489.551613\n# 2018-12-05  3950.98  3970.00  3745.00  3769.84  44004.799448\n```\n\n## Backtest trading strategies\n\n### Simple Moving Average Crossover (15 day MA vs 40 day MA)\nDaily Jollibee prices from 2018-01-01 to 2019-01-01\n```\nfrom fastquant import backtest\nbacktest('smac', df, fast_period=15, slow_period=40)\n\n# Starting Portfolio Value: 100000.00\n# Final Portfolio Value: 102272.90\n```\n![](./docs/assets/smac_sample.png)\n\n## Want to do this without coding at all?\n\nIf you want to make this kind of analysis even more simple without having to code at all (or want to avoid the pain of doing all of the setup required), you can signup for free and try out [Hawksight](https://hawksight.co/) - this new no-code tool I’m building to democratize data driven investments.\n\nHoping to make these kinds of powerful analyses accessible to more people!\n\n## Optimize trading strategies with automated grid search\n\nfastquant allows you to automatically measure the performance of your trading strategy on multiple combinations of parameters. All you need to do is to input the values as iterators (like as a `list` or `range`).\n\n### Simple Moving Average Crossover (15 to 30 day MA vs 40 to 55 day MA)\nDaily Jollibee prices from 2018-01-01 to 2019-01-01\n\n```\nfrom fastquant import backtest\nres = backtest(\"smac\", df, fast_period=range(15, 30, 3), slow_period=range(40, 55, 3), verbose=False)\n\n# Optimal parameters: {'init_cash': 100000, 'buy_prop': 1, 'sell_prop': 1, 'execution_type': 'close', 'fast_period': 15, 'slow_period': 40}\n# Optimal metrics: {'rtot': 0.022, 'ravg': 9.25e-05, 'rnorm': 0.024, 'rnorm100': 2.36, 'sharperatio': None, 'pnl': 2272.9, 'final_value': 102272.90}\n\nprint(res[['fast_period', 'slow_period', 'final_value']].head())\n\n#\tfast_period\tslow_period\tfinal_value\n#0\t15\t        40\t        102272.90\n#1\t21\t        40\t         98847.00\n#2\t21\t        52\t         98796.09\n#3\t24\t        46\t         98008.79\n#4\t15\t        46\t         97452.92\n\n```\n\n## Library of trading strategies\n\n| Strategy | Alias | Parameters |\n| --- | --- | --- |\n| Relative Strength Index (RSI) | rsi | `rsi_period`, `rsi_upper`,  `rsi_lower` |\n| Simple moving average crossover (SMAC) | smac | `fast_period`, `slow_period` |\n| Exponential moving average crossover (EMAC) | emac | `fast_period`, `slow_period` |\n| Moving Average Convergence Divergence (MACD) | macd | `fast_perod`, `slow_upper`, `signal_period`, `sma_period`, `dir_period` |\n| Bollinger Bands | bbands | `period`, `devfactor` |\n| Buy and Hold | buynhold | `N/A` |\n| Sentiment Strategy | sentiment | `keyword` , `page_nums`, `senti` |\n| Custom Prediction Strategy | custom | `upper_limit`, `lower_limit`, `custom_column` |\n| Custom Ternary Strategy | ternary | `buy_int`, `sell_int`, `custom_column` |\n\n### Relative Strength Index (RSI) Strategy\n```\nbacktest('rsi', df, rsi_period=14, rsi_upper=70, rsi_lower=30)\n\n# Starting Portfolio Value: 100000.00\n# Final Portfolio Value: 132967.87\n```\n![](./docs/assets/rsi.png)\n\n### Simple moving average crossover (SMAC) Strategy\n```\nbacktest('smac', df, fast_period=10, slow_period=30)\n\n# Starting Portfolio Value: 100000.00\n# Final Portfolio Value: 95902.74\n```\n![](./docs/assets/smac.png)\n\n### Exponential moving average crossover (EMAC) Strategy\n```\nbacktest('emac', df, fast_period=10, slow_period=30)\n\n# Starting Portfolio Value: 100000.00\n# Final Portfolio Value: 90976.00\n```\n![](./docs/assets/emac.png)\n\n### Moving Average Convergence Divergence (MACD) Strategy\n```\nbacktest('macd', df, fast_period=12, slow_period=26, signal_period=9, sma_period=30, dir_period=10)\n\n# Starting Portfolio Value: 100000.00\n# Final Portfolio Value: 96229.58\n```\n![](./docs/assets/macd.png)\n\n### Bollinger Bands Strategy\n```\nbacktest('bbands', df, period=20, devfactor=2.0)\n\n# Starting Portfolio Value: 100000.00\n# Final Portfolio Value: 97060.30\n```\n![](./docs/assets/bbands.png)\n\n### News Sentiment Strategy\nUse Tesla (TSLA) stock from yahoo finance and news articles from [Business Times](https://www.businesstimes.com.sg/)\n```\nfrom fastquant import get_yahoo_data, get_bt_news_sentiment\ndata = get_yahoo_data(\"TSLA\", \"2020-01-01\", \"2020-07-04\")\nsentiments = get_bt_news_sentiment(keyword=\"tesla\", page_nums=3)\nbacktest(\"sentiment\", data, sentiments=sentiments, senti=0.2)\n\n# Starting Portfolio Value: 100000.00\n# Final Portfolio Value: 313198.37\n# Note: Unfortunately, you can't recreate this scenario due to inconsistencies in the dates and sentiments that is scraped by get_bt_news_sentiment. In order to have a quickstart with News Sentiment Strategy you need to make the dates consistent with the sentiments that you are scraping.\n\nfrom fastquant import get_yahoo_data, get_bt_news_sentiment\nfrom datetime import datetime, timedelta\n\n# we get the current date and delta time of 30 days\ncurrent_date = datetime.now().strftime(\"%Y-%m-%d\")\ndelta_date = (datetime.now() - timedelta(30)).strftime(\"%Y-%m-%d\")\ndata = get_yahoo_data(\"TSLA\", delta_date, current_date)\nsentiments = get_bt_news_sentiment(keyword=\"tesla\", page_nums=3)\nbacktest(\"sentiment\", data, sentiments=sentiments, senti=0.2)\n```\n![](./docs/assets/sentiment.png)\n\n### Multi Strategy\n\nMultiple registered strategies can be utilized together in an OR fashion, where buy or sell signals are applied when at least one of the strategies trigger them.\n\n```\ndf = get_stock_data(\"JFC\", \"2018-01-01\", \"2019-01-01\")\n\n# Utilize single set of parameters\nstrats = { \n    \"smac\": {\"fast_period\": 35, \"slow_period\": 50}, \n    \"rsi\": {\"rsi_lower\": 30, \"rsi_upper\": 70} \n} \nres = backtest(\"multi\", df, strats=strats)\nres.shape\n# (1, 16)\n\n\n# Utilize auto grid search\nstrats_opt = { \n    \"smac\": {\"fast_period\": 35, \"slow_period\": [40, 50]}, \n    \"rsi\": {\"rsi_lower\": [15, 30], \"rsi_upper\": 70} \n} \n\nres_opt = backtest(\"multi\", df, strats=strats_opt)\nres_opt.shape\n# (4, 16)\n```\n\n### Custom Strategy for Backtesting Machine Learning \u0026 Statistics Based Predictions\n\nThis powerful strategy allows you to backtest your own trading strategies using any type of model w/ as few as 3 lines of code after the forecast!\n\nPredictions based on any model can be used as a custom indicator to be backtested using fastquant. You just need to add a `custom` column in the input dataframe, and set values for `upper_limit` and `lower_limit`.\n\nThe strategy is structured similar to `RSIStrategy` where you can set an `upper_limit`, above which the asset is sold (considered \"overbought\"), and a `lower_limit`, below which the asset is bought (considered \"underbought). `upper_limit` is set to 95 by default, while `lower_limit` is set to 5 by default.\n\nIn the example below, we show how to use the custom strategy to backtest a custom indicator based on out-of-sample time series forecasts. The forecasts were generated using Facebook's [Prophet](https://github.com/facebook/prophet) package on Bitcoin prices.\n\n```\nfrom fastquant import get_crypto_data, backtest\nfrom fbprophet import Prophet\nimport pandas as pd\nfrom matplotlib import pyplot as plt\n\n# Pull crypto data\ndf = get_crypto_data(\"BTC/USDT\", \"2019-01-01\", \"2020-05-31\")\n\n# Fit model on closing prices\nts = df.reset_index()[[\"dt\", \"close\"]]\nts.columns = ['ds', 'y']\nm = Prophet(daily_seasonality=True, yearly_seasonality=True).fit(ts)\nforecast = m.make_future_dataframe(periods=0, freq='D')\n\n# Predict and plot\npred = m.predict(forecast)\nfig1 = m.plot(pred)\nplt.title('BTC/USDT: Forecasted Daily Closing Price', fontsize=25)\n```\n\n![](./docs/assets/bitcoin_forecasts.png)\n\n```\n# Convert predictions to expected 1 day returns\nexpected_1day_return = pred.set_index(\"ds\").yhat.pct_change().shift(-1).multiply(100)\n\n# Backtest the predictions, given that we buy bitcoin when the predicted next day return is \u003e +1.5%, and sell when it's \u003c -1.5%.\ndf[\"custom\"] = expected_1day_return.multiply(-1)\nbacktest(\"custom\", df.dropna(),upper_limit=1.5, lower_limit=-1.5)\n```\n\n![](./docs/assets/bitcoin_prophet_backtest.png)\n\nSee more examples [here](https://nbviewer.jupyter.org/github/enzoampil/fastquant/tree/master/examples/).\n\n## fastquant API\nView full list of fastquan API [here](API.md)\n\n## Be part of the growing fastquant community\n\nWant to discuss more about fastquant with other users, and our team of developers?\n\nYou can reach us on the [Hawksight discord](https://discord.gg/BHMCw2C6VP). Feel free to ask about fastquant in the #feedback-suggestions and #bug-report channels.\n\n## Run fastquant in a Docker Container\n\n```\n# Build the image\ndocker build -t myimage .\n\n# Run the container\ndocker run -t -d -p 5000:5000 myimage\n\n# Get the container id\ndocker ps\n\n# SSH into the fastquant container\ndocker exec -it \u003cCONTAINER_ID\u003e /bin/bash\n\n# Run python and use fastquant\npython\n\n\u003e\u003e\u003e from fastquant import get_stock_data\n\u003e\u003e\u003e df = get_stock_data(\"TSLA\", \"2019-01-01\", \"2020-01-01\")\n\u003e\u003e\u003e df.head()\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fenzoampil%2Ffastquant","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fenzoampil%2Ffastquant","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fenzoampil%2Ffastquant/lists"}