Empyrial is a Python-based open-source quantitative investment library dedicated to financial institutions and retail investors

Overview

By Investors, For Investors.











Open In Colab


Want to read this in Chinese? Click here

Empyrial is a Python-based open-source quantitative investment library dedicated to financial institutions and retail investors, officially released in March 2021. Already used by thousands of people working in the finance industry, Empyrial aims to become an all-in-one platform for portfolio management, analysis, and optimization.

Empyrial empowers portfolio management by bringing the best of performance and risk analysis in an easy-to-understand, flexible and powerful framework.

With Empyrial, you can easily analyze security or a portfolio in order to get the best insights from it.



Installation

You can install Empyrial using pip:

pip install empyrial

For a better experience, we advise you to use Empyrial on a notebook (e.g., Jupyter, Google Colab)

Note: macOS users will need to install Xcode Command Line Tools.

Note: Windows users will need to install C++. (download, install instructions)

Features

Feature 📰 Status
Engine (backtesting + performance analysis) Released on May 30, 2021
Optimizer Released on Jun 7, 2021
Rebalancing Released on Jun 27, 2021
Risk manager Released on Jul 5, 2021
Sandbox Released on Jul 17, 2021

Documentation

Full documentation (website)

Full documentation (PDF)

Usage

Empyrial Engine

from empyrial import empyrial, Engine

portfolio = Engine(
    start_date = "2018-06-09", 
    portfolio = ["BABA", "PDD", "KO", "AMD","^IXIC"], 
    weights = [0.2, 0.2, 0.2, 0.2, 0.2],  # equal weighting is set by default
    benchmark = ["SPY"]  # SPY is set by default
)

empyrial(portfolio)

Calendar Rebalancing

A portfolio can be rebalanced for either a specific time period or for specific dates using the rebalance option.

Rebalance for Time Period

Time periods available for rebalancing are 2y, 1y, 6mo, quarterly, monthly

from empyrial import empyrial, Engine

portfolio = Engine(
    start_date = "2018-06-09", 
    portfolio = ["BABA", "PDD", "KO", "AMD","^IXIC"], 
    weights = [0.2, 0.2, 0.2, 0.2, 0.2],  # equal weighting is set by default
    benchmark = ["SPY"],  # SPY is set by default
    rebalance = "1y"
)

empyrial(portfolio)

Rebalance for Custom Dates

You can rebalance a portfolio by specifying a list of custom dates.
⚠️ When using custom dates, the first date of the list must correspond with the start_date and the last element should correspond to the end_date which is today's date by default.

from empyrial import empyrial, Engine

portfolio = Engine(
    start_date = "2018-06-09", 
    portfolio = ["BABA", "PDD", "KO", "AMD","^IXIC"], 
    weights = [0.2, 0.2, 0.2, 0.2, 0.2],  # equal weighting is set by default
    benchmark = ["SPY"],  # SPY is set by default
    rebalance = ["2018-06-09", "2019-01-01", "2020-01-01", "2021-01-01"]
)

empyrial(portfolio)

Optimizer

The default optimizer is equal weighting. You can specify custom weights, if desired.

from empyrial import empyrial, Engine

portfolio = Engine(
    start_date = "2018-01-01",
    portfolio = ["BABA", "PDD", "KO", "AMD","^IXIC"], 
    weights = [0.1, 0.3, 0.15, 0.25, 0.2],   # custom weights
    rebalance = "1y"  # rebalance every year
)

empyrial(portfolio)

You can also use the built-in optimizers. There are 4 optimizers available:

  • "EF": Global Efficient Frontier Example
  • "MEANVAR": Mean-Variance Example
  • "HRP": Hierarchical Risk Parity Example
  • "MINVAR": Minimum-Variance Example
from empyrial import empyrial, Engine

portfolio = Engine(
    start_date = "2018-01-01",
    portfolio = ["BABA", "PDD", "KO", "AMD","^IXIC"],
    optimizer = "EF",
    rebalance = "1y"  # rebalance every year
)

portfolio.weights

Output:

[0.0, 0.0, 0.0348, 0.9652, 0.0]

We can see that the allocation has been optimized.

Risk Manager

3 Risk Managers are available:

  • Max Drawdown: {"Max Drawdown" : -0.3} Example
  • Take Profit: {"Take Profit" : 0.4} Example
  • Stop Loss: {"Stop Loss" : -0.2} Example
from empyrial import empyrial, Engine

portfolio = Engine(
    start_date = "2018-01-01",
    portfolio= ["BABA", "PDD", "KO", "AMD","^IXIC"], 
    optimizer = "EF",
    rebalance = "1y",  # rebalance every year
    risk_manager = {"Max Drawdown" : -0.2}  # Stop the investment when the drawdown becomes superior to -20%
)

empyrial(portfolio)

Empyrial Outputs

image image image image image image image image image image image

Download the Tearsheet

You can use the get_report() function of Empyrial to generate a tearsheet, and then download this as a PDF document.

from empyrial import get_report, Engine

portfolio = Engine(
      start_date = "2018-01-01",
      portfolio = ["BABA", "PDD", "KO", "AMD","^IXIC"],
      optimizer = "EF",
      rebalance = "1y", #rebalance every year
      risk_manager = {"Stop Loss" : -0.2}
)

get_report(portfolio)

Output:

image

Stargazers over time

追星族的时间

Contribution and Issues

Empyrial uses GitHub to host its source code. Learn more about the Github flow.

For larger changes (e.g., new feature request, large refactoring), please open an issue to discuss first.

Smaller improvements (e.g., document improvements, bugfixes) can be handled by the Pull Request process of GitHub: pull requests.

  • To contribute to the code, you will need to do the following:

  • Fork Empyrial - Click the Fork button at the upper right corner of this page.

  • Clone your own fork. E.g., git clone https://github.com/ssantoshp/Empyrial.git
    If your fork is out of date, then will you need to manually sync your fork: Synchronization method

  • Create a Pull Request using your fork as the compare head repository.

You contributions will be reviewed, potentially modified, and hopefully merged into Empyrial.

Contributors

Thanks goes to these wonderful people (emoji key):

All Contributors


Brendan Glancy

💻 🐛

Renan Lopes

💻 🐛

Mark Thebault

💻

Diego Alvarez

💻 🐛

Rakesh Bhat

💻

Anh Le

🐛

Tony Zhang

💻

Ikko Ashimine

✒️

QuantNomad

📹

Buckley

✒️ 💻

Adam Nelsson

📓

This project follows the all-contributors specification. Contributions of any kind are welcome!

Contact

You are welcome to contact us by email at [email protected] or in Empyrial's discussion space

License

MIT

Comments
  • Issue with Pandas datareader

    Issue with Pandas datareader

    Describe the bug This seems to effect all your branches

    RemoteDataError Traceback (most recent call last) in ----> 1 oracle(portfolio)

    ~/anaconda3/envs/empyr/lib/python3.8/site-packages/empyrial.py in oracle(my_portfolio, prediction_days, based_on) 334 335 --> 336 df = web.DataReader(asset, data_source='yahoo', start = my_portfolio.start_date, end= my_portfolio.end_date) 337 df = pd.DataFrame(df) 338 df.reset_index(level=0, inplace=True)

    ~/anaconda3/envs/empyr/lib/python3.8/site-packages/pandas/util/_decorators.py in wrapper(*args, **kwargs) 197 else: 198 kwargs[new_arg_name] = new_arg_value --> 199 return func(*args, **kwargs) 200 201 return cast(F, wrapper)

    ~/anaconda3/envs/empyr/lib/python3.8/site-packages/pandas_datareader/data.py in DataReader(name, data_source, start, end, retry_count, pause, session, api_key) 374 375 if data_source == "yahoo": --> 376 return YahooDailyReader( 377 symbols=name, 378 start=start,

    ~/anaconda3/envs/empyr/lib/python3.8/site-packages/pandas_datareader/base.py in read(self) 251 # If a single symbol, (e.g., 'GOOG') 252 if isinstance(self.symbols, (string_types, int)): --> 253 df = self._read_one_data(self.url, params=self._get_params(self.symbols)) 254 # Or multiple symbols, (e.g., ['GOOG', 'AAPL', 'MSFT']) 255 elif isinstance(self.symbols, DataFrame):

    ~/anaconda3/envs/empyr/lib/python3.8/site-packages/pandas_datareader/yahoo/daily.py in _read_one_data(self, url, params) 151 url = url.format(symbol) 152 --> 153 resp = self._get_response(url, params=params) 154 ptrn = r"root.App.main = (.*?);\n}(this));" 155 try:

    ~/anaconda3/envs/empyr/lib/python3.8/site-packages/pandas_datareader/base.py in _get_response(self, url, params, headers) 179 msg += "\nResponse Text:\n{0}".format(last_response_text) 180 --> 181 raise RemoteDataError(msg) 182 183 def _get_crumb(self, *args):

    RemoteDataError: Unable to read URL: https://finance.yahoo.com/quote/BABA/history?period1=1591671600&period2=1625972399&interval=1d&frequency=1d&filter=history Response Text: b'\n \n \n \n Yahoo\n \n \n \n \n \n \n \n \n

    \n \n \n \n
    \n Yahoo Logo\n

    Will be right back...

    \n

    Thank you for your patience.

    \n

    Our engineers are working quickly to resolve the issue.

    \n
    \n '

    1

    opened by geofffoster 8
  • Failed to build scs ERROR: Could not build wheels for scs which use PEP 517 and cannot be installed directly

    Failed to build scs ERROR: Could not build wheels for scs which use PEP 517 and cannot be installed directly

    I am using Python 3.8.10. I had a separate environment and I got the following error when pip installing empyrial Failed to build scs ERROR: Could not build wheels for scs which use PEP 517 and cannot be installed directly

    From this link https://github.com/pydata/bottleneck/issues/281 I tried pip install --upgrade pip setuptools wheel but I am still getting the same bug when installing empyrial.

    • OS: Ubuntu 20.04
    • mini conda version and a separate environment for trading
    • Python 3.8.10
    • Let me know if there is any way around this bug. Thanks
    opened by gurusura 8
  • RemoteDataError: No data fetched using 'YahooDailyReader'

    RemoteDataError: No data fetched using 'YahooDailyReader'

    Discussed in https://github.com/ssantoshp/Empyrial/discussions/27

    Originally posted by karim1104 July 3, 2021 Starting July 1, I'm getting the error "RemoteDataError: No data fetched using 'YahooDailyReader'". I've tried it in different Python environments (3.6, 3.8, 3.9). It seems like a Pandas DataReader issue (https://github.com/pydata/pandas-datareader/issues/868) How can we resolve this? I have a subscription to FMP, is there a way I use instead of Yahoo Finance?

    opened by ssantoshp 6
  • Error when rebalancing with only one stock

    Error when rebalancing with only one stock

    Hi, I have tried to reproduce test results and simulated one single stock over time by forcing the weight distribution as shown below: tickers = ["stock1", "stock2"] weights_new_ = [1.0, 0.0] no optimizer is used, so just using the quantstats calculations of ratios and returns. In the next example, we do the same but with a yearly rebalancer. The thing here is that the results should be exactly the same. There seems to be a slight error in the returns calculations over time, which turns out to be bigger with more rebalancing.

    I will have some more look at it, and update if I find the bug. Btw great work!

    opened by atobiese 5
  • Unlisted Stock Symbol Counted in Pie Chart

    Unlisted Stock Symbol Counted in Pie Chart

    Hi , awesome tool santosh bhai. If a ticker symbol data is not listed at the time of the start date , it stills counts the ticker in the pie chart portfolio. Ideally it should not .. or am i getting this wrong. very new guy. regards ,

    opened by lawzeus 5
  • get_report error

    get_report error

    Describe the bug the sample code (as per --> https://empyrial.gitbook.io/empyrial/save-the-tearsheet/get-a-report) is throwing an error

    To Reproduce Steps to reproduce the behavior:

    1. Go to 'https://empyrial.gitbook.io/empyrial/save-the-tearsheet/get-a-report...'
    2. Run the sample code
    3. Scroll down to '....'
    4. See error

    NameError Traceback (most recent call last) /var/folders/41/q1hx0rjd5xzck1vl121t6b2m0000gn/T/ipykernel_11664/2518190224.py in 10 empyrial(portfolio) 11 ---> 12 get_report(portfolio)

    NameError: name 'get_report' is not defined

    Expected behavior A clear and concise description of what you expected to happen.

    Screenshots If applicable, add screenshots to help explain your problem.

    Desktop (please complete the following information):

    • OS: [e.g. iOS]
    • Browser [e.g. chrome, safari]
    • Version [e.g. 22]

    Additional context using jypiterlab notebook

    opened by lawzeus 5
  • Support for custom data, or data from other exchanges

    Support for custom data, or data from other exchanges

    Is your feature request related to a problem? Please describe. I want to analyze portfolio in other exchanges.

    Describe the solution you'd like Ability to provide other exchange data.

    opened by suvojit-0x55aa 4
  • Error when running fundlens

    Error when running fundlens

    Anaconda3\lib\site-packages\empyrial.py", line 610, in fundlens ['Dividend yield', yahoo_financials.get_dividend_yield()], ['Payout ratio', yahoo_financials.get_payout_ratio()], ['Controversy', controversy], ['Social score', social_score],

    UnboundLocalError: local variable 'controversy' referenced before assignment

    opened by jaredre 4
  • rebalance has a bug

    rebalance has a bug

    When you set up quarterly rebalance with only one ticker, the strategy and benchmark show different values. This is a bug. They should be completely equal.

    The codebase below reproduces the issue. The EOY returns and the timeseries plot of Cumulative returns vs benchmark show that the strategy and benchmark are divergent.

    from empyrial import empyrial, Engine portfolio = Engine(
    start_date= "2021-01-01", portfolio= ["BTC-USD", "GOOG"], weights = [1, 0.], #equal weighting is set by default benchmark = ["BTC-USD"], #SPY is set by default rebalance = 'quarterly' ) empyrial(portfolio)

    opened by rgleavenworth 3
  • Graph styling

    Graph styling

    Is there a way to override the default styling parameters used in your tearsheet? I understand that most of the styling is inherited from quantstats. Anyway you can suggest how to change things like facecolor, linewidth, etc?

    opened by rgleavenworth 3
  • EM Optimizer fails if benchmark changed to Nifty50  (yahoo ticker used

    EM Optimizer fails if benchmark changed to Nifty50 (yahoo ticker used "^NSEI")

    Describe the bug The EM optimiser fails when the default benchmark is altered to Nifty .

    However if the default is restored it works .

    To Reproduce Steps to reproduce the behavior : use this code "from empyrial import empyrial, Engine

    portfolio = Engine(
    start_date= "2015-01-01", #start date for the backtesting portfolio= ["TCS.NS", "INFY.NS", "HDFC.NS", "KOTAKBANK.NS","TITAN.NS","NESTLEIND.NS"], #assets in your portfolio benchmark = ["NSEI"] optimizer = "EF" ) empyrial(portfolio)"

    Expected behavior error message " File "/var/folders/41/q1hx0rjd5xzck1vl121t6b2m0000gn/T/ipykernel_2924/1251204071.py", line 7 optimizer = "EF" ^ SyntaxError: invalid syntax

    Screenshots If applicable, add screenshots to help explain your problem.

    Desktop (please complete the following information):

    • OS: MacOsx
    • Browser Chrome
    • jupyter

    Additional context Add any other context about the problem here.

    opened by lawzeus 3
  • assets value / non-stock based portfolio?

    assets value / non-stock based portfolio?

    Wondering if Empyrial can be used with a non-stock based portfolio. The example in the docs is like this:

    from empyrial import empyrial, Engine portfolio = Engine(
    start_date= "2018-06-09", portfolio= ["BABA", "PDD", "KO", "AMD","^IXIC"], weights = [0.2, 0.2, 0.2, 0.2, 0.2], #equal weighting is set by default benchmark = ["SPY"] #SPY is set by default ) empyrial(portfolio)

    Is there any alternate way to define a portfolio, not as a list of stocks / weights but based on the value of the assets in the account?

    opened by andrew521 2
  • str and Timestamp error

    str and Timestamp error

    The code:

    from empyrial import empyrial, Engine
    portfolio = Engine(
                      start_date= "2021-01-01", #start date for the backtesting
                      end_date= "2022-05-01",
                      portfolio= tickers[:], #assets in your portfolio
                      weights = w2[:],
                      benchmark=["XU100.IS"]
    )
    print(empyrial(portfolio))
    print(portfolio)
    

    It gives an error like below.

    TypeError Traceback (most recent call last) ~\AppData\Local\Temp/ipykernel_10148/966461475.py in 11 ) 12 ---> 13 print(empyrial(portfolio)) 14 print(portfolio)

    ~\AppData\Roaming\Python\Python39\site-packages\empyrial.py in empyrial(my_portfolio, rf, sigma_value, confidence_value) 304 empyrial.SR = SR 305 --> 306 CR = qs.stats.calmar(returns) 307 CR = CR.tolist() 308 CR = str(round(CR, 2))

    ~\AppData\Roaming\Python\Python39\site-packages\quantstats\stats.py in calmar(returns, prepare_returns) 547 if prepare_returns: 548 returns = _utils._prepare_returns(returns) --> 549 cagr_ratio = cagr(returns) 550 max_dd = max_drawdown(returns) 551 return cagr_ratio / abs(max_dd)

    ~\AppData\Roaming\Python\Python39\site-packages\quantstats\stats.py in cagr(returns, rf, compounded) 500 total = _np.sum(total) 501 --> 502 years = (returns.index[-1] - returns.index[0]).days / 365. 503 504 res = abs(total + 1.0) ** (1.0 / years) - 1

    TypeError: unsupported operand type(s) for -: 'str' and 'Timestamp'

    opened by burakgulmez 1
Releases(v1.9.8)
Owner
Santosh
The 17-year-old not so part-time coder
Santosh
Houseprices - Predict sales prices and practice feature engineering, RFs, and gradient boosting

House Prices - Advanced Regression Techniques Predicting House Prices with Machine Learning This project is build to enhance my knowledge about machin

1 Jan 01, 2022
Bayesian Modeling and Computation in Python

Bayesian Modeling and Computation in Python Open access and Code This repository contains the open access version of the text and the code examples in

Bayesian Modeling and Computation in Python 339 Jan 02, 2023
A pure-python implementation of the UpSet suite of visualisation methods by Lex, Gehlenborg et al.

pyUpSet A pure-python implementation of the UpSet suite of visualisation methods by Lex, Gehlenborg et al. Contents Purpose How to install How it work

288 Jan 04, 2023
A python fast implementation of the famous SVD algorithm popularized by Simon Funk during Netflix Prize

⚡ funk-svd funk-svd is a Python 3 library implementing a fast version of the famous SVD algorithm popularized by Simon Funk during the Neflix Prize co

Geoffrey Bolmier 171 Dec 19, 2022
Microsoft Machine Learning for Apache Spark

Microsoft Machine Learning for Apache Spark MMLSpark is an ecosystem of tools aimed towards expanding the distributed computing framework Apache Spark

Microsoft Azure 3.9k Dec 30, 2022
A Software Framework for Neuromorphic Computing

A Software Framework for Neuromorphic Computing

Lava 338 Dec 26, 2022
This is the material used in my free Persian course: Machine Learning with Python

This is the material used in my free Persian course: Machine Learning with Python

Yara Mohamadi 4 Aug 07, 2022
TIANCHI Purchase Redemption Forecast Challenge

TIANCHI Purchase Redemption Forecast Challenge

Haorui HE 4 Aug 26, 2022
fastFM: A Library for Factorization Machines

Citing fastFM The library fastFM is an academic project. The time and resources spent developing fastFM are therefore justified by the number of citat

1k Dec 24, 2022
Home repository for the Regularized Greedy Forest (RGF) library. It includes original implementation from the paper and multithreaded one written in C++, along with various language-specific wrappers.

Regularized Greedy Forest Regularized Greedy Forest (RGF) is a tree ensemble machine learning method described in this paper. RGF can deliver better r

RGF-team 363 Dec 14, 2022
UpliftML: A Python Package for Scalable Uplift Modeling

UpliftML is a Python package for scalable unconstrained and constrained uplift modeling from experimental data. To accommodate working with big data, the package uses PySpark and H2O models as base l

Booking.com 254 Dec 31, 2022
Machine Learning Study 혼자 해보기

Machine Learning Study 혼자 해보기 기여자 (Contributors) ✨ Teddy Lee 🏠 HongJaeKwon 🏠 Seungwoo Han 🏠 Tae Heon Kim 🏠 Steve Kwon 🏠 SW Song 🏠 K1A2 🏠 Wooil

Teddy Lee 1.7k Jan 01, 2023
Avocado hass time series vs predict price

AVOCADO HASS TIME SERIES VÀ PREDICT PRICE Trước khi vào Heroku muốn giao diện đẹp mọi người chuyển giúp mình theo hình bên dưới https://avocado-hass.h

hieulmsc 3 Dec 18, 2021
A game theoretic approach to explain the output of any machine learning model.

SHAP (SHapley Additive exPlanations) is a game theoretic approach to explain the output of any machine learning model. It connects optimal credit allo

Scott Lundberg 18.2k Jan 02, 2023
100 Days of Machine and Deep Learning Code

💯 Days of Machine Learning and Deep Learning Code MACHINE LEARNING TOPICS COVERED - FROM SCRATCH Linear Regression Logistic Regression K Means Cluste

Tanishq Gautam 66 Nov 02, 2022
A statistical library designed to fill the void in Python's time series analysis capabilities, including the equivalent of R's auto.arima function.

pmdarima Pmdarima (originally pyramid-arima, for the anagram of 'py' + 'arima') is a statistical library designed to fill the void in Python's time se

alkaline-ml 1.3k Dec 22, 2022
A Multipurpose Library for Synthetic Time Series Generation in Python

TimeSynth Multipurpose Library for Synthetic Time Series Please cite as: J. R. Maat, A. Malali, and P. Protopapas, “TimeSynth: A Multipurpose Library

278 Dec 26, 2022
TensorFlow implementation of an arbitrary order Factorization Machine

This is a TensorFlow implementation of an arbitrary order (=2) Factorization Machine based on paper Factorization Machines with libFM. It supports: d

Mikhail Trofimov 785 Dec 21, 2022
PySurvival is an open source python package for Survival Analysis modeling

PySurvival What is Pysurvival ? PySurvival is an open source python package for Survival Analysis modeling - the modeling concept used to analyze or p

Square 265 Dec 27, 2022
Tools for mathematical optimization region

Tools for mathematical optimization region

林景 15 Nov 30, 2022