diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index e1a092a5..08f6a80f 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -13,9 +13,11 @@ jobs: matrix: python-version: ["3.10", "3.11", "3.12", "3.13"] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - name: Install Dependencies @@ -35,4 +37,4 @@ jobs: if: ${{ matrix.python-version == '3.12' }} run: codecov env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index aed7282e..02e53649 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -10,9 +10,11 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: '3.x' - name: Install dependencies diff --git a/CLAUDE.md b/CLAUDE.md index ec0d9127..6f5b3cff 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -43,6 +43,16 @@ The library is a single-file module with these key components: - `` - uses default column and window (e.g., `rsi`, `macd`) - `_` - uses default column with custom window (e.g., `rsi_6`) - `__` - full specification (e.g., `close_20_sma`) +- `_delta` - difference from previous row (e.g., `close_delta`) +- `_x_` / `_xu_` / `_xd_` - cross/cross-up/cross-down between two columns +- `_le_`, `_ge_`, `_lt_`, `_gt_`, `_eq_`, `_ne_` - comparison operators between columns + +**Column resolution order** (in `__init_not_exist_column`): +1. Check the `handler` property map (multi-column indicators like macd/macds/macdh) +2. Check for `_delta` suffix +3. Check for cross patterns (`_x_`, `_xu_`, `_xd_`) +4. Check for comparison patterns (`_le_`, `_ge_`, etc.) +5. Parse as `(column, window, name)` and dispatch to `_get_` handler **Configuration**: - `_dft_windows` dict: default window sizes for each indicator diff --git a/MANIFEST.in b/MANIFEST.in index 354a0ee0..56c1e98a 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,3 +1,2 @@ -include *.rst -include *.cfg -include *.txt \ No newline at end of file +include *.toml +include *.txt diff --git a/README.md b/README.md index 4386c393..87197d17 100644 --- a/README.md +++ b/README.md @@ -4,75 +4,26 @@ [![codecov](https://codecov.io/gh/jealous/stockstats/branch/master/graph/badge.svg?token=IFMD1pVJ7T)](https://codecov.io/gh/jealous/stockstats) [![pypi](https://img.shields.io/pypi/v/stockstats.svg)](https://pypi.python.org/pypi/stockstats) -VERSION: 0.6.7 - ## Introduction -Supply a wrapper ``StockDataFrame`` for ``pandas.DataFrame`` with inline stock +Supply a wrapper `StockDataFrame` for `pandas.DataFrame` with inline stock statistics/indicators support. Supported statistics/indicators are: -* delta -* permutation (zero-based) -* log return -* max in range -* min in range -* middle = (close + high + low) / 3 -* compare: le, ge, lt, gt, eq, ne -* count: both backward(c) and forward(fc) -* cross: including upward cross and downward cross -* SMA: Simple Moving Average -* EMA: Exponential Moving Average -* MSTD: Moving Standard Deviation -* MVAR: Moving Variance -* RSV: Raw Stochastic Value -* RSI: Relative Strength Index -* KDJ: Stochastic Oscillator -* Bolling: Bollinger Band -* MACD: Moving Average Convergence Divergence -* CR: Energy Index (Intermediate Willingness Index) -* WR: Williams Overbought/Oversold index -* CCI: Commodity Channel Index -* TR: True Range -* ATR: Average True Range -* DMA: Different of Moving Average (10, 50) -* DMI: Directional Moving Index, including - * +DI: Positive Directional Indicator - * -DI: Negative Directional Indicator - * ADX: Average Directional Movement Index - * ADXR: Smoothed Moving Average of ADX -* TRIX: Triple Exponential Moving Average -* TEMA: Another Triple Exponential Moving Average -* VR: Volume Variation Index -* MFI: Money Flow Index -* VWMA: Volume Weighted Moving Average -* CHOP: Choppiness Index -* KER: Kaufman's efficiency ratio -* KAMA: Kaufman's Adaptive Moving Average -* PPO: Percentage Price Oscillator -* StochRSI: Stochastic RSI -* WT: LazyBear's Wave Trend -* Supertrend: with the Upper Band and Lower Band -* Aroon: Aroon Oscillator -* Z: Z-Score -* AO: Awesome Oscillator -* BOP: Balance of Power -* MAD: Mean Absolute Deviation -* ROC: Rate of Change -* Coppock: Coppock Curve -* Ichimoku: Ichimoku Cloud -* CTI: Correlation Trend Indicator -* LRMA: Linear Regression Moving Average -* ERI: Elder-Ray Index -* FTR: the Gaussian Fisher Transform Price Reversals indicator -* RVGI: Relative Vigor Index -* Inertia: Inertia Indicator -* KST: Know Sure Thing -* PGO: Pretty Good Oscillator -* PSL: Psychological Line -* PVO: Percentage Volume Oscillator -* QQE: Quantitative Qualitative Estimation +**Moving Averages**: SMA, EMA, SMMA, TEMA, LRMA, KAMA, VWMA, DMA + +**Momentum**: RSI, StochRSI, MACD, PPO, KDJ, ROC, CMO, KST, Coppock, AO, BOP, CTI, Inertia, PSL + +**Trend**: Supertrend, Aroon, Ichimoku, CR, DMI (+DI/-DI/ADX/ADXR), TRIX, WT + +**Volatility**: Bollinger Bands, ATR, TR, CCI, WR, CHOP, KER, Z-Score, MAD, PGO + +**Volume**: VR, MFI, PVO, VWMA + +**Oscillators**: QQE, RVGI, ERI, FTR + +**Utilities**: delta, shift, log return, cross/cross-up/cross-down, comparisons (le/ge/lt/gt/eq/ne), count, max/min in range, permutation ## Installation @@ -80,289 +31,265 @@ Supported statistics/indicators are: ## Compatibility -The build checks the compatibility for the last two major releases of python3 and -the last release of python2. +Requires Python 3.9+. CI tests against Python 3.10, 3.11, 3.12, and 3.13. ## License [BSD-3-Clause License](./LICENSE.txt) -## Tutorial +## Quick Start -### Initialization +### Load and wrap data -`StockDataFrame` works as a wrapper for the `pandas.DataFrame`. You need to -Initialize the `StockDataFrame` with `wrap` or `StockDataFrame.retype`. +`StockDataFrame` works as a wrapper for `pandas.DataFrame`. Initialize it +with `wrap` or `StockDataFrame.retype`. ``` python import pandas as pd from stockstats import wrap -data = pd.read_csv('stock.csv') -df = wrap(data) +# from CSV +df = wrap(pd.read_csv('stock.csv')) + +# from yfinance (disable multi-level index for compatibility) +import yfinance as yf +df = wrap(yf.download('AAPL', multi_level_index=False)) ``` -Formalize your data. This package takes for granted that your data is sorted by -timestamp and contains certain columns. Please align your column name. +Your data should contain these columns (case-insensitive): -* `date`: timestamp of the record, optional. * `close`: the close price of the period * `high`: the highest price of the interval * `low`: the lowest price of the interval * `volume`: the volume of stocks traded during the interval +* `date`: timestamp of the record, optional (used as index by default) -Note these column names are case-insensitive. They are converted to lower case -when you wrap the data frame. +You can specify the index column name in `wrap` or `retype`. Use `unwrap` +to convert back to a plain `pandas.DataFrame`. -By default, the `date` column is used as the index. Users can also specify the -index column name in the `wrap` or `retype` function. - -Example: -`DataFrame` loaded from CSV. +### Access indicators -``` - Date Amount Close High Low Volume -0 20040817 90923240.0 11.20 12.21 11.03 7877900 -1 20040818 52955668.0 10.29 10.90 10.29 5043200 -2 20040819 32614676.0 10.53 10.65 10.30 3116800 -... ... ... ... ... ... ... -2810 20160815 56416636.0 39.58 39.79 38.38 1436706 -2811 20160816 68030472.0 39.66 40.86 39.00 1703600 -2812 20160817 62536480.0 40.45 40.59 39.12 1567600 -``` +Indicators are calculated on first access. Delete a column to force +re-evaluation. -After conversion to `StockDataFrame` +``` python +# indicators with default windows +rsi = df['rsi'] # 14-period RSI (default) +rsi6 = df['rsi_6'] # 6-period RSI +# moving averages on any column +sma = df['close_20_sma'] # 20-period SMA of close +ema = df['high_10_ema'] # 10-period EMA of high ``` - amount close high low volume -date -20040817 90923240.0 11.20 12.21 11.03 7877900 -20040818 52955668.0 10.29 10.90 10.29 5043200 -20040819 32614676.0 10.53 10.65 10.30 3116800 -... ... ... ... ... ... -20160815 56416636.0 39.58 39.79 38.38 1436706 -20160816 68030472.0 39.66 40.86 39.00 1703600 -20160817 62536480.0 40.45 40.59 39.12 1567600 -``` - -Use `unwrap` to convert it back to a `pandas.DataFrame`. -Note that `unwrap` won't reset the columns and the index. - -### `yfinance` support - -When retrieving data from yfinance, the resulting DataFrame may have a multi-index. -This can cause issues with the wrap function. -To handle this, a workaround is provided to identify and extract the actual -series when a multi-index is present. However, this approach has a limitation: -new columns generated by stockstats will not include the additional column index. +### Multi-line indicators -The recommended solution is to disable the multi-level index when retrieving -data from yfinance. This ensures compatibility without additional processing. -An example is provided below: +Some indicators generate multiple columns at once. -```python -import yfinance as yf +``` python +# MACD generates three columns at once +df.get('macd') +print(df[['macd', 'macds', 'macdh']].tail()) -# Disable multi-level index when downloading data -data = yf.download('VIXY', multi_level_index=False) +# Bollinger Bands +df.get('boll') +print(df[['boll', 'boll_ub', 'boll_lb']].tail()) ``` -By disabling the multi-level index, the DataFrame structure remains simple, -and subsequent operations can be performed seamlessly. - -### Access the Data - -`StockDataFrame` is a subclass of `pandas.DataFrame`. All the functions -of `pandas.DataFrame` should work the same as before. +### Signal detection -#### Retrieve the data with symbol - -We allow the user to access the statistics directly with some specified column -name, such as `kdjk`, `macd`, `rsi`. - -The values of these columns are calculated the first time you access -them from the data frame. Please delete those columns first if you want the -lib to re-evaluate them. - -#### Retrieve the Series +``` python +# cross-over detection +golden_cross = df['close_10_sma_xu_close_50_sma'] # 10 SMA crosses above 50 SMA -Use `macd = stock['macd']` or `rsi = stock.get('rsi')` to retrieve the `Series`. +# comparison operators +overbought = df['rsi_ge_70'] # True when RSI >= 70 +``` -#### Retrieve the symbol with 2 arguments +### Initialize all indicators with shortcuts -Some statistics need the column name and the window size, -such as delta, shift, simple moving average, etc. Use this patter to retrieve -them: `__` +Some indicators, such as KDJ, BOLL, MFI, have shortcuts. Use `df.init_all()` +to initialize all these indicators. -Examples: +This operation generates lots of columns. Please use it with caution. -* 5 periods simple moving average of the high price: `high_5_sma` -* 10 periods exponential moving average of the close: `close_10_ema` -* 1 period delta of the high price: `high_-1_d`. - The minus symbol means looking backward. +## Tutorial -#### Retrieve the symbol with 1 argument +### Column naming patterns + +Use pattern `__` for full control: + +* `high_5_sma` - 5 periods simple moving average of the high price +* `close_10_ema` - 10 periods exponential moving average of the close +* `high_-1_d` - 1 period delta of the high price (minus means looking backward) + +Use pattern `_` when only the window varies: + +* `rsi_6` - 6 periods RSI +* `cci_10` - 10 periods CCI +* `atr_13` - 13 periods ATR + +Some indicators have default windows. Check their documentation for details. + +### Configurable parameters + +Some statistics have configurable parameters. They are class-level fields. Changes +are global and won't affect existing results. Remove existing columns so that they +will be re-evaluated the next time you access them. + +## Statistics/Indicators + +### Summary + +| Name | Access Pattern | Default Window | Description | +|------|---------------|----------------|-------------| +| SMA | `close_20_sma` | - | Simple Moving Average | +| EMA | `close_20_ema` | - | Exponential Moving Average | +| SMMA | `close_7_smma` | - | Smoothed Moving Average | +| TEMA | `tema` | 5 | Triple Exponential Moving Average | +| LRMA | `close_10_lrma` | - | Linear Regression Moving Average | +| KAMA | `close_2_kama` | 10, 5, 34 | Kaufman's Adaptive Moving Average | +| VWMA | `vwma` | 14 | Volume Weighted Moving Average | +| DMA | `dma` | 10, 50 | Difference of Moving Average | +| RSI | `rsi` | 14 | Relative Strength Index | +| StochRSI | `stochrsi` | 14 | Stochastic RSI | +| MACD | `macd` | 12, 26, 9 | Moving Average Convergence Divergence | +| PPO | `ppo` | 12, 26, 9 | Percentage Price Oscillator | +| KDJ | `kdjk` | 9 | Stochastic Oscillator | +| ROC | `close_10_roc` | - | Rate of Change | +| CMO | `cmo` | 14 | Chande Momentum Oscillator | +| KST | `kst` | - | Know Sure Thing | +| Coppock | `coppock` | 10, 11, 14 | Coppock Curve | +| AO | `ao` | 5, 34 | Awesome Oscillator | +| BOP | `bop` | - | Balance of Power | +| CTI | `cti` | 12 | Correlation Trend Indicator | +| Inertia | `inertia` | 20, 14 | Inertia Indicator | +| PSL | `psl` | 12 | Psychological Line | +| Supertrend | `supertrend` | 14 | Supertrend indicator | +| Aroon | `aroon` | 25 | Aroon Oscillator | +| Ichimoku | `ichimoku` | 9, 26, 52 | Ichimoku Cloud | +| CR | `cr` | 26 | Energy Index | +| DMI | `pdi`, `ndi`, `adx` | 14 | Directional Movement Index | +| TRIX | `trix` | 12 | Triple Exponential Average | +| WT | `wt1`, `wt2` | 10, 21 | Wave Trend | +| Bollinger | `boll` | 20 | Bollinger Bands | +| ATR | `atr` | 14 | Average True Range | +| TR | `tr` | - | True Range | +| CCI | `cci` | 14 | Commodity Channel Index | +| WR | `wr` | 14 | Williams %R | +| CHOP | `chop` | 14 | Choppiness Index | +| KER | `ker` | 10 | Kaufman's Efficiency Ratio | +| Z-Score | `close_75_z` | - | Z-Score | +| MAD | `close_10_mad` | - | Mean Absolute Deviation | +| PGO | `pgo` | 14 | Pretty Good Oscillator | +| VR | `vr` | 26 | Volume Variation Index | +| MFI | `mfi` | 14 | Money Flow Index | +| PVO | `pvo` | 12, 26, 9 | Percentage Volume Oscillator | +| QQE | `qqe` | 14, 5 | Quantitative Qualitative Estimation | +| RVGI | `rvgi` | 14 | Relative Vigor Index | +| ERI | `eribull`, `eribear` | 13 | Elder-Ray Index | +| FTR | `ftr` | 9 | Gaussian Fisher Transform | + +--- + +### Moving Averages -Some statistics require the window size but not the column name. Use -this patter to specify your window: `_` +#### [Simple Moving Average](https://www.investopedia.com/terms/m/mean.asp) -Examples: +Follow the pattern `__sma` to retrieve a simple moving average. -* 6 periods RSI: `rsi_6` -* 10 periods CCI: `cci_10` -* 13 periods ATR: `atr_13` +#### [Exponential Moving Average](https://www.investopedia.com/terms/e/ema.asp) -Some of them have default windows. Check their document for detail. +Follow the pattern `__ema` to retrieve an exponential moving average. -#### Initialize all indicators with shortcuts +#### SMMA - Smoothed Moving Average -Some indicators, such as KDJ, BOLL, MFI, have shortcuts. Use `df.init_all()` -to initialize all these indicators. +It requires column and window. -This operation generates lots of columns. Please use it with caution. +For example, use `df['close_7_smma']` to retrieve the 7 periods smoothed moving +average of the close price. -### Statistics/Indicators +#### [TEMA - Triple Exponential Moving Average](https://www.forextraders.com/forex-education/forex-technical-analysis/triple-exponential-moving-average-the-tema-indicator/) -Some statistics have configurable parameters. They are class-level fields. Change -of these fields is global. And they won't affect the existing results. Removing -existing columns so that they will be re-evaluated the next time you access them. +TEMA is another implementation for the triple exponential moving average. -#### Delta of Periods +``` +TEMA = (3 x EMA) - (3 x EMA of EMA) + (EMA of EMA of EMA) +``` -Using pattern `__d` to retrieve the delta between different periods. +It takes two parameters, column and window. By default, the column is `close`, +the window is 5. -You can also use `_delta` as a shortcut to `_-1_d` +Use `set_dft_window('tema', n)` to change the default window. Examples: -* `df['close_-1_d']` retrieves the close price delta between current and prev. period. -* `df['close_delta']` is the same as `df['close_-1_d']` -* `df['high_2_d']` retrieves the high price delta between current and 2 days later - -#### Shift Periods - -Shift the column backward or forward. It takes 2 parameters: - -* the name of the column to shift -* periods to shift, can be negative -We fill the head and tail with the nearest data. +* `df['tema']` stands for 5 periods TEMA for the close price. +* `df['middle_10_tema']` stands for the 10 periods TEMA for the typical price. -See the example below: +#### [LRMA - Linear Regression Moving Average](https://www.daytrading.com/moving-linear-regression) -``` python -In [15]: df[['close', 'close_-1_s', 'close_2_s']] -Out[15]: - close close_-1_s close_2_s -date -20040817 11.20 11.20 10.53 -20040818 10.29 11.20 10.55 -20040819 10.53 10.29 10.10 -20040820 10.55 10.53 10.25 -... ... ... ... -20160812 39.10 38.70 39.66 -20160815 39.58 39.10 40.45 -20160816 39.66 39.58 40.45 -20160817 40.45 39.66 40.45 +Linear regression works by taking various data points in a sample and +providing a "best fit" line to match the general trend in the data. -[2813 rows x 3 columns] -``` +Implementation reference: -#### [RSI - Relative Strength Index](https://en.wikipedia.org/wiki/Relative_strength_index) +https://github.com/twopirllc/pandas-ta/blob/main/pandas_ta/overlap/linreg.py -RSI has a configurable window. The default window size is 14 which is -configurable through `set_dft_window('rsi', n)`. e.g. +Examples: +* `df['close_10_lrma']` linear regression of close price with window size 10 -* `df['rsi']`: 14 periods RSI -* `df['rsi_6']`: 6 periods RSI +#### [KAMA - Kaufman's Adaptive Moving Average](https://school.stockcharts.com/doku.php?id=technical_indicators:kaufman_s_adaptive_moving_average) -#### [Log Return of the Close](https://en.wikipedia.org/wiki/Rate_of_return) +Kaufman's Adaptive Moving Average is designed to account for market noise or +volatility. -Logarithmic return = ln( close / last close) +It has 2 optional parameters and 2 required parameters: +* fast - optional, the parameter for fast EMA smoothing, default to 5 +* slow - optional, the parameter for slow EMA smoothing, default to 34 +* column - required, the column to calculate +* window - required, rolling window size -From wiki: +The default value for window, fast and slow can be configured with +`set_dft_window('kama', (10, 5, 34))` -> For example, if a stock is priced at 3.570 USD per share at the close on -> one day, and at 3.575 USD per share at the close the next day, then the -> logarithmic return is: ln(3.575/3.570) = 0.0014, or 0.14%. +Examples: +* `df['close_10,2,30_kama']` retrieves 10 periods KAMA of the close + price with `fast = 2` and `slow = 30` +* `df['close_2_kama']` retrieves 2 periods KAMA of the close price + with default fast and slow -Use `df['log-ret']` to access this column. +#### [VWMA - Volume Weighted Moving Average](https://www.investopedia.com/articles/trading/11/trading-with-vwap-mvwap.asp) -#### Count of Non-Zero Value +It's the moving average weighted by volume. -Count non-zero values of a specific range. It requires a column and a window. +It has a parameter for window size. The default window is 14. Change it with +`set_dft_window('vwma', n)`. Examples: +* `df['vwma']` retrieves the 14 periods VWMA +* `df['vwma_6']` retrieves the 6 periods VWMA -* Count how many typical prices are larger than close in the past 10 periods - -``` python -In [22]: tp = df['middle'] - -In [23]: df['res'] = df['middle'] > df['close'] - -In [24]: df[['middle', 'close', 'res', 'res_10_c']] -Out[24]: - middle close res res_10_c -date -20040817 11.480000 11.20 True 1.0 -20040818 10.493333 10.29 True 2.0 -20040819 10.493333 10.53 False 2.0 -20040820 10.486667 10.55 False 2.0 -20040823 10.163333 10.10 True 3.0 -... ... ... ... ... -20160811 38.703333 38.70 True 5.0 -20160812 38.916667 39.10 False 5.0 -20160815 39.250000 39.58 False 4.0 -20160816 39.840000 39.66 True 5.0 -20160817 40.053333 40.45 False 5.0 - -[2813 rows x 4 columns] -``` - -* Count ups in the past 10 periods +#### DMA - Difference of Moving Average -``` python -In [26]: df['ups'], df['downs'] = df['change'] > 0, df['change'] < 0 - -In [27]: df[['ups', 'ups_10_c', 'downs', 'downs_10_c']] -Out[27]: - ups ups_10_c downs downs_10_c -date -20040817 False 0.0 False 0.0 -20040818 False 0.0 True 1.0 -20040819 True 1.0 False 1.0 -20040820 True 2.0 False 1.0 -20040823 False 2.0 True 2.0 -... ... ... ... ... -20160811 False 3.0 True 7.0 -20160812 True 3.0 False 7.0 -20160815 True 4.0 False 6.0 -20160816 True 5.0 False 5.0 -20160817 True 5.0 False 5.0 - -[2813 rows x 4 columns] -``` +`df['dma']` retrieves the difference of 10 periods SMA of the close price and +the 50 periods SMA of the close price. -#### Max and Min of the Periods +#### [Moving Standard Deviation](https://www.investopedia.com/terms/s/standarddeviation.asp) -Retrieve the max/min value of specified periods. They require column and -window. -Note the window does NOT simply stand for the rolling window. +Follow the pattern `__mstd` to retrieve the moving STD. -Examples: +#### [Moving Variance](https://www.investopedia.com/terms/v/variance.asp) -* `close_-3,2_max` stands for the max of 2 periods later and 3 periods ago -* `close_-2~0_min` stands for the min of 2 periods ago till now +Follow the pattern `__mvar` to retrieve the moving VAR. -#### RSV - Raw Stochastic Value +--- -RSV is essential for calculating KDJ. It takes a window parameter. -Use `df['rsv']` or `df['rsv_6']` to access it. +### Momentum #### [RSI - Relative Strength Index](https://en.wikipedia.org/wiki/Relative_strength_index) -RSI chart the current and historical strength or weakness of a stock. It takes +RSI charts the current and historical strength or weakness of a stock. It takes a window parameter. The default window is 14. Use `set_dft_window('rsi', n)` to tune it. @@ -374,7 +301,7 @@ Examples: #### [Stochastic RSI](https://www.investopedia.com/terms/s/stochrsi.asp) -Stochastic RSI gives traders an idea of whether the current RSI value is +Stochastic RSI gives traders an idea of whether the current RSI value is overbought or oversold. It takes a window parameter. The default window is 14. Use `set_dft_window('stochrsi', n)` to tune it. @@ -384,27 +311,56 @@ Examples: * `df['stochrsi']`: retrieve the Stochastic RSI of 14 periods * `df['stochrsi_6']`: retrieve the Stochastic RSI of 6 periods -#### [WT - Wave Trend](https://medium.com/@samuel.mcculloch/lets-take-a-look-at-wavetrend-with-crosses-lazybear-s-indicator-2ece1737f72f) +#### [MACD - Moving Average Convergence Divergence](https://en.wikipedia.org/wiki/MACD) -Retrieve the LazyBear's Wave Trend with `df['wt1']` and `df['wt2']`. +We use the close price to calculate the MACD lines. +* `df['macd']` is the difference between two exponential moving averages. +* `df['macds']` is the signal line. +* `df['macdh']` is the histogram line. -Wave trend uses two parameters. You can tune them with -`set_dft_window('wt', (10, 21))`. +The period of short, long EMA and signal line can be tuned with +`set_dft_window('macd', (short, long, signal))`. The default +windows are 12 and 26 and 9. -#### SMMA - Smoothed Moving Average +Note: In July 2017 the code for MACDH was changed to drop an extra 2x multiplier +on the final value to align with calculation methods used in tools like +cryptowatch, tradingview, etc. -It requires column and window. +#### [PPO - Percentage Price Oscillator](https://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:price_oscillators_ppo) -For example, use `df['close_7_smma']` to retrieve the 7 periods smoothed moving -average of the close price. +The Percentage Price Oscillator includes three lines. + +* `df['ppo']` derives from the difference of 2 exponential moving average. +* `df['ppos']` is the signal line. +* `df['ppoh']` is the histogram line. + +The period of short, long EMA and signal line can be tuned with +`set_dft_window('ppo', (short, long, signal))`. The default +windows are 12 and 26 and 9. + +#### [KDJ Indicator](https://en.wikipedia.org/wiki/Stochastic_oscillator) + +The stochastic oscillator is a momentum indicator that uses support and +resistance levels. + +It includes three lines: +* `df['kdjk']` - K series +* `df['kdjd']` - D series +* `df['kdjj']` - J series + +The default window is 9. Use `set_dft_window('kdjk', n)` to change it. +Use `df['kdjk_6']` to retrieve the K series of 6 periods. + +KDJ also has two configurable parameters named `StockDataFrame.KDJ_PARAM`. +The default value is `(2.0/3.0, 1.0/3.0)` #### [ROC - Rate of Change](https://www.investopedia.com/terms/p/pricerateofchange.asp) -The Price Rate of Change (ROC) is a momentum-based technical indicator -that measures the percentage change in price between the current price +The Price Rate of Change (ROC) is a momentum-based technical indicator +that measures the percentage change in price between the current price and the price a certain number of periods ago. -Formular: +Formula: ROC = (PriceP - PricePn) / PricePn * 100 @@ -418,121 +374,139 @@ Examples: * `df['close_10_roc']`: the ROC of the close price in 10 periods * `df['high_5_roc']`: the ROC of the high price in 5 periods -#### [MAD - Mean Absolute Deviation](https://www.khanacademy.org/math/statistics-probability/summarizing-quantitative-data/other-measures-of-spread/a/mean-absolute-deviation-mad-review) - -The mean absolute deviation of a dataset is the average -distance between each data point and the mean. It gives -us an idea about the variability in a dataset. - -Formular: -1. Calculate the mean. -2. Calculate how far away each data point is from the - mean using positive distances. These are called - absolute deviations. -3. Add those deviations together. -4. Divide the sum by the number of data points. - -Example: -* `df['close_10_mad']`: the MAD of the close price in 10 periods +#### [CMO - Chande Momentum Oscillator](https://www.investopedia.com/terms/c/chandemomentumoscillator.asp) -#### [TRIX - Triple Exponential Average](https://www.investopedia.com/articles/technical/02/092402.asp) +The Chande Momentum Oscillator (CMO) is a technical momentum +indicator developed by Tushar Chande. -The triple exponential average is used to identify oversold and overbought -markets. +The formula calculates the difference between the sum of recent +gains and the sum of recent losses and then divides the result +by the sum of all price movements over the same period. -The algorithm is: +The default window is 14. +Formula: ``` -TRIX = (TripleEMA - LastTripleEMA) - * 100 / LastTripleEMA -TripleEMA = EMA of EMA of EMA -LastTripleEMA = TripleEMA of the last period +CMO = 100 * ((sH - sL) / (sH + sL)) ``` -It requires column and window. By default, the column is `close`, -the window is 12. - -Use `set_dft_window('trix', n)` to change the default window. +where: +* sH=the sum of higher closes over N periods +* sL=the sum of lower closes of N periods Examples: +* `df['cmo']` returns the CMO with a window of 14 +* `df['cmo_5']` returns the CMO with a window of 5 -* `df['trix']` stands for 12 periods Trix for the close price. -* `df['middle_10_trix']` stands for the 10 periods Trix for the typical price. - -#### [TEMA - Another Triple Exponential Average](https://www.forextraders.com/forex-education/forex-technical-analysis/triple-exponential-moving-average-the-tema-indicator/) - -Tema is another implementation for the triple exponential moving average. +#### [KST - Know Sure Thing](https://www.investopedia.com/terms/k/know-sure-thing-kst.asp) -``` -TEMA=(3 x EMA) - (3 x EMA of EMA) + (EMA of EMA of EMA) -``` +The Know Sure Thing (KST) is a momentum oscillator developed by +Martin Pring to make rate-of-change readings easier for traders +to interpret. -It takes two parameters, column and window. By default, the column is `close`, -the window is 5. +Formula: +* KST=(RCMA1x1)+(RCMA2x2)+(RCMA3x3)+(RCMA4x4) -Use `set_dft_window('tema', n)` to change the default window. +Where: +* RCMA1=10-period SMA of 10-period ROC +* RCMA2=10-period SMA of 15-period ROC +* RCMA3=10-period SMA of 20-period ROC +* RCMA4=15-period SMA of 30-period ROC -Examples: +Example: +* `df['kst']` retrieves the KST. -* `df['tema']` stands for 12 periods TEMA for the close price. -* `df['middle_10_tema']` stands for the 10 periods TEMA for the typical price. +#### [Coppock Curve](https://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:coppock_curve) -#### [VR - Volume Variation Index](https://help.eaglesmarkets.com/hc/en-us/articles/900002867026-Summary-of-volume-variation-index) +Coppock Curve is a momentum indicator that signals +long-term trend reversals. -It is the strength index of the trading volume. +Formula: -It has a default window of 26. Change it with `set_dft_window('vr', n)`. +Coppock Curve = 10-period WMA of (14-period RoC + 11-period RoC) +WMA = Weighted Moving Average +RoC = Rate-of-Change Examples: -* `df['vr']` retrieves the 26 periods VR. -* `df['vr_6']` retrieves the 6 periods VR. +* `df['coppock']` returns the Coppock Curve with default windows +* `df['coppock_5,10,15']` returns the Coppock Curve with WMA window 5, + fast window 10, slow window 15. -#### [WR - Williams Overbought/Oversold Index](https://www.investopedia.com/terms/w/williamsr.asp) +#### [Awesome Oscillator](https://www.ifcm.co.uk/ntx-indicators/awesome-oscillator) -Williams Overbought/Oversold index -is a type of momentum indicator that moves between 0 and -100 and measures -overbought and oversold levels. +The AO indicator is a good indicator for measuring the market dynamics, +it reflects specific changes in the driving force of the market, which +helps to identify the strength of the trend, including the points of +its formation and reversal. -It takes a window parameter. The default window is 14. Use `set_dft_window('wr', n)` -to change the default window. +Awesome Oscillator Formula -Examples: +* MEDIAN PRICE = (HIGH+LOW)/2 +* AO = SMA(MEDIAN PRICE, 5)-SMA(MEDIAN PRICE, 34) -* `df['wr']` retrieves the 14 periods WR. -* `df['wr_6']` retrieves the 6 periods WR. +Examples: +* `df['ao']` returns the Awesome Oscillator with default windows (5, 34) +* `df['ao_3,10']` returns the Awesome Oscillator with a window of 3 and 10 -#### [CCI - Commodity Channel Index](https://www.investopedia.com/terms/c/commoditychannelindex.asp) +#### [Balance of Power](https://school.stockcharts.com/doku.php?id=technical_indicators:balance_of_power) -CCI stands for Commodity Channel Index. +Balance of Power (BOP) measures the strength of the bulls vs. bears. -It requires a window parameter. The default window is 14. Use -`set_dft_window('cci', n)` to change it. +Formula: +``` +BOP = (close - open) / (high - low) +``` + +Example: +* `df['bop']` returns the Balance of Power + +#### [Correlation Trend Indicator](https://tlc.thinkorswim.com/center/reference/Tech-Indicators/studies-library/C-D/CorrelationTrendIndicator) + +Correlation Trend Indicator is a study that estimates +the current direction and strength of a trend. + +Implementation is based on the following code: + +https://github.com/twopirllc/pandas-ta/blob/main/pandas_ta/momentum/cti.py Examples: +* `df['cti']` returns the CTI of close price with window 12 +* `df['high_5_cti']` returns the CTI of high price with window 5 -* `df['cci']` retrieves the default 14 periods CCI. -* `df['cci_6']` retrieves the 6 periods CCI. +#### [Inertia Indicator](https://theforexgeek.com/inertia-indicator/) -#### TR - True Range of Trading +In financial markets, the concept of inertia was given by Donald Dorsey +in the 1995 issue of Technical Analysis of Stocks and Commodities +through the Inertia Indicator. The Inertia Indicator is moment-based +and is an extension of Dorsey's Relative Volatility Index (RVI). -TR is a measure of the volatility of a High-Low-Close series. It is used for -calculating the ATR. +Formula: +* inertia = n periods linear regression of RVGI -#### [ATR - Average True Range](https://en.wikipedia.org/wiki/Average_true_range) +Examples: +* `df['inertia']` retrieves the inertia of 20 periods linear regression of 14 periods RVGI +* `df['inertia_10']` retrieves the inertia of 10 periods linear regression of 14 periods RVGI -The Average True Range is an -N-period smoothed moving average (SMMA) of the true range value. -Default to 14 periods. +#### [Psychological Line (PSL)](https://library.tradingtechnologies.com/trade/chrt-ti-psychological-line.html) -Users can modify the default window with `set_dft_window('atr', n)`. +The Psychological Line indicator is the ratio of the number of +rising periods over the total number of periods. + +Formula: +* PSL = (Number of Rising Periods) / (Total Number of Periods) * 100 Example: +* `df['psl']` retrieves the PSL with default window 12. +* `df['psl_10']` retrieves the PSL with window 10. +* `df['high_12_psl']` retrieves the PSL of high price with window 12. -* `df['atr']` retrieves the 14 periods ATR. -* `df['atr_5']` retrieves the 5 periods ATR. +--- + +### Trend #### [Supertrend](https://economictimes.indiatimes.com/markets/stocks/news/how-to-use-supertrend-indicator-to-find-buying-and-selling-opportunities-in-market/articleshow/54492970.cms) -Supertrend indicates the current trend. +Supertrend indicates the current trend. We use the [algorithm described here](https://medium.com/codex/step-by-step-implementation-of-the-supertrend-indicator-in-python-656aa678c111). It includes 3 lines: * `df['supertrend']` is the trend line. @@ -541,12 +515,69 @@ It includes 3 lines: It has 2 parameters: * `StockDataFrame.SUPERTREND_MUL` is the multiplier of the band, default to 3. -* the default window size is 14. Change it with `set_dft_window('supertrend', n)` +* the default window size is 14. Change it with `set_dft_window('supertrend', n)` -#### DMA - Difference of Moving Average +#### [Aroon Oscillator](https://www.investopedia.com/terms/a/aroonoscillator.asp) -`df['dma']` retrieves the difference of 10 periods SMA of the close price and -the 50 periods SMA of the close price. +The Aroon Oscillator measures the strength of a trend and +the likelihood that it will continue. + +The default window is 25. + +* Aroon Oscillator = Aroon Up - Aroon Down +* Aroon Up = 100 * (n - periods since n-period high) / n +* Aroon Down = 100 * (n - periods since n-period low) / n +* n = window size + +Examples: +* `df['aroon']` returns Aroon oscillator with a window of 25 +* `df['aroon_14']` returns Aroon oscillator with a window of 14 + +#### [Ichimoku Cloud](https://www.investopedia.com/terms/i/ichimoku-cloud.asp) + +The Ichimoku Cloud is a collection of technical indicators +that show support and resistance levels, as well as momentum +and trend direction. + +In this implementation, we only calculate the delta between +lead A and lead B (which is the width of the cloud). + +It contains three windows: +* window for the conversion line, default to 9 +* window for the baseline and the shifts, default to 26 +* window for the leading line, default to 52 + +Formula: +* conversion line = (PH9 + PL9) / 2 +* baseline = (PH26 + PL26) / 2 +* leading span A = (conversion line + baseline) / 2 +* leading span B = (PH52 + PL52) / 2 +* result = leading span A - leading span B + +Where: +* PH = Period High +* PL = Period Low + +Examples: +* `df['ichimoku']` returns the ichimoku cloud width with default windows +* `df['ichimoku_7,22,44']` returns the ichimoku cloud width with window sizes + 7, 22, 44 + +#### [CR - Energy Index](https://support.futunn.com/en/topic167/?lang=en-us) + +The Energy Index (Intermediate Willingness Index) +uses the relationship between the highest price, the lowest price and +yesterday's middle price to reflect the market's willingness to buy +and sell. + +It contains 4 lines: +* `df['cr']` - the CR line +* `df['cr-ma1']` - `StockDataFrame.CR_MA[0]` periods of the CR moving average, + the default window is 5 +* `df['cr-ma2']` - `StockDataFrame.CR_MA[1]` periods of the CR moving average, + the default window is 10 +* `df['cr-ma3']` - `StockDataFrame.CR_MA[2]` periods of the CR moving average, + the default window is 20 #### [DMI - Directional Movement Index](https://www.investopedia.com/terms/d/dmi.asp) @@ -569,149 +600,111 @@ It has several parameters. * `StockDataFrame.ADX_EMA` - window for ADX, default to 6 * `StockDataFrame.ADXR_EMA` - window for ADXR, default to 6 -#### [KDJ Indicator](https://en.wikipedia.org/wiki/Stochastic_oscillator) +#### [TRIX - Triple Exponential Average](https://www.investopedia.com/articles/technical/02/092402.asp) -The stochastic oscillator is a momenxtum indicator that uses support and -resistance levels. +The triple exponential average is used to identify oversold and overbought +markets. -It includes three lines: -* `df['kdjk']` - K series -* `df['kdjd']` - D series -* `df['kdjj']` - J series +The algorithm is: -The default window is 9. Use `set_dft_window('kdjk', n)` to change it. -Use `df['kdjk_6']` to retrieve the K series of 6 periods. +``` +TRIX = (TripleEMA - LastTripleEMA) * 100 / LastTripleEMA +TripleEMA = EMA of EMA of EMA +LastTripleEMA = TripleEMA of the last period +``` -KDJ also has two configurable parameters named `StockDataFrame.KDJ_PARAM`. -The default value is `(2.0/3.0, 1.0/3.0)` +It requires column and window. By default, the column is `close`, +the window is 12. -#### [CR - Energy Index](https://support.futunn.com/en/topic167/?lang=en-us) +Use `set_dft_window('trix', n)` to change the default window. -The Energy Index (Intermediate Willingness Index) -uses the relationship between the highest price, the lowest price and -yesterday's middle price to reflect the market's willingness to buy -and sell. +Examples: -It contains 4 lines: -* `df['cr']` - the CR line -* `df['cr-ma1']` - `StockDataFrame.CR_MA[0]` periods of the CR moving average, - the default window is 5 -* `df['cr-ma2']` - `StockDataFrame.CR_MA[1]` periods of the CR moving average, - the default window is 10 -* `df['cr-ma3']` - `StockDataFrame.CR_MA[2]` periods of the CR moving average, - the default window is 20 +* `df['trix']` stands for 12 periods Trix for the close price. +* `df['middle_10_trix']` stands for the 10 periods Trix for the typical price. -#### [Typical Price](https://en.wikipedia.org/wiki/Typical_price) +#### [WT - Wave Trend](https://medium.com/@samuel.mcculloch/lets-take-a-look-at-wavetrend-with-crosses-lazybear-s-indicator-2ece1737f72f) -It's the average of `high`, `low` and `close`. -Use `df['middle']` to access this value. +Retrieve the LazyBear's Wave Trend with `df['wt1']` and `df['wt2']`. -When `amount` is available, `middle = amount / volume` -This should be more accurate because amount represents the total cash flow. +Wave trend uses two parameters. You can tune them with +`set_dft_window('wt', (10, 21))`. + +--- + +### Volatility #### [Bollinger Bands](https://en.wikipedia.org/wiki/Bollinger_Bands) -The Bollinger bands includes three lines +The Bollinger bands includes three lines: * `df['boll']` is the baseline * `df['boll_ub']` is the upper band * `df['boll_lb']` is the lower band The default window of boll is 20. -You can also supply your window with `df['boll_10']`. It will also +You can also supply your window with `df['boll_10']`. It will also generate the `boll_ub_10` and `boll_lb_10` column. The default period of the Bollinger Band can be changed with -`set_dft_window('boll', n)`. The width of the bands can be turned with -`StockDataFrame.BOLL_STD_TIMES`. The default value is 2. - -#### [MACD - Moving Average Convergence Divergence](https://en.wikipedia.org/wiki/MACD) +`set_dft_window('boll', n)`. The width of the bands can be tuned with +`StockDataFrame.BOLL_STD_TIMES`. The default value is 2. -We use the close price to calculate the MACD lines. -* `df['macd']` is the difference between two exponential moving averages. -* `df['macds]` is the signal line. -* `df['macdh']` is he histogram line. +#### TR - True Range of Trading -The period of short, long EMA and signal line can be tuned with -`set_dft_window('macd', (short, long, signal))`. The default -windows are 12 and 26 and 9. +TR is a measure of the volatility of a High-Low-Close series. It is used for +calculating the ATR. -#### [PPO - Percentage Price Oscillator](https://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:price_oscillators_ppo) +#### [ATR - Average True Range](https://en.wikipedia.org/wiki/Average_true_range) -The Percentage Price Oscillator includes three lines. +The Average True Range is an +N-period smoothed moving average (SMMA) of the true range value. +Default to 14 periods. -* `df['ppo']` derives from the difference of 2 exponential moving average. -* `df['ppos]` is the signal line. -* `df['ppoh']` is he histogram line. +Users can modify the default window with `set_dft_window('atr', n)`. -The period of short, long EMA and signal line can be tuned with -`set_dft_window('ppo', (short, long, signal))`. The default -windows are 12 and 26 and 9. +Example: -#### [Simple Moving Average](https://www.investopedia.com/terms/m/mean.asp) +* `df['atr']` retrieves the 14 periods ATR. +* `df['atr_5']` retrieves the 5 periods ATR. -Follow the pattern `__sma` to retrieve a simple moving average. +#### [CCI - Commodity Channel Index](https://www.investopedia.com/terms/c/commoditychannelindex.asp) -#### [Moving Standard Deviation](https://www.investopedia.com/terms/s/standarddeviation.asp) +CCI stands for Commodity Channel Index. -Follow the pattern `__mstd` to retrieve the moving STD. +It requires a window parameter. The default window is 14. Use +`set_dft_window('cci', n)` to change it. -#### [Moving Variance](https://www.investopedia.com/terms/v/variance.asp) +Examples: -Follow the pattern `__mvar` to retrieve the moving VAR. +* `df['cci']` retrieves the default 14 periods CCI. +* `df['cci_6']` retrieves the 6 periods CCI. -#### [Volume Weighted Moving Average](https://www.investopedia.com/articles/trading/11/trading-with-vwap-mvwap.asp) +#### [WR - Williams Overbought/Oversold Index](https://www.investopedia.com/terms/w/williamsr.asp) -It's the moving average weighted by volume. +Williams Overbought/Oversold index +is a type of momentum indicator that moves between 0 and -100 and measures +overbought and oversold levels. -It has a parameter for window size. The default window is 14. Change it with -`set_dft_window('vwma', n)`. +It takes a window parameter. The default window is 14. Use `set_dft_window('wr', n)` +to change the default window. Examples: -* `df['vwma']` retrieves the 14 periods VWMA -* `df['vwma_6']` retrieves the 6 periods VWMA + +* `df['wr']` retrieves the 14 periods WR. +* `df['wr_6']` retrieves the 6 periods WR. #### [CHOP - Choppiness Index](https://www.tradingview.com/education/choppinessindex/) The Choppiness Index determines if the market is choppy. -It has a parameter for window size. The default window is 14. Change it with +It has a parameter for window size. The default window is 14. Change it with `set_dft_window('chop', n)`. Examples: * `df['chop']` retrieves the 14 periods CHOP * `df['chop_6']` retrieves the 6 periods CHOP -#### [MFI - Money Flow Index](https://www.investopedia.com/terms/m/mfi.asp) - -The Money Flow Index -identifies overbought or oversold signals in an asset. - -It has a parameter for window size. The default window is 14. Change it with -`set_dft_window('mfi', n)`. - -Examples: -* `df['mfi']` retrieves the 14 periods MFI -* `df['mfi_6']` retrieves the 6 periods MFI - -#### [ERI - Elder-Ray Index](https://admiralmarkets.com/education/articles/forex-indicators/bears-and-bulls-power-indicator) - -The Elder-Ray Index contains the bull and the bear power. -Both are calculated based on the EMA of the close price. - -The default window is 13. - -Formular: -* Bulls Power = High - EMA -* Bears Power = Low - EMA -* EMA is exponential moving average of close of N periods - -Examples: -* `df['eribull']` retrieves the 13 periods bull power -* `df['eribear']` retrieves the 13 periods bear power -* `df['eribull_5']` retrieves the 5 periods bull power -* `df['eribear_5']` retrieves the 5 periods bear power - -#### [KER - Kaufman's efficiency ratio](https://strategyquant.com/codebase/kaufmans-efficiency-ratio-ker/) +#### [KER - Kaufman's Efficiency Ratio](https://strategyquant.com/codebase/kaufmans-efficiency-ratio-ker/) The Efficiency Ratio (ER) is calculated by dividing the price change over a period by the @@ -726,7 +719,7 @@ The default column is close. The default window is 10. -Formular: +Formula: * window_change = ABS(close - close[n]) * last_change = ABS(close-close[1]) * volatility = moving sum of last_change in n @@ -736,216 +729,203 @@ Examples: * `df['ker']` retrieves the 10 periods KER of the close price * `df['high_5_ker']` retrieves 5 periods KER of the high price -#### [KAMA - Kaufman's Adaptive Moving Average](https://school.stockcharts.com/doku.php?id=technical_indicators:kaufman_s_adaptive_moving_average) - -Kaufman's Adaptive Moving Average is designed to account for market noise or -volatility. - -It has 2 optional parameters and 2 required parameters -* fast - optional, the parameter for fast EMA smoothing, default to 5 -* slow - optional, the parameter for slow EMA smoothing, default to 34 -* column - required, the column to calculate -* window - required, rolling window size +#### [Z-Score](https://www.investopedia.com/terms/z/zscore.asp) -The default value for window, fast and slow can be configured with -`set_dft_window('kama', (10, 5, 34))` +Z-score is a statistical measurement that describes a value's relationship to +the mean of a group of values. -Examples: -* `df['close_10,2,30_kama']` retrieves 10 periods KAMA of the close - price with `fast = 2` and `slow = 30` -* `df['close_2_kama']` retrieves 2 periods KAMA of the close price - with default fast and slow +There is no default column name or window for Z-Score. -#### Cross Upwards and Cross Downwards +The statistical formula for a value's z-score is calculated using +the following formula: -Use the pattern `_xu_` to check when A crosses up B. +``` +z = ( x - mu ) / sigma +``` -Use the pattern `_xd_` to check when A crosses down B. +Where: -Use the pattern `_x_` to check when A crosses B. +* `z` = Z-score +* `x` = the value being evaluated +* `mu` = the mean +* `sigma` = the standard deviation Examples: -* `kdjk_x_kdjd` returns a series that marks the cross of KDJK and KDJD -* `kdjk_xu_kdjd` returns a series that marks where KDJK crosses up KDJD -* `kdjk_xd_kdjd` returns a series that marks where KDJD crosses down KDJD - -#### [Aroon Oscillator](https://www.investopedia.com/terms/a/aroonoscillator.asp) +* `df['close_75_z']` returns the Z-Score of close price with a window of 75 -The Aroon Oscillator measures the strength of a trend and -the likelihood that it will continue. +#### [MAD - Mean Absolute Deviation](https://www.khanacademy.org/math/statistics-probability/summarizing-quantitative-data/other-measures-of-spread/a/mean-absolute-deviation-mad-review) -The default window is 25. +The mean absolute deviation of a dataset is the average +distance between each data point and the mean. It gives +us an idea about the variability in a dataset. -* Aroon Oscillator = Aroon Up - Aroon Down -* Aroon Up = 100 * (n - periods since n-period high) / n -* Aroon Down = 100 * (n - periods since n-period low) / n -* n = window size - -Examples: -* `df['aroon']` returns Aroon oscillator with a window of 25 -* `df['aroon_14']` returns Aroon oscillator with a window of 14 - -#### [Z-Score](https://www.investopedia.com/terms/z/zscore.asp) - -Z-score is a statistical measurement that describes a value's relationship to -the mean of a group of values. +Formula: +1. Calculate the mean. +2. Calculate how far away each data point is from the + mean using positive distances. These are called + absolute deviations. +3. Add those deviations together. +4. Divide the sum by the number of data points. -There is no default column name or window for Z-Score. +Example: +* `df['close_10_mad']`: the MAD of the close price in 10 periods -The statistical formula for a value's z-score is calculated using -the following formula: +#### [Pretty Good Oscillator (PGO)](https://library.tradingtechnologies.com/trade/chrt-ti-pretty-good-oscillator.html) -``` -z = ( x - μ ) / σ -``` +The Pretty Good Oscillator indicator by Mark Johnson measures the +distance of the current close from its N-day simple moving average, +expressed in terms of an average true range over a similar period. -Where: +Formula: +* PGO = (Close - SMA) / (EMA of TR) -* `z` = Z-score -* `x` = the value being evaluated -* `μ` = the mean -* `σ` = the standard deviation +Example: +* `df['pgo']` retrieves the PGO with default window 14. +* `df['pgo_10']` retrieves the PGO with window 10. -Examples: -* `df['close_75_z']` returns the Z-Score of close price with a window of 75 +--- -#### [Awesome Oscillator](https://www.ifcm.co.uk/ntx-indicators/awesome-oscillator) +### Volume -The AO indicator is a good indicator for measuring the market dynamics, -it reflects specific changes in the driving force of the market, which -helps to identify the strength of the trend, including the points of -its formation and reversal. +#### [VR - Volume Variation Index](https://help.eaglesmarkets.com/hc/en-us/articles/900002867026-Summary-of-volume-variation-index) -Awesome Oscillator Formula +It is the strength index of the trading volume. -* MEDIAN PRICE = (HIGH+LOW)/2 -* AO = SMA(MEDIAN PRICE, 5)-SMA(MEDIAN PRICE, 34) +It has a default window of 26. Change it with `set_dft_window('vr', n)`. Examples: -* `df['ao']` returns the Awesome Oscillator with default windows (5, 34) -* `df['ao_3,10']` returns the Awesome Oscillator with a window of 3 and 10 - -#### [Balance of Power](https://school.stockcharts.com/doku.php?id=technical_indicators:balance_of_power) - -Balance of Power (BOP) measures the strength of the bulls vs. bears. - -Formular: -``` -BOP = (close - open) / (high - low) -``` - -Example: -* `df['bop']` returns the Balance of Power +* `df['vr']` retrieves the 26 periods VR. +* `df['vr_6']` retrieves the 6 periods VR. -#### [Chande Momentum Oscillator] (https://www.investopedia.com/terms/c/chandemomentumoscillator.asp) +#### [MFI - Money Flow Index](https://www.investopedia.com/terms/m/mfi.asp) -The Chande Momentum Oscillator (CMO) is a technical momentum -indicator developed by Tushar Chande. +The Money Flow Index +identifies overbought or oversold signals in an asset. -The formula calculates the difference between the sum of recent -gains and the sum of recent losses and then divides the result -by the sum of all price movements over the same period. +It has a parameter for window size. The default window is 14. Change it with +`set_dft_window('mfi', n)`. -The default window is 14. +Examples: +* `df['mfi']` retrieves the 14 periods MFI +* `df['mfi_6']` retrieves the 6 periods MFI -Formular: -``` -CMO = 100 * ((sH - sL) / (sH + sL)) -``` +#### [Percentage Volume Oscillator (PVO)](https://school.stockcharts.com/doku.php?id=chart_school:technical_indicators:percentage_volume_oscillator_pvo) -where: -* sH=the sum of higher closes over N periods -* sL=the sum of lower closes of N periods +The Percentage Volume Oscillator (PVO) is a momentum oscillator for volume. +The PVO measures the difference between two volume-based moving averages as +a percentage of the larger moving average. -Examples: -* `df['cmo']` returns the CMO with a window of 14 -* `df['cmo_5']` returns the CMO with a window of 5 +Formula: -#### [Coppock Curve](https://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:coppock_curve) +* Percentage Volume Oscillator (PVO): + ((12-day EMA of Volume - 26-day EMA of Volume)/26-day EMA of Volume) x 100 +* Signal Line: 9-day EMA of PVO +* PVO Histogram: PVO - Signal Line -Coppock Curve is a momentum indicator that signals -long-term trend reversals. +Example: +* `df['pvo']` derives from the difference of 2 exponential moving average. +* `df['pvos']` is the signal line. +* `df['pvoh']` is the histogram line. -Formular: +The period of short, long EMA and signal line can be tuned with +`set_dft_window('pvo', (short, long, signal))`. The default +windows are 12 and 26 and 9. -Coppock Curve = 10-period WMA of (14-period RoC + 11-period RoC) -WMA = Weighted Moving Average -RoC = Rate-of-Change +--- -Examples: -* `df['coppock']` returns the Coppock Curve with default windows -* `df['coppock_5,10,15']` returns the Coppock Curve with WMA window 5, - fast window 10, slow window 15. +### Oscillators -#### [Ichimoku Cloud](https://www.investopedia.com/terms/i/ichimoku-cloud.asp) +#### [QQE - Quantitative Qualitative Estimation](https://www.tradingview.com/script/0vn4HZ7O-Quantitative-Qualitative-Estimation-QQE/) -The Ichimoku Cloud is a collection of technical indicators -that show support and resistance levels, as well as momentum -and trend direction. +The Qualitative Quantitative Estimation (QQE) indicator works like a smoother +version of the popular Relative Strength Index (RSI) indicator. QQE expands +on RSI by adding two volatility based trailing stop lines. These trailing +stop lines are composed of a fast and a slow moving Average True Range (ATR). +These ATR lines are smoothed making this indicator less susceptible to short +term volatility. -In this implementation, we only calculate the delta between -lead A and lead B (which is the width of the cloud). +Implementation reference: +https://github.com/twopirllc/pandas-ta/blob/main/pandas_ta/momentum/qqe.py -It contains three windows: -* window for the conversion line, default to 9 -* window for the baseline and the shifts, default to 26 -* window for the leading line, default to 52 +Example: +* `df['qqe']` retrieves the QQE with RSI window 14, MA window 5. +* `df['qqel']` retrieves the QQE long +* `df['qqes']` retrieves the QQE short +* `df['qqe_10,4']` retrieves the QQE with RSI window 10, MA window 4 +* `df['qqel_10,4']` retrieves the QQE long with customized windows. + Initialized by retrieving `df['qqe_10,4']` +* `df['qqes_10,4']` retrieves the QQE short with customized windows + Initialized by retrieving `df['qqe_10,4']` -Formular: -* conversion line = (PH9 + PL9) / 2 -* baseline = (PH26 + PL26) / 2 -* leading span A = (conversion line + baseline) / 2 -* leading span B = (PH52 + PL52) / 2 -* result = leading span A - leading span B +The period of short, long EMA and signal line can be tuned with +`set_dft_window('qqe', (rsi, rsi_ma))`. The default windows are 14 and 5. -Where: -* PH = Period High -* PL = Period Low +#### [RVGI - Relative Vigor Index](https://www.investopedia.com/terms/r/relative_vigor_index.asp) -Examples: -* `df['ichimoku']` returns the ichimoku cloud width with default windows -* `df['ichimoku_7,22,44']` returns the ichimoku cloud width with window sizes - 7, 22, 44 +The Relative Vigor Index (RVI) is a momentum indicator +used in technical analysis that measures the strength +of a trend by comparing a security's closing price to +its trading range while smoothing the results using a +simple moving average (SMA). -#### [Linear Regression Moving Average](https://www.daytrading.com/moving-linear-regression) +Formula: -Linear regression works by taking various data points in a sample and -providing a “best fit” line to match the general trend in the data. +* NUMERATOR= (a+(2xb)+(2xc)+d) / 6 +* DENOMINATOR= (e+(2xf)+(2xg)+h) / 6 +* RVI= SMA-N of DENOMINATOR / SMA-N of NUMERATOR +* Signal Line = (RVI+(2xi)+(2xj)+k) / 6 -Implementation reference: +where: -https://github.com/twopirllc/pandas-ta/blob/main/pandas_ta/overlap/linreg.py +* a=Close-Open +* b=Close-Open One Bar Prior to a +* c=Close-Open One Bar Prior to b +* d=Close-Open One Bar Prior to c +* e=High-Low of Bar a +* f=High-Low of Bar b +* g=High-Low of Bar c +* h=High-Low of Bar d +* i=RVI Value One Bar Prior +* j=RVI Value One Bar Prior to i +* k=RVI Value One Bar Prior to j +* N=Minutes/Hours/Days/Weeks/Months Examples: -* `df['close_10_lrma']` linear regression of close price with window size 10 +* `df['rvgi']` retrieves the RVGI line of window 14 +* `df['rvgis']` retrieves the RVGI signal line of window 14 +* `df['rvgi_5']` retrieves the RVGI line of window 5 +* `df['rvgis_5']` retrieves the RVGI signal line of window 5 -#### [Correlation Trend Indicator](https://tlc.thinkorswim.com/center/reference/Tech-Indicators/studies-library/C-D/CorrelationTrendIndicator) +#### [ERI - Elder-Ray Index](https://admiralmarkets.com/education/articles/forex-indicators/bears-and-bulls-power-indicator) -Correlation Trend Indicator is a study that estimates -the current direction and strength of a trend. +The Elder-Ray Index contains the bull and the bear power. +Both are calculated based on the EMA of the close price. -Implementation is based on the following code: +The default window is 13. -https://github.com/twopirllc/pandas-ta/blob/main/pandas_ta/momentum/cti.py +Formula: +* Bulls Power = High - EMA +* Bears Power = Low - EMA +* EMA is exponential moving average of close of N periods Examples: -* `df['cti']` returns the CTI of close price with window 12 -* `df['high_5_cti']` returns the CTI of high price with window 5 +* `df['eribull']` retrieves the 13 periods bull power +* `df['eribear']` retrieves the 13 periods bear power +* `df['eribull_5']` retrieves the 5 periods bull power +* `df['eribear_5']` retrieves the 5 periods bear power -#### [the Gaussian Fisher Transform Price Reversals indicator](https://www.tradingview.com/script/ajZT2tZo-Gaussian-Fisher-Transform-Price-Reversals-FTR/) +#### [FTR - Gaussian Fisher Transform Price Reversals](https://www.tradingview.com/script/ajZT2tZo-Gaussian-Fisher-Transform-Price-Reversals-FTR/) The Gaussian Fisher Transform Price Reversals indicator, dubbed FTR for short, is a stat based price reversal detection indicator inspired by and based on the work of the electrical engineer now private trader John F. Ehlers. -https://www.tradingview.com/script/ajZT2tZo-Gaussian-Fisher-Transform-Price-Reversals-FTR/ - Implementation reference: https://github.com/twopirllc/pandas-ta/blob/084dbe1c4b76082f383fa3029270ea9ac35e4dc7/pandas_ta/momentum/fisher.py#L9 -Formular: +Formula: * Fisher Transform = 0.5 * ln((1 + X) / (1 - X)) * X is a series whose values are between -1 to 1 @@ -953,160 +933,161 @@ Examples: * `df['ftr']` returns the FTR with window 9 * `df['ftr_20']` returns the FTR with window 20 -#### [Relative Vigor Index (RVGI)](https://www.investopedia.com/terms/r/relative_vigor_index.asp) - -The Relative Vigor Index (RVI) is a momentum indicator -used in technical analysis that measures the strength -of a trend by comparing a security's closing price to -its trading range while smoothing the results using a -simple moving average (SMA). +--- -Formular +### Utilities -* NUMERATOR= (a+(2×b)+(2×c)+d) / 6 -* DENOMINATOR= (e+(2×f)+(2×g)+h) / 6 -* RVI= SMA-N of DENOMINATOR / SMA-N of NUMERATOR -* Signal Line = (RVI+(2×i)+(2×j)+k) / 6 +#### Delta of Periods -where: +Using pattern `__d` to retrieve the delta between different periods. -* a=Close−Open -* b=Close−Open One Bar Prior to a -* c=Close−Open One Bar Prior to b -* d=Close−Open One Bar Prior to c -* e=High−Low of Bar a -* f=High−Low of Bar b -* g=High−Low of Bar c -* h=High−Low of Bar d -* i=RVI Value One Bar Prior -* j=RVI Value One Bar Prior to i -* k=RVI Value One Bar Prior to j -* N=Minutes/Hours/Days/Weeks/Months +You can also use `_delta` as a shortcut to `_-1_d` Examples: -* `df['rvgi']` retrieves the RVGI line of window 14 -* `df['rvgis']` retrieves the RVGI signal line of window 14 -* `df['rvgi_5']` retrieves the RVGI line of window 5 -* `df['rvgis_5']` retrieves the RVGI signal line of window 5 +* `df['close_-1_d']` retrieves the close price delta between current and prev. period. +* `df['close_delta']` is the same as `df['close_-1_d']` +* `df['high_2_d']` retrieves the high price delta between current and 2 days later -#### [Inertia Indicator](https://theforexgeek.com/inertia-indicator/) +#### Shift Periods -In financial markets, the concept of inertia was given by Donald Dorsey -in the 1995 issue of Technical Analysis of Stocks and Commodities -through the Inertia Indicator. The Inertia Indicator is moment-based -and is an extension of Dorsey’s Relative Volatility Index (RVI). +Shift the column backward or forward. It takes 2 parameters: -Formular: -* inertia = n periods linear regression of RVGI +* the name of the column to shift +* periods to shift, can be negative -Examples: -* `df['inertia']` retrieves the inertia of 20 periods linear regression of 14 periods RVGI -* `df['inertia_10']` retrieves the inertia of 10 periods linear regression of 14 periods RVGI +We fill the head and tail with the nearest data. -#### [Know Sure Thing (kst)](https://www.investopedia.com/terms/k/know-sure-thing-kst.asp) +See the example below: -The Know Sure Thing (KST) is a momentum oscillator developed by -Martin Pring to make rate-of-change readings easier for traders -to interpret. +``` python +In [15]: df[['close', 'close_-1_s', 'close_2_s']] +Out[15]: + close close_-1_s close_2_s +date +20040817 11.20 11.20 10.53 +20040818 10.29 11.20 10.55 +20040819 10.53 10.29 10.10 +20040820 10.55 10.53 10.25 +... ... ... ... +20160812 39.10 38.70 39.66 +20160815 39.58 39.10 40.45 +20160816 39.66 39.58 40.45 +20160817 40.45 39.66 40.45 -Formular: -* KST=(RCMA1×1)+(RCMA2×2) + (RCMA3×3)+(RCMA4×4) +[2813 rows x 3 columns] +``` -Where: -* RCMA1=10-period SMA of 10-period ROC -* RCMA2=10-period SMA of 15-period ROC -* RCMA3=10-period SMA of 20-period ROC -* RCMA4=15-period SMA of 30-period ROC +#### [Log Return of the Close](https://en.wikipedia.org/wiki/Rate_of_return) -Example: -* `df['kst']` retrieves the KST. +Logarithmic return = ln( close / last close) -#### [Pretty Good Oscillator (PGO)](https://library.tradingtechnologies.com/trade/chrt-ti-pretty-good-oscillator.html) +From wiki: -The Pretty Good Oscillator indicator by Mark Johnson measures the -distance of the current close from its N-day simple moving average, -expressed in terms of an average true range over a similar period. +> For example, if a stock is priced at 3.570 USD per share at the close on +> one day, and at 3.575 USD per share at the close the next day, then the +> logarithmic return is: ln(3.575/3.570) = 0.0014, or 0.14%. -Formular: -* PGO = (Close - SMA) / (EMA of TR) +Use `df['log-ret']` to access this column. -Example: -* `df['pgo']` retrieves the PGO with default window 14. -* `df['pgo_10']` retrieves the PGO with window 10. +#### Cross Upwards and Cross Downwards -#### [Psychological Line (PSL)](https://library.tradingtechnologies.com/trade/chrt-ti-psychological-line.html) +Use the pattern `_xu_` to check when A crosses up B. -The Psychological Line indicator is the ratio of the number of -rising periods over the total number of periods. +Use the pattern `_xd_` to check when A crosses down B. -Formular: -* PSL = (Number of Rising Periods) / (Total Number of Periods) * 100 +Use the pattern `_x_` to check when A crosses B. -Example: -* `df['psl']` retrieves the PSL with default window 12. -* `df['psl_10']` retrieves the PSL with window 10. -* `df['high_12_psl']` retrieves the PSL of high price with window 10. +Examples: +* `kdjk_x_kdjd` returns a series that marks the cross of KDJK and KDJD +* `kdjk_xu_kdjd` returns a series that marks where KDJK crosses up KDJD +* `kdjk_xd_kdjd` returns a series that marks where KDJD crosses down KDJD -#### [Percentage Volume Oscillator(PVO)](https://school.stockcharts.com/doku.php?id=technical_indicators:percentage_volume_oscillator_pvo) +#### Comparisons -The Percentage Volume Oscillator (PVO) is a momentum oscillator for volume. -The PVO measures the difference between two volume-based moving averages as -a percentage of the larger moving average. +Use patterns `_le_`, `_ge_`, `_lt_`, `_gt_`, +`_eq_`, `_ne_` for comparing two columns. -Formular: +#### Count of Non-Zero Value -* Percentage Volume Oscillator (PVO): - ((12-day EMA of Volume - 26-day EMA of Volume)/26-day EMA of Volume) x 100 -* Signal Line: 9-day EMA of PVO -* PVO Histogram: PVO - Signal Line +Count non-zero values of a specific range. It requires a column and a window. -Example: -* `df['pvo']` derives from the difference of 2 exponential moving average. -* `df['pvos]` is the signal line. -* `df['pvoh']` is he histogram line. +Examples: -The period of short, long EMA and signal line can be tuned with -`set_dft_window('pvo', (short, long, signal))`. The default -windows are 12 and 26 and 9. +* Count how many typical prices are larger than close in the past 10 periods -#### [Quantitative Qualitative Estimation(QQE)](https://www.tradingview.com/script/0vn4HZ7O-Quantitative-Qualitative-Estimation-QQE/) +``` python +In [22]: tp = df['middle'] -The Qualitative Quantitative Estimation (QQE) indicator works like a smoother -version of the popular Relative Strength Index (RSI) indicator. QQE expands -on RSI by adding two volatility based trailing stop lines. These trailing -stop lines are composed of a fast and a slow moving Average True Range (ATR). -These ATR lines are smoothed making this indicator less susceptible to short -term volatility. +In [23]: df['res'] = df['middle'] > df['close'] -Implementation reference: -https://github.com/twopirllc/pandas-ta/blob/main/pandas_ta/momentum/qqe.py +In [24]: df[['middle', 'close', 'res', 'res_10_c']] +Out[24]: + middle close res res_10_c +date +20040817 11.480000 11.20 True 1.0 +20040818 10.493333 10.29 True 2.0 +20040819 10.493333 10.53 False 2.0 +20040820 10.486667 10.55 False 2.0 +20040823 10.163333 10.10 True 3.0 +... ... ... ... ... +20160811 38.703333 38.70 True 5.0 +20160812 38.916667 39.10 False 5.0 +20160815 39.250000 39.58 False 4.0 +20160816 39.840000 39.66 True 5.0 +20160817 40.053333 40.45 False 5.0 + +[2813 rows x 4 columns] +``` -Example: -* `df['qqe']` retrieves the QQE with RSI window 14, MA window 5. -* `df['qqel']` retrieves the QQE long -* `df['qqes']` retrieves the QQE short -* `df['qqe_10,4']` retrieves the QQE with RSI window 10, MA window 4 -* `df['qqel_10,4']` retrieves the QQE long with customized windows. - Initialized by retrieving `df['qqe_10,4']` -* `df['qqes_10,4']` retrieves the QQE short with customized windows - Initialized by retrieving `df['qqe_10,4']` +* Count ups in the past 10 periods -The period of short, long EMA and signal line can be tuned with -`set_dft_window('qqe', (rsi, rsi_ma))`. The default windows are 14 and 5. +``` python +In [26]: df['ups'], df['downs'] = df['change'] > 0, df['change'] < 0 -## Issues +In [27]: df[['ups', 'ups_10_c', 'downs', 'downs_10_c']] +Out[27]: + ups ups_10_c downs downs_10_c +date +20040817 False 0.0 False 0.0 +20040818 False 0.0 True 1.0 +20040819 True 1.0 False 1.0 +20040820 True 2.0 False 1.0 +20040823 False 2.0 True 2.0 +... ... ... ... ... +20160811 False 3.0 True 7.0 +20160812 True 3.0 False 7.0 +20160815 True 4.0 False 6.0 +20160816 True 5.0 False 5.0 +20160817 True 5.0 False 5.0 + +[2813 rows x 4 columns] +``` -We use [Github Issues](https://github.com/jealous/stockstats/issues) to track -the issues or bugs. +#### Max and Min of the Periods + +Retrieve the max/min value of specified periods. They require column and +window. +Note the window does NOT simply stand for the rolling window. -## Others +Examples: -MACDH Note: +* `close_-3,2_max` stands for the max of 2 periods later and 3 periods ago +* `close_-2~0_min` stands for the min of 2 periods ago till now -In July 2017 the code for MACDH was changed to drop an extra 2x multiplier on -the final value to align better with calculation methods used in tools like -cryptowatch, tradingview, etc. +#### RSV - Raw Stochastic Value -## Contact author: +RSV is essential for calculating KDJ. It takes a window parameter. +Use `df['rsv']` or `df['rsv_6']` to access it. + +#### [Typical Price](https://en.wikipedia.org/wiki/Typical_price) -* Cedric Zhuang +It's the average of `high`, `low` and `close`. +Use `df['middle']` to access this value. + +When `amount` is available, `middle = amount / volume` +This should be more accurate because amount represents the total cash flow. + +## Issues + +We use [Github Issues](https://github.com/jealous/stockstats/issues) to track +the issues or bugs. diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..8ea73d17 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,42 @@ +[build-system] +requires = ["setuptools>=64", "setuptools-scm>=8"] +build-backend = "setuptools.build_meta" + +[project] +name = "stockstats" +dynamic = ["version"] +description = "DataFrame with inline stock statistics support." +readme = {file = "README.md", content-type = "text/markdown"} +license = "BSD-3-Clause" +requires-python = ">=3.9" +authors = [ + {name = "Cedric Zhuang", email = "jealous@163.com"}, +] +keywords = ["stock", "statistics", "indicator"] +classifiers = [ + "Programming Language :: Python", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: Implementation :: CPython", + "Natural Language :: English", + "Intended Audience :: Developers", + "Intended Audience :: Financial and Insurance Industry", + "Operating System :: OS Independent", + "Development Status :: 4 - Beta", + "Topic :: Utilities", +] +dependencies = [ + "numpy>=1.16.6", + "pandas>=0.24.2", +] + +[project.urls] +Homepage = "https://github.com/jealous/stockstats" + +[tool.setuptools] +py-modules = ["stockstats"] + +[tool.setuptools_scm] +version_scheme = "guess-next-dev" +local_scheme = "dirty-tag" diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 7c2b2874..00000000 --- a/setup.cfg +++ /dev/null @@ -1,2 +0,0 @@ -[bdist_wheel] -universal = 1 \ No newline at end of file diff --git a/setup.py b/setup.py deleted file mode 100644 index c29badf7..00000000 --- a/setup.py +++ /dev/null @@ -1,97 +0,0 @@ -# coding=utf-8 -# Copyright (c) 2016, Cedric Zhuang -# All rights reserved. -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# * Neither the name of disclaimer nor the names of its contributors may -# be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND ANY -# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY -# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -from setuptools import setup -import io -import re -import os - -__author__ = "Cedric Zhuang" - - -def version(): - desc = get_long_description() - ret = re.findall(r"VERSION: (.*)", desc)[0] - return ret.strip() - - -def here(filename=None): - ret = os.path.abspath(os.path.dirname(__file__)) - if filename is not None: - ret = os.path.join(ret, filename) - return ret - - -def read(*filenames, **kwargs): - encoding = kwargs.get("encoding", "utf-8") - sep = kwargs.get("sep", "\n\n") - buf = [] - for filename in filenames: - with io.open(here(filename), encoding=encoding) as f: - buf.append(f.read()) - return sep.join(buf) - - -def read_requirements(filename): - with open(filename) as f: - return f.read().splitlines() - - -def get_long_description(): - filename = "README.md" - return read(filename) - - -setup( - name="stockstats", - version=version(), - author="Cedric Zhuang", - author_email="jealous@163.com", - description="DataFrame with inline stock statistics support.", - license="BSD", - keywords="stock statistics indicator", - url="https://github.com/jealous/stockstats", - py_modules=["stockstats"], - platforms=["any"], - long_description=get_long_description(), - classifiers=[ - "Programming Language :: Python", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: Implementation :: CPython", - "Natural Language :: English", - "Intended Audience :: Developers", - "Intended Audience :: Financial and Insurance Industry", - "Operating System :: OS Independent", - "Development Status :: 4 - Beta", - "Topic :: Utilities", - "License :: OSI Approved :: BSD License", - ], - install_requires=read_requirements("requirements.txt"), - tests_require=read_requirements("test-requirements.txt"), - long_description_content_type="text/markdown", -) diff --git a/stockstats.py b/stockstats.py index df9a8fa7..1fd667f1 100644 --- a/stockstats.py +++ b/stockstats.py @@ -1444,7 +1444,10 @@ def _get_chop(self, meta: _Meta): high_low = high - low choppy = np.divide(atr_sum, high_low, out=np.zeros_like(atr_sum), where=high_low != 0) - numerator = np.log10(choppy) * 100 + numerator = np.zeros_like(choppy) + valid = choppy > 0 + np.log10(choppy, out=numerator, where=valid) + numerator *= 100 denominator = np.log10(window) self[meta.name] = self.to_series(numerator / denominator) diff --git a/test.py b/test.py index 02de2f83..1f759f9f 100644 --- a/test.py +++ b/test.py @@ -780,6 +780,26 @@ def test_chop(self): assert_that(chop_14.loc[idx], near_to(chop.loc[idx])) assert_that(chop_7.loc[idx], is_not(near_to(chop.loc[idx]))) + @staticmethod + def test_chop_flat_bars(): + import warnings + import numpy as np + data = pd.DataFrame({ + 'open': [10.0] * 20, + 'high': [10.0] * 20, + 'low': [10.0] * 20, + 'close': [10.0] * 20, + 'volume': [100] * 20, + }) + stock = wrap(data) + with warnings.catch_warnings(): + warnings.simplefilter("error", RuntimeWarning) + chop = stock["chop"] + assert_that(len(chop), equal_to(20)) + for val in chop.values: + assert_that(val, equal_to(0.0)) + assert_that(np.isfinite(val), equal_to(True)) + def test_column_conflict(self): stock = self.get_stock_90days() res = stock[["close_26_ema", "macd"]]