{"id":13958489,"url":"https://github.com/bsolomon1124/pyfinance","last_synced_at":"2025-04-04T08:04:14.480Z","repository":{"id":54393193,"uuid":"101308108","full_name":"bsolomon1124/pyfinance","owner":"bsolomon1124","description":"Python package designed for general financial and security returns analysis.","archived":false,"fork":false,"pushed_at":"2023-03-13T16:13:41.000Z","size":308,"stargazers_count":331,"open_issues_count":14,"forks_count":66,"subscribers_count":15,"default_branch":"master","last_synced_at":"2025-03-28T07:04:07.457Z","etag":null,"topics":["finance","investment-analysis","python3"],"latest_commit_sha":null,"homepage":"https://pypi.python.org/pypi/pyfinance","language":"Python","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/bsolomon1124.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-08-24T15:07:04.000Z","updated_at":"2025-02-24T20:25:48.000Z","dependencies_parsed_at":"2024-06-18T17:07:04.290Z","dependency_job_id":"5a62e684-68ef-414a-a9b6-c8175868b561","html_url":"https://github.com/bsolomon1124/pyfinance","commit_stats":{"total_commits":154,"total_committers":2,"mean_commits":77.0,"dds":"0.038961038961038974","last_synced_commit":"c6fd88ba4fb5c9f083ebc3ff60960a1b4df76c55"},"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bsolomon1124%2Fpyfinance","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bsolomon1124%2Fpyfinance/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bsolomon1124%2Fpyfinance/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bsolomon1124%2Fpyfinance/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bsolomon1124","download_url":"https://codeload.github.com/bsolomon1124/pyfinance/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247140834,"owners_count":20890520,"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":["finance","investment-analysis","python3"],"created_at":"2024-08-08T13:01:39.290Z","updated_at":"2025-04-04T08:04:14.463Z","avatar_url":"https://github.com/bsolomon1124.png","language":"Python","funding_links":[],"categories":["金融股票"],"sub_categories":["网络服务_其他"],"readme":"# pyfinance\n\npyfinance is a Python package built for investment management and analysis of security returns.\n\nIt is meant to be a complement to existing packages geared towards quantitative finance, such as [pyfolio](https://github.com/quantopian/pyfolio),\n[pandas-datareader](https://github.com/pydata/pandas-datareader), and [fecon235](https://github.com/rsvp/fecon235).\n\n\u003ctable\u003e\n\u003ctr\u003e\n  \u003ctd\u003eSupports\u003c/td\u003e\n  \u003ctd\u003ePython 3.5 | 3.6 | 3.7 | 3.8 | 3.9\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003eLatest Release\u003c/td\u003e\n  \u003ctd\u003e\n    \u003ca href=\"https://pypi.org/project/pyfinance/\"\u003e\n    \u003cimg src=\"https://img.shields.io/pypi/v/pyfinance.svg\" alt=\"latest release\" /\u003e\n    \u003c/a\u003e\n  \u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003ePackage Status\u003c/td\u003e\n  \u003ctd\u003e\n    \u003ca href=\"https://pypi.org/project/pyfinance/\"\u003e\n    \u003cimg src=\"https://img.shields.io/pypi/status/pyfinance.svg\" alt=\"status\" /\u003e\u003c/td\u003e\n    \u003c/a\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n  \u003ctd\u003eLicense\u003c/td\u003e\n  \u003ctd\u003e\n    \u003ca href=\"https://github.com/bsolomon1124/pyfinance/blob/master/LICENSE\"\u003e\n    \u003cimg src=\"https://img.shields.io/pypi/l/pyfinance.svg\" alt=\"license\" /\u003e\n    \u003c/a\u003e\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n## Contents\n\npyfinance is best explored on a module-by-module basis:\n\n| Module | Description |\n| ------ | ----------- |\n| `datasets.py`  | Financial dataset download \u0026 assembly via `requests`. |\n| `general.py`   | General-purpose financial computations, such as active share calculation, returns distribution approximation, and tracking error optimization. |\n| `ols.py`       | Ordinary least-squares (OLS) regression, supporting static and rolling cases, built with a matrix formulation and implemented with NumPy. |\n| `options.py`   | Vectorized option calculations, including Black-Scholes Merton European option valuation, Greeks, and implied volatility, as well as payoff determination for common money-spread option strategies. |\n| `returns.py`   | Statistical analysis of financial time series through the CAPM framework, designed to mimic functionality of software such as FactSet Research Systems and Zephyr, with improved speed and flexibility. |\n| `utils.py`     | Utilities not fitting into any of the above. |\n\nPlease note that `returns` and `general` are still in development; they are not thoroughly tested and have some NotImplemented features.\n\nInstallation\n\npyfinance is available via [PyPI](https://pypi.python.org/pypi/pyfinance/).  Install with pip:\n\n```bash\n$ python3 -m install pyfinance\n```\n\n**Note**: pyfinance aims for compatibility with all minor releases of Python 3.x, but does not guarantee workability with Python 2.x.\n\n## Dependencies\n\npyfinance relies primarily on Python's scientific stack, including NumPy, Pandas, Matplotlib, Seaborn, Scikit-Learn, and StatsModels.  Other dependencies include Beautiful Soup, Requests, xrld, and xmltodict.\n\nSee `setup.py` for specific version threshold requirements.\n\n## Tutorial\n\nThis is a walkthrough of some of pyfinance's features.\n\nThe `returns.py` module is designed for statistical analysis of financial time series through the CAPM framework, designed to mimic functionality of software such as FactSet Research Systems and Zephyr, with improved speed and flexibility.\n\nIts main class is `TSeries`, a subclassed Pandas Series.  The DataFrame equivalent, `TFrame`, is not yet implemented as of March 2018.\n\n`TSeries` implements a collection of new methods that pertain specifically to investment management and the study of security returns and asset performance, such cumulative return indices and drawdown.\n\nHere's an example of construction:\n\n```python\n\u003e\u003e\u003e import numpy as np\n\u003e\u003e\u003e import pandas as pd\n\u003e\u003e\u003e from pyfinance import TSeries\n\n\u003e\u003e\u003e np.random.seed(444)\n\n# Normally distributed with 0.08% daily drift term.\n\u003e\u003e\u003e s = np.random.randn(400) / 100 + 0.0008\n\u003e\u003e\u003e idx = pd.date_range(start='2016', periods=len(s))  # default daily freq.\n\u003e\u003e\u003e ts = TSeries(s, index=idx)\n\n\u003e\u003e\u003e ts.head()\n2016-01-01    0.0044\n2016-01-02    0.0046\n2016-01-03    0.0146\n2016-01-04    0.0126\n2016-01-05   -0.0086\nFreq: D, dtype: float64\n```\n\nAnd a few \"new\" methods:\n\n```python\n\u003e\u003e\u003e ts.max_drawdown()\n-0.12374551561531844\n\n# Downsample to quarterly compounded returns.\n\u003e\u003e\u003e ts.rollup('Q')\n2016-03-31    0.0450\n2016-06-30    0.1240\n2016-09-30    0.0631\n2016-12-31   -0.0081\n2017-03-31    0.1925\nFreq: Q-DEC, dtype: float64\n\n\u003e\u003e\u003e ts.anlzd_stdev()\n0.16318780660107757\n\n\u003e\u003e\u003e ts.sharpe_ratio(ddof=1)\n2.501797257311737\n```\n\nSome statistics are benchmark-relative.  For methods that take a `benchmark` parameter, `benchmark` can be either another `TSeries`, a Pandas Series, a 1d NumPy array.\n\n```python\n\u003e\u003e\u003e bmk = TSeries(np.random.randn(400) / 100 + .0005,\n...               index=ts.index)\n\u003e\u003e\u003e ts.beta_adj(bmk)\n0.3176455956603447\n\n\u003e\u003e\u003e ts.tracking_error(benchmark=bmk)\n0.23506660057562254\n```\n\nWith CAPM-related statistics such as alpha, beta, and R-squared, it can also be a Pandas DataFrame or 2d NumPy array.\n\n```python\n\u003e\u003e\u003e multi_bmk = pd.DataFrame(np.random.randn(400, 2) / 100 + .0005,\n...                          index=ts.index)\n\n\u003e\u003e\u003e # Multifactor model support.\n\u003e\u003e\u003e ts.alpha(multi_bmk)\n0.0010849614688207107\n```\n\n`TSeries` comes with just one additional and optional argument that must be as a keyword argument: `freq` (default `None`) allows for manual specification of the time-series frequency.  It may be any frequency string or anchored offset string recognized by Pandas, such as 'D', '5D', 'Q', 'Q-DEC', or 'BQS-APR'.\n\n```python\n\u003e\u003e\u003e # This is okay as long as a frequency can be inferred.\n\u003e\u003e\u003e ts.freq is None\nTrue\n```\n\nThe purpose of this extra parameter is to create an annualization factor for statistics that are given on an annualized basis, such as standard deviation.\n\nIf no frequency is passed explicitly, pyfinance will attempt to infer an annualization factor from the Index, with an exception being raised if neither of these yield a frequency.\n\n```python\n\u003e\u003e\u003e no_idx = TSeries(np.random.laplace(size=24) * .01 + .005,\n                     freq='M')\n\n\u003e\u003e\u003e no_idx.freq\n'M'\n\n\u003e\u003e\u003e no_idx.anlzd_ret()\n0.04975219957136123\n```\n\n`freq` can also be passed within some methods, which will override the class instance's `.freq` if it exists:\n\n```python\n\u003e\u003e\u003e no_idx.anlzd_ret(freq='W')  # Treat `no_idx` as weekly returns.\n0.2341731795205313\n```\n\n`datasets.py` provides for financial dataset download \u0026 assembly via `requests`.  It leverages sources including:\n\n- Ken French's data library (via `pandas-datareader`);\n- SEC.gov;\n- cboe.com;\n- AQR's dataset page;\n- fred.stlouisfed.org;\n- Robert Shiller's page at econ.yale.edu.\n\nBelow is a batch of examples.\n\nLoad SEC 13F filings:\n\n```python\n# Third Point LLC June 2017 13F\n\u003e\u003e\u003e from pyfinance import datasets\n\u003e\u003e\u003e url = 'https://www.sec.gov/Archives/edgar/data/1040273/000108514617001787/form13fInfoTable.xml'  # noqa\n\u003e\u003e\u003e df = datasets.load_13f(url=url)\n\u003e\u003e\u003e df.head()\n          nameOfIssuer   titleOfClass      cusip   value  votingAuthority\n0  ALEXION PHARMACE...            COM  015351109  152088          1250000\n1  ALIBABA GROUP HL...  SPONSORED ADS  01609W102  634050          4500000\n2         ALPHABET INC   CAP STK CL A  02079K305  534566           575000\n3           ANTHEM INC            COM  036752103  235162          1250000\n4       BANCO MACRO SA     SPON ADR B  05961W105   82971           900000\n```\n\nIndustry-portfolio monthly returns:\n\n```python\n\u003e\u003e\u003e from pyfinance import datasets\n\u003e\u003e\u003e ind = datasets.load_industries()\n\u003e\u003e\u003e ind.keys()\ndict_keys([5, 10, 12, 17, 30, 38, 48])\n\n# Monthly returns to 5 industry portfolios\n\u003e\u003e\u003e ind[5].head()\n            Cnsmr  Manuf  HiTec  Hlth   Other\nDate\n1950-01-31   1.26   1.47   3.21   1.06   3.19\n1950-02-28   1.91   1.29   2.06   1.92   1.02\n1950-03-31   0.28   1.93   3.46  -2.90  -0.68\n1950-04-30   3.22   5.21   3.58   5.52   1.50\n1950-05-31   3.81   6.18   1.07   3.96   1.36\n```\n\nS\u0026P 500 and interest rate data from Robert Shiller's website, 1871-present:\n\n```python\n\u003e\u003e\u003e from pyfinance import datasets\n\u003e\u003e\u003e shiller = datasets.load_shiller()\n\u003e\u003e\u003e shiller.iloc[:7, :5]\n            sp50p  sp50d  sp50e      cpi  real_rate\ndate\n1871-01-31   4.44   0.26    0.4  12.4641     5.3200\n1871-02-28   4.50   0.26    0.4  12.8446     5.3233\n1871-03-31   4.61   0.26    0.4  13.0350     5.3267\n1871-04-30   4.74   0.26    0.4  12.5592     5.3300\n1871-05-31   4.86   0.26    0.4  12.2738     5.3333\n1871-06-30   4.82   0.26    0.4  12.0835     5.3367\n1871-07-31   4.73   0.26    0.4  12.0835     5.3400\n```\n\nThe `ols.py` module provides ordinary least-squares (OLS) regression, supporting static and rolling cases, and is built with a matrix formulation and implemented with NumPy.\n\nFirst, let's load some data on currencies, interest rates, and commodities to generate a regression of changes in the trade-weighted USD against interest rate term spreads and copper.\n\n```python\n\u003e\u003e\u003e from pandas_datareader import DataReader\n\n\u003e\u003e\u003e syms = {\n...     'TWEXBMTH': 'usd',\n...     'T10Y2YM': 'term_spread',\n...     'PCOPPUSDM': 'copper'\n...     }\n\n\u003e\u003e\u003e data = DataReader(syms.keys(), data_source='fred',\n...                   start='2000-01-01', end='2016-12-31')\\\n...     .pct_change()\\\n...     .dropna()\\\n...     .rename(columns=syms)\n\n\u003e\u003e\u003e y = data.pop('usd')\n\n\u003e\u003e\u003e data.head()\n            term_spread  copper\nDATE\n2000-02-01      -1.4091 -0.0200\n2000-03-01       2.0000 -0.0372\n2000-04-01       0.5185 -0.0333\n2000-05-01      -0.0976  0.0614\n2000-06-01       0.0270 -0.0185\n\n\u003e\u003e\u003e y.head()\nDATE\n2000-02-01    0.0126\n2000-03-01   -0.0001\n2000-04-01    0.0056\n2000-05-01    0.0220\n2000-06-01   -0.0101\n```\n\nThe `OLS` class implements \"static\" (single) linear regression, with the model being fit when the object is instantiated.\n\nIt is designed primarily for statistical inference, not out-of-sample prediction, and its attributes largely mimic the structure of StatsModels' [RegressionResultsWrapper](http://www.statsmodels.org/dev/generated/statsmodels.regression.linear_model.RegressionResults.html).\n\n```python\n\u003e\u003e\u003e from pyfinance import ols\n\n\u003e\u003e\u003e model = ols.OLS(y=y, x=data)\n\n\u003e\u003e\u003e model.alpha  # the intercept - a scalar\n0.0012303204434167458\n\n\u003e\u003e\u003e model.beta  # the coefficients\narray([-0.0006, -0.0949])\n\n\u003e\u003e\u003e model.fstat\n33.42923069295481\n\n# Residuals and predicted y values are NumPy arrays\n# with the same shape as `y`.\n\u003e\u003e\u003e model.resids.shape\n(203,)\n\n\u003e\u003e\u003e model.predicted.shape\n(203,)\n```\n\nThe module also supports rolling regression.  (Iterative regressions done on sliding windows over the data.)\n\n- `RollingOLS` has methods that generate NumPy arrays as outputs.\n- `PandasRollingOLS` is a wrapper around `RollingOLS` and is meant to mimic the look of Pandas's deprecated `MovingOLS` class.  It generates Pandas DataFrame and Series outputs.\n\n**Note**: all solutions are generated through a matrix formulation, which takes advantage of NumPy's broadcasting capabilities to expand the classical [matrix formulation](https://onlinecourses.science.psu.edu/stat501/node/382) to an additional dimension.  This approach may be slow for significantly large datasets.\n\nAlso, note that windows are not \"time-aware\" in the way that Pandas time functionality is.  Because of the NumPy implementation, specifying a window of 12 where the index contains one missing months would generate a regression over 13 months.  To avoid this, simply reindex the input data to a set frequency.\n\n```python\n# 12-month rolling regressions\n# First entry would be the \"12 months ending\" 2001-01-30\n\u003e\u003e\u003e rolling = ols.PandasRollingOLS(y=y, x=data, window=12)\n\n\u003e\u003e\u003e rolling.beta.head()\n            term_spread  copper\nDATE\n2001-01-01   9.9127e-05  0.0556\n2001-02-01   4.7607e-04  0.0627\n2001-03-01   1.4671e-03  0.0357\n2001-04-01   1.6101e-03  0.0296\n2001-05-01   1.5839e-03 -0.0449\n\n\u003e\u003e\u003e rolling.alpha.head()\nDATE\n2001-01-01    0.0055\n2001-02-01    0.0050\n2001-03-01    0.0067\n2001-04-01    0.0070\n2001-05-01    0.0048\n\n\u003e\u003e\u003e rolling.pvalue_alpha.head()\nDATE\n2001-01-01    0.0996\n2001-02-01    0.1101\n2001-03-01    0.0555\n2001-04-01    0.0479\n2001-05-01    0.1020\n```\n\n`options.py` is built for vectorized options calculations.\n\n`BSM` encapsulates a European option and its associated value, Greeks, and implied volatility, using the Black-Scholes Merton model.\n\n```python\n\u003e\u003e\u003e from pyfinance.options import BSM\n\u003e\u003e\u003e op = BSM(S0=100, K=100, T=1, r=.04, sigma=.2)\n\n\u003e\u003e\u003e op.summary()\nOrderedDict([('Value', 9.925053717274437),\n             ('d1', 0.3),\n             ('d2', 0.09999999999999998),\n             ('Delta', 0.6179114221889526),\n             ('Gamma', 0.019069390773026208),\n             ('Vega', 38.138781546052414),\n             ('Theta', -5.888521694670074),\n             ('Rho', 51.86608850162082),\n             ('Omega', 6.225774084360724)])\n\n# What is the implied annualized volatility at P=10?\n\u003e\u003e\u003e op.implied_vol(value=10)\n0.20196480875586834\n\n# Vectorized - pass an array of strikes.\n\u003e\u003e\u003e import numpy as np\n\u003e\u003e\u003e ops = BSM(S0=100, K=np.arange(100, 110), T=1, r=.04, sigma=.2)\n\n\u003e\u003e\u003e ops.value()\narray([9.9251, 9.4159, 8.9257, 8.4543, 8.0015, 7.567 , 7.1506, 6.7519,\n       6.3706, 6.0064])\n\n# Multiple array inputs are evaluated elementwise/zipped.\n\u003e\u003e\u003e ops2 = BSM(S0=np.arange(100, 110), K=np.arange(100, 110),\n...            T=1, r=.04, sigma=.2)\n\n\u003e\u003e\u003e ops2\nBSM(kind=call,\n    S0=[100 101 102 103 104 105 106 107 108 109],\n    K=[100 101 102 103 104 105 106 107 108 109],\n    T=1,\n    r=0.04,\n    sigma=0.2)\n\n\u003e\u003e\u003e ops2.value()\narray([ 9.9251, 10.0243, 10.1236, 10.2228, 10.3221, 10.4213, 10.5206,\n       10.6198, 10.7191, 10.8183])\n```\n\n`options.py` also exports a handful of options *strategies*, such as `Straddle`, `Straddle`, `Strangle`, `BullSpread`, and `ShortButterfly`, to name a few.\n\nAll of these inherit from a generic and customizable `OpStrat` class, which can be built from an arbitrary number of puts and/or calls.\n\nHere is an example of constructing a bear spread, which is a combination of 2 puts or 2 calls (*put* is the default).  Here, we are short a put at 1950 and long a put at 2050.  Like the case of a single option, the instance methods are vectorized, so we can compute payoff and profit across a vector or grid:\n\n```python\n\u003e\u003e\u003e from pyfinance import options as op\n\n\u003e\u003e\u003e spread = op.BearSpread(St=np.array([2100, 2000, 1900]),\n...                        K1=1950., K2=2050.,\n...                        price1=56.01, price2=107.39)\n\n\u003e\u003e\u003e spread.payoff()\narray([  0.,  50., 100.])\n\n\u003e\u003e\u003e spread.profit()\narray([-51.38,  -1.38,  48.62])\n```\n\nThe `utils.py` module contains odds-and-ends utilities.\n\n```python\n\u003e\u003e\u003e from pyfinance import utils\n\n# Generate 7 unique 5-letter mutual fund tickers\n\u003e\u003e\u003e utils.random_tickers(length=5, n_tickers=7, endswith='X')\n['JXNQX', 'DPTJX', 'WAKOX', 'DZIHX', 'MDYXX', 'HSKWX', 'IDMZX']\n\n# Same for ETFs\n\u003e\u003e\u003e utils.random_tickers(3, 8)\n['FIS', 'FNN', 'FZC', 'PWV', 'PBA', 'RDG', 'BKY', 'CDW']\n\n# Five-asset portfolio leveraged 1.5x.\n\u003e\u003e\u003e utils.random_weights(size=5, sumto=1.5)\narray([0.3263, 0.1763, 0.4703, 0.4722, 0.0549])\n\n# Two 7-asset portfolios leverage 1.0x and 1.5x, respectively.\n\u003e\u003e\u003e utils.random_weights(size=(2, 7), sumto=[1., 1.5])\narray([[0.1418, 0.2007, 0.0255, 0.2575, 0.0929, 0.2272, 0.0544],\n       [0.3041, 0.109 , 0.2561, 0.2458, 0.3001, 0.0333, 0.2516]])\n\n\u003e\u003e\u003e utils.random_weights(size=(2, 7), sumto=[1., 1.5]).sum(axis=1)\narray([1. , 1.5])\n\n# Convert Pandas offset alises to periods per year.\n\u003e\u003e\u003e from pyfinance import utils\n\n\u003e\u003e\u003e utils.get_anlz_factor('M')\n12.0\n\u003e\u003e\u003e utils.get_anlz_factor('BQS-DEC')\n4.0\n```\n\n## API\n\nFor in-depth call syntaxes, see the source docstrings.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbsolomon1124%2Fpyfinance","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbsolomon1124%2Fpyfinance","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbsolomon1124%2Fpyfinance/lists"}