Common financial risk and performance metrics. Used by zipline and pyfolio.

Related tags

Financeempyrical
Overview

Build Status

PyPI

empyrical

Common financial risk metrics.

Table of Contents

Installation

pip install empyrical

Usage

Simple Statistics

import numpy as np
from empyrical import max_drawdown, alpha_beta

returns = np.array([.01, .02, .03, -.4, -.06, -.02])
benchmark_returns = np.array([.02, .02, .03, -.35, -.05, -.01])

# calculate the max drawdown
max_drawdown(returns)

# calculate alpha and beta
alpha, beta = alpha_beta(returns, benchmark_returns)

Rolling Measures

import numpy as np
from empyrical import roll_max_drawdown

returns = np.array([.01, .02, .03, -.4, -.06, -.02])

# calculate the rolling max drawdown
roll_max_drawdown(returns, window=3)

Pandas Support

import pandas as pd
from empyrical import roll_up_capture, capture

returns = pd.Series([.01, .02, .03, -.4, -.06, -.02])

# calculate a capture ratio
capture(returns)

# calculate capture for up markets on a rolling 60 day basis
roll_up_capture(returns, window=60)

Support

Please open an issue for support.

Deprecated: Data Reading via pandas-datareader

As of early 2018, Yahoo Finance has suffered major API breaks with no stable replacement, and the Google Finance API has not been stable since late 2017 (source). In recent months it has become a greater and greater strain on the empyrical development team to maintain support for fetching data through pandas-datareader and other third-party libraries, as these APIs are known to be unstable.

As a result, all empyrical support for data reading functionality has been deprecated and will be removed in a future version.

Users should beware that the following functions are now deprecated:

  • empyrical.utils.cache_dir
  • empyrical.utils.data_path
  • empyrical.utils.ensure_directory
  • empyrical.utils.get_fama_french
  • empyrical.utils.load_portfolio_risk_factors
  • empyrical.utils.default_returns_func
  • empyrical.utils.get_symbol_returns_from_yahoo

Users should expect regular failures from the following functions, pending patches to the Yahoo or Google Finance API:

  • empyrical.utils.default_returns_func
  • empyrical.utils.get_symbol_returns_from_yahoo

Contributing

Please contribute using Github Flow. Create a branch, add commits, and open a pull request.

Testing

  • install requirements
    • "nose>=1.3.7",
    • "parameterized>=0.6.1"
./runtests.py
Comments
  • Additional Calculations & Roll, Up, Down Helpers

    Additional Calculations & Roll, Up, Down Helpers

    Summary

    Added a few helper methods in the utils file that allow us to stack some transformation logic together before calling an actual metric. For example, if we want to calculate the rolling up capture of a strategy vs its benchmark, we want to be able to do something like [roll,up, capture] where roll, up, capture, are each methods that perform either a series deconstruction (roll), a filter (up), or a calculation (capture). Doing it this why is more DRY than embedding roll and filter logic in each method, but does add some complication.

    I elected to add a variety of small methods to the stats file that wrap the complexity described above. This way we keep the API the user is used to calling the same. e.g there is actually a method called rolling_up_capture that takes the expected "returns, factor_returns" arguments. That function simply calls the more complex stacked function to get the results.

    Details

    • added new methods details below.
    • added roll, up, and down as stackable methods to use in future calculations
    • added a handful of tests for new methods
    • corrected an issue with the max_drawdown. See note below
    • updated nose_parameterized to just parameterized
    • move date/period symbols into a separate file
    • added some examples to the README

    Not Done

    • add information_ratio per #41
    • bump empyrical version
    • add remainder of tests.

    Max Drawdown

    The max_drawdown code was not considering the first return in the array. The max_return array did not consider the starting value of 100 used in the function. In cases where ALL the returns in the array are negative, the max value in the array will be the 100 * (1+ the first negative return). For e.g if the first return in the array is -0.02, then the max value in the array will be 98. This will cause max drawdowns to appear less severe than if they started at 100.

    The max drawdown code was masquerading as correct because the negative_returns Series in the test suite starts with a 0. (i.e they aren't all negative).

    I've corrected that by ensuring that the cum_returns array starts with a value that matches the base value.

    New Methods

        capture,
        up_capture,
        down_capture,
        up_down_capture,
        up_alpha_beta,
        down_alpha_beta,
        roll_max_drawdown,
        roll_up_capture,
        roll_down_capture,
        roll_up_down_capture,
        roll_alpha_beta,
        roll_sharpe_ratio,
    

    Resolves #41 #46

    opened by cgdeboer 21
  • DEP: Deprecate all data reading functionality via pandas-datareader

    DEP: Deprecate all data reading functionality via pandas-datareader

    Closes #96 #89 #65 #64

    Deprecates all data-fetching functionality via pandas-datareader, and adds a simple_returns helper function to replace that functionality that was implicitly done in the data-fetchers.

    To quote the REAME:

    As of early 2018, Yahoo Finance has suffered major API breaks with no stable replacement, and the Google Finance API has not been stable since late 2017 (source). In recent months it has become a greater and greater strain on the empyrical development team to maintain support for fetching data through pandas-datareader and other third-party libraries, as these APIs are known to be unstable.

    As a result, all empyrical support for data reading functionality has been deprecated and will be removed in a future version.

    Users should beware that the following functions are now deprecated:

    • empyrical.utils.cache_dir
    • empyrical.utils.data_path
    • empyrical.utils.ensure_directory
    • empyrical.utils.get_utc_timestamp
    • empyrical.utils._1_bday_ago
    • empyrical.utils.get_fama_french
    • empyrical.utils.load_portfolio_risk_factors
    • empyrical.utils.default_returns_func
    • empyrical.utils.get_symbol_returns_from_yahoo

    Users should expect regular failures from the following functions, pending patches to the Yahoo or Google Finance API:

    • empyrical.utils.default_returns_func
    • empyrical.utils.get_symbol_returns_from_yahoo
    opened by eigenfoo 11
  • ENH Add beta_fragility_heuristic and gpd_risk_estimates functions

    ENH Add beta_fragility_heuristic and gpd_risk_estimates functions

    Hi,

    I thought it'd be interesting to add some risk metrics to empyrical for use in zipline/pyfolio.

    Here's the papers I used.

    • Beta Fragility: https://www.imf.org/external/pubs/ft/wp/2012/wp12216.pdf

    • GPD Risk Estimates: https://link.springer.com/article/10.1007/s10614-006-9025-7

    I wasn't sure about whether or not docstrings and tests are required for subroutines. (I'm missing some docstrings and tests for subroutines of gpd_risk_estimates.)

    If the above are required, please feel free to ping me back and I'll work on adding them.

    Thanks!

    Jeyan

    opened by jeyoor 10
  • ENH Allow cum_returns to accept DataFrame

    ENH Allow cum_returns to accept DataFrame

    In order for cum_returns to correctly support vector input, we need to check all columns using np.all.

    Before, we were getting this error when passing some vector returns:

    ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
    

    cc @twiecki

    opened by gusgordon 10
  • Migrate data loaders and related functions from pyfolio

    Migrate data loaders and related functions from pyfolio

    See this comment https://github.com/quantopian/alphalens/pull/183#issuecomment-321880108 and PR for context on this PR. Also this empyrical issue https://github.com/quantopian/empyrical/issues/55

    opened by jameschristopher 9
  • fix43: wrap logic in a try suite

    fix43: wrap logic in a try suite

    To handle the case #43 where object to be returned from max_drawdown may be Series/ndarray, invoked min on it. If it is already a float scalar then AttributeError will be raised and appropriately handled.

    opened by avi-analytics 8
  • Fix for pandas 1.0

    Fix for pandas 1.0

    FIXED for Pandas >= 1.0.0

    • as_matrix() was deprecated then removed. to_numpy() works in this situation

    • updated travis to include pandas 1.0.x, python 3.7 numpy 1.18 and scipy 1.4.x

      • previously travis only had very old pandas, and this change is not backwards compatible before Pandas 0.23
    • kept a python 2.7 build with the last supported versions of pydata.

    opened by atkinson 6
  • Remove Information Ratio

    Remove Information Ratio

    Our Information Ratio calculation (https://github.com/quantopian/empyrical/blob/master/empyrical/stats.py#L590) is wrong as noted by @marketneutral: "The definition is wrong. You need a risk model to calc active risk to benchmark. And the benchmark look through to calc active return."

    As this is still a ways off, we should rather delete it instead of having a wrong measure in here.

    opened by twiecki 6
  • Wrong annualization of Sortino Ratio?

    Wrong annualization of Sortino Ratio?

    The Sortino Ratio is annualized in stats.py as follows: return sortino * ann_factor

    where ann_factor is ann_factor = annualization_factor(period, annualization)

    I believe you actually meant to return return sortino * np.sqrt(ann_factor)

    just like you did with the Sharpe Ratio.

    opened by gabrieleiacono 5
  • Fix sortino_ratio downside_risk

    Fix sortino_ratio downside_risk

    This is needed because if yearly data is given, then the Sortino ratio (sortino_ratio) can be overridden by setting the annualization value but when downside risk is calculated in the downside_risk function it will default to daily as annualization is not carried forward thus affecting the final value.

    opened by lostVkng 5
  • ENH: Use ddof=0 and nanstd, remove skipped test

    ENH: Use ddof=0 and nanstd, remove skipped test

    Empyrical is not generally used for the sample of a large population. Change the degrees of freedom(ddof) to 0 because that is how the standard deviation of a population is calculated. Regressive tests have been updated to reflect change in method.

    Use nanstd instead of np.std for consistency.

    There was a flapping test without sound logic that is being removed as well.

    opened by analicia 5
  • Assertion error

    Assertion error

    Hi,

    This is the only error occurring while I'm running tests: python runtests.py

    /usr/lib/python3.8/site-packages/pandas/util/__init__.py:12: FutureWarning: pandas.util.testing is deprecated. Use the functions in the public API at pandas.testing instead.
      import pandas.util.testing
    .F...............................................................................................................................................................................................................................................................ssssssss.....s.s...s.ss.......................................................s................................................................................................................................................s...............ssssssss.....s.s...s.ss.......................................................s................................................................................................................................................s...............
    ======================================================================
    FAIL: test_perf_attrib_simple (empyrical.tests.test_perf_attrib.PerfAttribTestCase)
    ----------------------------------------------------------------------
    Traceback (most recent call last):
      File "/empyrical-0.5.5/empyrical/tests/test_perf_attrib.py", line 69, in test_perf_attrib_simple
        pd.util.testing.assert_frame_equal(expected_perf_attrib_output,
      File "/usr/lib/python3.8/site-packages/pandas/_testing.py", line 1611, in assert_frame_equal
        assert_series_equal(
      File "/usr/lib/python3.8/site-packages/pandas/_testing.py", line 1327, in assert_series_equal
        assert lidx.freq == ridx.freq, (lidx.freq, ridx.freq)
    AssertionError: (<Day>, None)
    
    ----------------------------------------------------------------------
    Ran 735 tests in 0.827s
    
    FAILED (failures=1, skipped=30)
    
    opened by antoscha 0
  • empyrical.stats.value_at_risk output is NaN

    empyrical.stats.value_at_risk output is NaN

    empyrical.stats.value_at_risk output is NaN. I cannot figure out what the problem is as all the other empyrical.stats functions work perfectly with the same data serie. Also, where I can access the source codes of the stats. This was provided in the earlier version of empyrical. Thanks,

    opened by Mo-Iravani 0
  • ENH: add expected max drawdown function (#90)

    ENH: add expected max drawdown function (#90)

    I needed the expected maximum drawdown function for Brownian motion, as described in #90, so I decided to create a PR! It does not fully solve the issue, as I do not compute the Calmar ratio, but it should be trivial to build that on top of this function.

    opened by pepicello 0
  • Uncaught Exception: FutureWarning: pandas.util.testing is deprecated. Use the functions in the public API at pandas.testing instead.

    Uncaught Exception: FutureWarning: pandas.util.testing is deprecated. Use the functions in the public API at pandas.testing instead.

      File "/usr/local/bin/jesse", line 11, in <module>
        load_entry_point('jesse', 'console_scripts', 'jesse')()
      File "/usr/local/lib/python3.8/dist-packages/click/core.py", line 829, in __call__
        return self.main(*args, **kwargs)
      File "/usr/local/lib/python3.8/dist-packages/click/core.py", line 782, in main
        rv = self.invoke(ctx)
      File "/usr/local/lib/python3.8/dist-packages/click/core.py", line 1259, in invoke
        return _process_result(sub_ctx.command.invoke(sub_ctx))
      File "/usr/local/lib/python3.8/dist-packages/click/core.py", line 1066, in invoke
        return ctx.invoke(self.callback, **ctx.params)
      File "/usr/local/lib/python3.8/dist-packages/click/core.py", line 610, in invoke
        return callback(*args, **kwargs)
      File "/home/src/jesse/jesse/__init__.py", line 307, in backtest
        from jesse.modes import backtest_mode
      File "/home/src/jesse/jesse/modes/backtest_mode/__init__.py", line 10, in <module>
        import jesse.services.statistics as stats
      File "/home/src/jesse/jesse/services/statistics.py", line 1, in <module>
        import empyrical
      File "/usr/local/lib/python3.8/dist-packages/empyrical/__init__.py", line 21, in <module>
        from .stats import (
      File "/usr/local/lib/python3.8/dist-packages/empyrical/stats.py", line 24, in <module>
        from .utils import nanmean, nanstd, nanmin, up, down, roll, rolling_window
      File "/usr/local/lib/python3.8/dist-packages/empyrical/utils.py", line 27, in <module>
        from pandas_datareader import data as web
      File "/usr/local/lib/python3.8/dist-packages/pandas_datareader/__init__.py", line 2, in <module>
        from .data import (
      File "/usr/local/lib/python3.8/dist-packages/pandas_datareader/data.py", line 11, in <module>
        from pandas_datareader.av.forex import AVForexReader
      File "/usr/local/lib/python3.8/dist-packages/pandas_datareader/av/__init__.py", line 5, in <module>
        from pandas_datareader._utils import RemoteDataError
      File "/usr/local/lib/python3.8/dist-packages/pandas_datareader/_utils.py", line 6, in <module>
        from pandas_datareader.compat import is_number
      File "/usr/local/lib/python3.8/dist-packages/pandas_datareader/compat/__init__.py", line 7, in <module>
        from pandas.util.testing import assert_frame_equal
      File "/usr/local/lib/python3.8/dist-packages/pandas/util/testing.py", line 5, in <module>
        warnings.warn(
    =========================================================================
     Uncaught Exception: FutureWarning: pandas.util.testing is deprecated. Use the functions in the public API at pandas.testing instead.```
    
    We have this annoying FutureWarning. Looks like its origin is empyrical.
    opened by cryptocoinserver 1
  • Community Contributions

    Community Contributions

    Are open source contributions still welcomed/wanted? If so are there any active issues? I had a look at github issues, but they all seemed pretty outdated.

    opened by shaneding 3
Releases(0.5.5)
  • 0.5.4(Oct 13, 2020)

  • 0.5.3(Aug 27, 2019)

  • 0.5.2(Aug 15, 2019)

  • 0.5.0(Aug 15, 2019)

    Author: Vikram Narayan [email protected] Date: Fri Jun 15 12:33:29 2018 -0400

    Merge pull request #102 from quantopian/license
    
    MAINT: add year/name to license
    

    commit 85e1b0fa518a1193beee66a5118b6ee20554b9d7 Author: vikram-narayan [email protected] Date: Fri Jun 15 12:13:21 2018 -0400

    MAINT: add year/name to license
    

    commit 30a5c4c9eab9a3fd6e7a1ad64baf99a7872391aa Author: George Ho [email protected] Date: Thu Jun 14 14:43:04 2018 +0000

    DEP: Deprecate all data reading functionality via pandas-datareader (#97)
    
    * DEP: Deprecate all functions using pandas-datareader
    
    * DOC: Update README with deprecation documentation
    
    * STY: Markdown style
    
    * STY: Markdown style again
    
    * REV: revert previous commit
    
    * STY: typo
    
    * STY: consistent naming convention
    
    * DEP: also deprecate any cacheing of data
    
    * DEP: forgot to deprecate additional funcs
    
    * REV: get_utc_timestamp should not be deprecated
    
    * ENH: add function to compute returns from prices
    
    * BUG: wrap import in try-except
    
    * MAINT: update deprecation warning
    
    * MAINT: move `simple_returns` func to `stats` module
    
    * MAINT: don't raise deprecation warning for _1_bday_ago
    
    * DOC: remove suggestions
    
    * TST: added test for simple_returns
    
    * MAINT: add simple_returns to init
    
    * TST: fixed simple_returns test
    
    * STY: use size, not shape
    
    * TST: tests passing
    
    * DOC: 1_bday_ago no longer deprecated
    

    commit 7d39c4ab8cb6f86a3b8fccf37c08421422f287d9 Author: Scott Sanderson [email protected] Date: Wed Jun 13 10:33:06 2018 -0400

    ENH: Allow 2D input in cum_returns_final.
    

    commit 6408f85780c3d956cec7d587039443844069aadd Author: Todd [email protected] Date: Sat Jun 9 23:21:39 2018 -0400

    Include LICENSE file in wheels
    
    Although not strictly required by the license, having a copy of the license file is preferred by some groups such as Linux distros that repackage the software.  This makes sure the license is included in the wheels.  See the wheel documentation [here](https://wheel.readthedocs.io/en/stable/#including-the-license-in-the-generated-wheel-file) for more information.
    
    Source code(tar.gz)
    Source code(zip)
  • 0.4.3(May 2, 2018)

  • 0.4.2(Mar 12, 2018)

  • 0.4.1(Mar 12, 2018)

    • Fixes a bug where indices of pandas objects were not preserved by some rolling operations. (https://github.com/quantopian/empyrical/pull/85).
    Source code(tar.gz)
    Source code(zip)
  • 0.4.0(Feb 23, 2018)

Owner
Quantopian, Inc.
Quantopian builds software tools and libraries for quantitative finance.
Quantopian, Inc.
'Personal Finance' is a project where people can manage and track their expenses

Personal Finance by Abhiram Rishi Pratitpati 'Personal Finance' is a project where people can manage and track their expenses. It is hard to keep trac

Abhiram Rishi Prattipati 1 Dec 21, 2021
A proper portfolio tracker. Featuring historical allocation, cash flows and real returns.

Python Portfolio Analytics A portfolio tracker featuring account transactions, historical allocation, dividends and splits management and endless perf

Simone Precicchiani 13 Aug 13, 2022
stock data on eink with raspberry

small python skript to display tradegate data on a waveshare e-ink important you need locale "de_AT.UTF-8 UTF-8" installed. do so in raspi-config's Lo

Simon Oberhammer 24 Feb 22, 2022
ARCH models in Python

arch Autoregressive Conditional Heteroskedasticity (ARCH) and other tools for financial econometrics, written in Python (with Cython and/or Numba used

Kevin Sheppard 1k Jan 04, 2023
Yahoo! Finance market data downloader (+faster Pandas Datareader)

Yahoo! Finance market data downloader Ever since Yahoo! finance decommissioned their historical data API, many programs that relied on it to stop work

Ran Aroussi 8.4k Jan 01, 2023
Q-Fin: A Python library for mathematical finance.

Q-Fin A Python library for mathematical finance. Installation https://pypi.org/project/QFin/ pip install qfin Bond Pricing Option Pricing Black-Schol

Roman Paolucci 247 Jan 01, 2023
Indicator divergence library for python

Indicator divergence library This module aims to help to find bullish/bearish divergences (regular or hidden) between two indicators using argrelextre

8 Dec 13, 2022
Portfolio and risk analytics in Python

pyfolio pyfolio is a Python library for performance and risk analysis of financial portfolios developed by Quantopian Inc. It works well with the Zipl

Quantopian, Inc. 4.8k Jan 08, 2023
Python Backtesting library for trading strategies

backtrader Yahoo API Note: [2018-11-16] After some testing it would seem that data downloads can be again relied upon over the web interface (or API v

DRo 9.8k Dec 30, 2022
scrilla: A Financial Optimization Application

A python application that wraps around AlphaVantage, Quandl and IEX APIs, calculates financial statistics and optimizes portfolio allocations.

Grant Moore 6 Dec 17, 2022
Performance analysis of predictive (alpha) stock factors

Alphalens Alphalens is a Python Library for performance analysis of predictive (alpha) stock factors. Alphalens works great with the Zipline open sour

Quantopian, Inc. 2.5k Dec 28, 2022
Technical Analysis Library using Pandas and Numpy

Technical Analysis Library in Python It is a Technical Analysis library useful to do feature engineering from financial time series datasets (Open, Cl

Darío López Padial 3.4k Jan 02, 2023
Python library for backtesting trading strategies & analyzing financial markets (formerly pythalesians)

finmarketpy (formerly pythalesians) finmarketpy is a Python based library that enables you to analyze market data and also to backtest trading strateg

Cuemacro 3k Dec 30, 2022
Fourth and final milestone project

Milestone Project 4: Pound Dog Click link to visit "Pound Dog" Aim of the project The aim of this project is to provide access to a website informing

Jamie Wilson 1 Oct 31, 2021
This repository provides all Python codes and Jupyter Notebooks of the book Python for Finance

Python for Finance (O'Reilly) This repository provides all Python codes and Jupyter Notebooks of the book Python for Finance -- Analyze Big Financial

Yves Hilpisch 1.6k Jan 03, 2023
Python sync/async framework for Interactive Brokers API

Introduction The goal of the IB-insync library is to make working with the Trader Workstation API from Interactive Brokers as easy as possible. The ma

Ewald de Wit 2k Dec 30, 2022
ffn - a financial function library for Python

ffn - Financial Functions for Python Alpha release - please let me know if you find any bugs! If you are looking for a full backtesting framework, ple

Philippe Morissette 1.4k Jan 01, 2023
Zipline, a Pythonic Algorithmic Trading Library

Zipline is a Pythonic algorithmic trading library. It is an event-driven system for backtesting. Zipline is currently used in production as the backte

Quantopian, Inc. 15.7k Jan 02, 2023
A banking system is a group or network of institutions that provide financial services for us

A banking system is a group or network of institutions that provide financial services for us. These institutions are responsible for operating a payment system, providing loans, taking deposits, and

UTTKARSH PARMAR 1 Oct 24, 2021