mirror of
https://github.com/wassname/pandas-ta.git
synced 2026-09-10 12:23:49 +08:00
@@ -124,6 +124,7 @@ reqs.txt
|
||||
requirements.txt
|
||||
driver.py
|
||||
qd.py
|
||||
tdseq.py
|
||||
|
||||
# Local package installs
|
||||
ta-lib/
|
||||
|
||||
@@ -11,10 +11,11 @@ Pandas TA - A Technical Analysis Library in Python 3
|
||||
[](https://pypi.org/project/pandas_ta/)
|
||||
[](https://pypi.org/project/pandas_ta/)
|
||||
[](https://pypistats.org/packages/pandas_ta)
|
||||
[](#contributors-)
|
||||

|
||||
|
||||
|
||||
_Pandas Technical Analysis_ (**Pandas TA**) is an easy to use library that leverages the Pandas library with more than 120 Indicators and Utility functions. Many commonly used indicators are included, such as: _Simple Moving Average_ (**sma**) _Moving Average Convergence Divergence_ (**macd**), _Hull Exponential Moving Average_ (**hma**), _Bollinger Bands_ (**bbands**), _On-Balance Volume_ (**obv**), _Aroon & Aroon Oscillator_ (**aroon**), _Squeeze_ (**squeeze**) and **_many more_**.
|
||||
_Pandas Technical Analysis_ (**Pandas TA**) is an easy to use library that leverages the Pandas library with more than 130 Indicators and Utility functions. Many commonly used indicators are included, such as: _Simple Moving Average_ (**sma**) _Moving Average Convergence Divergence_ (**macd**), _Hull Exponential Moving Average_ (**hma**), _Bollinger Bands_ (**bbands**), _On-Balance Volume_ (**obv**), _Aroon & Aroon Oscillator_ (**aroon**), _Squeeze_ (**squeeze**) and **_many more_**.
|
||||
|
||||
<br/>
|
||||
|
||||
@@ -33,16 +34,18 @@ _Pandas Technical Analysis_ (**Pandas TA**) is an easy to use library that lever
|
||||
* [Pandas TA Strategies](#pandas-ta-strategies)
|
||||
* [Types of Strategies](#types-of-strategies)
|
||||
* [DataFrame Properties](#dataframe-properties)
|
||||
* [DataFrame Methods](#dataframe-methods)
|
||||
* [Indicators by Category](#indicators-by-category)
|
||||
* [Candles](#candles-3)
|
||||
* [Momentum](#momentum-35)
|
||||
* [Overlap](#overlap-29)
|
||||
* [Cycles](#cycles-1)
|
||||
* [Momentum](#momentum-37)
|
||||
* [Overlap](#overlap-31)
|
||||
* [Performance](#performance-4)
|
||||
* [Statistics](#statistics-9)
|
||||
* [Trend](#trend-15)
|
||||
* [Utility](#utility-5)
|
||||
* [Volatility](#volatility-13)
|
||||
* [Volume](#volume-13)
|
||||
* [Volume](#volume-14)
|
||||
* [Performance Metrics](#performance-metrics)
|
||||
* [Changes](#changes)
|
||||
* [General](#general)
|
||||
@@ -59,13 +62,14 @@ _Pandas Technical Analysis_ (**Pandas TA**) is an easy to use library that lever
|
||||
|
||||
# **Features**
|
||||
|
||||
* Has 120+ indicators and utility functions.
|
||||
* Has 130+ indicators and utility functions.
|
||||
* Indicators are tightly correlated with the de facto [TA Lib](https://mrjbq7.github.io/ta-lib/) if they share common indicators.
|
||||
* Have the need for speed? By using the DataFrame _strategy_ method, you get **multiprocessing** for free!
|
||||
* Easily add _prefixes_ or _suffixes_ or both to columns names. Useful for Custom Chained Strategies.
|
||||
* Example Jupyter Notebooks under the [examples](https://github.com/twopirllc/pandas-ta/tree/master/examples) directory, including how to create Custom Strategies using the new [__Strategy__ Class](https://github.com/twopirllc/pandas-ta/tree/master/examples/PandaTA_Strategy_Examples.ipynb)
|
||||
* Potential Data Leaks: **ichimoku** and **dpo**. See indicator list below for details.
|
||||
* **UNDER DEVELOPMENT:** Performance Metrics
|
||||
* **UNDER DEVELOPMENT:** Easy Downloading of _ohlcv_ data using [yfinance](https://github.com/ranaroussi/yfinance). See ```help(ta.ticker)``` and ```help(ta.yf)```
|
||||
|
||||
<br/>
|
||||
|
||||
@@ -74,14 +78,14 @@ _Pandas Technical Analysis_ (**Pandas TA**) is an easy to use library that lever
|
||||
|
||||
Stable
|
||||
------
|
||||
The ```pip``` version is the last most stable release.
|
||||
The ```pip``` version is the last most stable release. Version: *0.2.45b*
|
||||
```sh
|
||||
$ pip install pandas_ta
|
||||
```
|
||||
|
||||
Latest Version
|
||||
--------------
|
||||
Best choice!
|
||||
Best choice! Version: *0.2.62b*
|
||||
```sh
|
||||
$ pip install -U git+https://github.com/twopirllc/pandas-ta
|
||||
```
|
||||
@@ -100,8 +104,12 @@ $ pip install -U git+https://github.com/twopirllc/pandas-ta.git@development
|
||||
import pandas as pd
|
||||
import pandas_ta as ta
|
||||
|
||||
df = pd.DataFrame() # Empty DataFrame
|
||||
|
||||
# Load data
|
||||
df = pd.read_csv("path/to/symbol.csv", sep=",")
|
||||
# OR if you have yfinance installed
|
||||
df = df.ta.ticker("aapl")
|
||||
|
||||
# VWAP requires the DataFrame index to be a DatetimeIndex.
|
||||
# Replace "datetime" with the appropriate column from your DataFrame
|
||||
@@ -136,8 +144,8 @@ help(df.ta)
|
||||
# List of all indicators
|
||||
df.ta.indicators()
|
||||
|
||||
# Help about the log_return indicator
|
||||
help(ta.log_return)
|
||||
# Help about an indicator such as bbands
|
||||
help(ta.bbands)
|
||||
```
|
||||
<br/>
|
||||
|
||||
@@ -175,7 +183,7 @@ Thanks for using **Pandas TA**!
|
||||
|
||||
_Thank you for your contributions!_
|
||||
|
||||
[alexonab](https://github.com/alexonab) | [allahyarzadeh](https://github.com/allahyarzadeh) | [codesutras](https://github.com/codesutras) | [daikts](https://github.com/daikts) | [DrPaprikaa](https://github.com/DrPaprikaa) | [FGU1](https://github.com/FGU1) | [lluissalord](https://github.com/lluissalord) | [maxdignan](https://github.com/maxdignan) | [NkosenhleDuma](https://github.com/NkosenhleDuma) | [pbrumblay](https://github.com/pbrumblay) | [RajeshDhalange](https://github.com/RajeshDhalange) | [rengel8](https://github.com/rengel8) | [rluong003](https://github.com/rluong003) | [SoftDevDanial](https://github.com/SoftDevDanial) | [tg12](https://github.com/tg12) | [twrobel](https://github.com/twrobel) | [whubsch](https://github.com/whubsch) | [YuvalWein](https://github.com/YuvalWein)
|
||||
[alexonab](https://github.com/alexonab) | [allahyarzadeh](https://github.com/allahyarzadeh) | [codesutras](https://github.com/codesutras) | [DrPaprikaa](https://github.com/DrPaprikaa) | [daikts](https://github.com/daikts) | [dorren](https://github.com/dorren) | [edwardwang1](https://github.com/edwardwang1) | [ffhirata](https://github.com/ffhirata) | [FGU1](https://github.com/FGU1) | [lluissalord](https://github.com/lluissalord) | [M6stafa](https://github.com/M6stafa) | [maxdignan](https://github.com/maxdignan) | [moritzgun](https://github.com/moritzgun) | [NkosenhleDuma](https://github.com/NkosenhleDuma) | [pbrumblay](https://github.com/pbrumblay) | [RajeshDhalange](https://github.com/RajeshDhalange) | [rengel8](https://github.com/rengel8) | [rluong003](https://github.com/rluong003) | [SoftDevDanial](https://github.com/SoftDevDanial) | [tg12](https://github.com/tg12) | [twrobel](https://github.com/twrobel) | [whubsch](https://github.com/whubsch) | [witokondoria](https://github.com/witokondoria) | [wouldayajustlookatit](https://github.com/wouldayajustlookatit) | [YuvalWein](https://github.com/YuvalWein)
|
||||
|
||||
<br/>
|
||||
|
||||
@@ -341,6 +349,7 @@ df.ta.strategy(verbose=True)
|
||||
df.ta.strategy(timed=True)
|
||||
|
||||
# Choose the number of cores to use. Default is all available cores.
|
||||
# For no multiprocessing, set this value to 0.
|
||||
df.ta.cores = 4
|
||||
|
||||
# Maybe you do not want certain indicators.
|
||||
@@ -405,6 +414,9 @@ df.ta.categories
|
||||
# Defaults to the number of cpus you have.
|
||||
df.ta.cores = 4
|
||||
|
||||
# Set the number of cores to 0 for no multiprocessing.
|
||||
df.ta.cores = 0
|
||||
|
||||
# Returns the number of cores you set or your default number of cpus.
|
||||
df.ta.cores
|
||||
```
|
||||
@@ -418,6 +430,24 @@ df.ta.cores
|
||||
df.ta.datetime_ordered
|
||||
```
|
||||
|
||||
## **exchange**
|
||||
|
||||
```python
|
||||
# Sets the Exchange to use when calculating the last_run property. Default: "NYSE"
|
||||
df.ta.exchange
|
||||
|
||||
# Set the Exchange to use.
|
||||
# Available Exchanges: "ASX", "BMF", "DIFX", "FWB", "HKE", "JSE", "LSE", "NSE", "NYSE", "NZSX", "RTS", "SGX", "SSE", "TSE", "TSX"
|
||||
df.ta.exchange = "LSE"
|
||||
```
|
||||
|
||||
## **last_run**
|
||||
|
||||
```python
|
||||
# Returns the time Pandas TA was last run as a string.
|
||||
df.ta.last_run
|
||||
```
|
||||
|
||||
## **reverse**
|
||||
|
||||
```python
|
||||
@@ -442,6 +472,85 @@ bothhl2 = df.ta.hl2(prefix="pre", suffix="post")
|
||||
print(bothhl2.name) # "pre_HL2_post"
|
||||
```
|
||||
|
||||
## **time_range**
|
||||
|
||||
```python
|
||||
# Returns the time range of the DataFrame as a float.
|
||||
# By default, it returns the time in "years"
|
||||
df.ta.time_range
|
||||
|
||||
# Available time_ranges include: "years", "months", "weeks", "days", "hours", "minutes". "seconds"
|
||||
df.ta.time_range = "days"
|
||||
df.ta.time_range # prints DataFrame time in "days" as float
|
||||
```
|
||||
|
||||
## **to_utc**
|
||||
|
||||
```python
|
||||
# Sets the DataFrame index to UTC format.
|
||||
df.ta.to_utc
|
||||
```
|
||||
|
||||
<br/><br/>
|
||||
|
||||
|
||||
# **DataFrame Methods**
|
||||
|
||||
## **constants**
|
||||
|
||||
```python
|
||||
import numpy as np
|
||||
|
||||
# Add constant '1' to the DataFrame
|
||||
df.ta.constants(True, [1])
|
||||
# Remove constant '1' to the DataFrame
|
||||
df.ta.constants(False, [1])
|
||||
|
||||
# Adding constants for charting
|
||||
import numpy as np
|
||||
chart_lines = np.append(np.arange(-4, 5, 1), np.arange(-100, 110, 10))
|
||||
df.ta.constants(True, chart_lines)
|
||||
# Removing some constants from the DataFrame
|
||||
df.ta.constants(False, np.array([-60, -40, 40, 60]))
|
||||
```
|
||||
|
||||
## **indicators**
|
||||
|
||||
```python
|
||||
# Prints the indicators and utility functions
|
||||
df.ta.indicators()
|
||||
|
||||
# Returns a list of indicators and utility functions
|
||||
ind_list = df.ta.indicators(as_list=True)
|
||||
|
||||
# Prints the indicators and utility functions that are not in the excluded list
|
||||
df.ta.indicators(exclude=["cg", "pgo", "ui"])
|
||||
# Returns a list of the indicators and utility functions that are not in the excluded list
|
||||
smaller_list = df.ta.indicators(exclude=["cg", "pgo", "ui"], as_list=True)
|
||||
```
|
||||
|
||||
## **ticker**
|
||||
|
||||
```python
|
||||
# Download Chart history using yfinance. (pip install yfinance) https://github.com/ranaroussi/yfinance
|
||||
# It uses the same keyword arguments as yfinance (excluding start and end)
|
||||
df = df.ta.ticker("aapl") # Default ticker is "SPY"
|
||||
|
||||
# Period is used instead of start/end
|
||||
# Valid periods: 1d,5d,1mo,3mo,6mo,1y,2y,5y,10y,ytd,max
|
||||
# Default: "max"
|
||||
df = df.ta.ticker("aapl", period="1y") # Gets this past year
|
||||
|
||||
# History by Interval by interval (including intraday if period < 60 days)
|
||||
# Valid intervals: 1m,2m,5m,15m,30m,60m,90m,1h,1d,5d,1wk,1mo,3mo
|
||||
# Default: "1d"
|
||||
df = df.ta.ticker("aapl", period="1y", interval="1wk") # Gets this past year in weeks
|
||||
df = df.ta.ticker("aapl", period="1mo", interval="1h") # Gets this past month in hours
|
||||
|
||||
# BUT WAIT!! THERE'S MORE!!
|
||||
help(ta.yf)
|
||||
```
|
||||
|
||||
<br/><br/>
|
||||
|
||||
# **Indicators** (_by Category_)
|
||||
@@ -450,8 +559,15 @@ print(bothhl2.name) # "pre_HL2_post"
|
||||
* _Doji_: **cdl_doji**
|
||||
* _Inside Bar_: **cdl_inside**
|
||||
* _Heikin-Ashi_: **ha**
|
||||
<br/>
|
||||
|
||||
### **Momentum** (36)
|
||||
|
||||
### **Cycles** (1)
|
||||
|
||||
* _Even Better Sinewave_: **ebsw**
|
||||
<br/>
|
||||
|
||||
### **Momentum** (37)
|
||||
|
||||
* _Awesome Oscillator_: **ao**
|
||||
* _Absolute Price Oscillator_: **apo**
|
||||
@@ -486,6 +602,8 @@ print(bothhl2.name) # "pre_HL2_post"
|
||||
* Default is John Carter's. Enable Lazybear's with ```lazybear=True```
|
||||
* _Stochastic Oscillator_: **stoch**
|
||||
* _Stochastic RSI_: **stochrsi**
|
||||
* _TD Sequential_: **td_seq**
|
||||
* Excluded from ```df.ta.strategy()```.
|
||||
* _Trix_: **trix**
|
||||
* _True strength index_: **tsi**
|
||||
* _Ultimate Oscillator_: **uo**
|
||||
@@ -495,9 +613,11 @@ print(bothhl2.name) # "pre_HL2_post"
|
||||
| _Moving Average Convergence Divergence_ (MACD) |
|
||||
|:--------:|
|
||||
|  |
|
||||
<br/>
|
||||
|
||||
### **Overlap** (30)
|
||||
### **Overlap** (31)
|
||||
|
||||
* _Arnaud Legoux Moving Average_: **alma**
|
||||
* _Double Exponential Moving Average_: **dema**
|
||||
* _Exponential Moving Average_: **ema**
|
||||
* _Fibonacci's Weighted Moving Average_: **fwma**
|
||||
@@ -506,6 +626,7 @@ print(bothhl2.name) # "pre_HL2_post"
|
||||
* _High-Low-Close Average_: **hlc3**
|
||||
* Commonly known as 'Typical Price' in Technical Analysis literature
|
||||
* _Hull Exponential Moving Average_: **hma**
|
||||
* _Holt-Winter Moving Average_: **hwma**
|
||||
* _Ichimoku Kinkō Hyō_: **ichimoku**
|
||||
* Use: help(ta.ichimoku). Returns two DataFrames.
|
||||
* Drop the Chikou Span Column, the final column of the first resultant DataFrame, remove potential data leak.
|
||||
@@ -536,6 +657,7 @@ print(bothhl2.name) # "pre_HL2_post"
|
||||
| _Simple Moving Averages_ (SMA) and _Bollinger Bands_ (BBANDS) |
|
||||
|:--------:|
|
||||
|  |
|
||||
<br/>
|
||||
|
||||
|
||||
### **Performance** (4)
|
||||
@@ -550,7 +672,7 @@ Use parameter: cumulative=**True** for cumulative results.
|
||||
| _Percent Return_ (Cumulative) with _Simple Moving Average_ (SMA) |
|
||||
|:--------:|
|
||||
|  |
|
||||
|
||||
<br/>
|
||||
|
||||
### **Statistics** (9)
|
||||
|
||||
@@ -567,10 +689,12 @@ Use parameter: cumulative=**True** for cumulative results.
|
||||
| _Z Score_ |
|
||||
|:--------:|
|
||||
|  |
|
||||
<br/>
|
||||
|
||||
### **Trend** (15)
|
||||
|
||||
* _Average Directional Movement Index_: **adx**
|
||||
* Also includes **dmp** and **dmn** in the resultant DataFrame.
|
||||
* _Archer Moving Averages Trends_: **amat**
|
||||
* _Aroon & Aroon Oscillator_: **aroon**
|
||||
* _Choppiness Index_: **chop**
|
||||
@@ -643,7 +767,7 @@ Use parameter: cumulative=**True** for cumulative results.
|
||||
|
||||
<br/><br/>
|
||||
|
||||
# **Performance Metrics** (BETA)
|
||||
# **Performance Metrics** _BETA_
|
||||
_Performance Metrics_ are a **new** addition to the package and consequentially are likely unreliable. **Use at your own risk.** These metrics return a _float_ and are _not_ part of the _DataFrame_ Extension. They are called the Standard way. For Example:
|
||||
|
||||
```python
|
||||
@@ -673,31 +797,21 @@ result = ta.cagr(df.close)
|
||||
* **Moving Average Choices**: dema, ema, fwma, hma, linreg, midpoint, pwma, rma, sinwma, sma, swma, t3, tema, trima, vidya, wma, zlma.
|
||||
* An _experimental_ and independent __Watchlist__ Class located in the [Examples](https://github.com/twopirllc/pandas-ta/tree/master/examples/watchlist.py) Directory that can be used in conjunction with the new __Strategy__ Class.
|
||||
* _Linear Regression_ (**linear_regression**) is a new utility method for Simple Linear Regression using _Numpy_ or _Scikit Learn_'s implementation.
|
||||
* Added utility/convience function, ```to_utc```, to convert the DataFrame index to UTC. See: ```help(ta.to_utc)```
|
||||
* Added utility/convience function, ```to_utc```, to convert the DataFrame index to UTC. See: ```help(ta.to_utc)``` **Now** as a Pandas TA DataFrame Property to easily convert the DataFrame index to UTC.
|
||||
|
||||
<br />
|
||||
|
||||
## **Breaking Indicators**
|
||||
* _Bollinger Bands_ (**bbands**): New column 'bandwidth' appended to the returning DataFrame. See: ```help(ta.bbands)```
|
||||
* _Volume Weighted Average Price_ (**vwap**): **Requires** the DataFrame index to be a DatetimeIndex.
|
||||
|
||||
|
||||
## **New Indicators**
|
||||
* _Drawdown_ (**drawdown**) shows the peak-to-trough decline during a specific period for an investment,
|
||||
* _Arnaud Legoux Moving Average_ (**alma**) uses the curve of the Normal (Gauss) distribution to allow regulating the smoothness and high sensitivity of the indicator. See: ```help(ta.alma)```
|
||||
trading account, or fund. See: ```help(ta.drawdown)```
|
||||
* _Gann High-Low Activator_ (**hilo**) was created by Robert Krausz in a 1998. See: ```help(ta.hilo)```
|
||||
* _McGinley Dynamic_ (**mcgd**) is an overlap indicator developed by John R. McGinley, a Certified Market Technician. See: ```help(ta.mcgd)```
|
||||
* _Price Volume Rank_ (**pvr**) was created by Anthony J. Macek. See: ```help(ta.pvr)```
|
||||
* _Quantitative Qualitative Estimation_ (**qqe**) is like SuperTrend for a Smoothed RSI. See: ```help(ta.qqe)```
|
||||
article in the June, 1994 issue of Technical Analysis of Stocks & Commodities Magazine. See: ```help(ta.pvr)```
|
||||
* _Relative Strength Xtra_ (**rsx**) is based on the popular RSI indicator and inspired by the work Jurik Research. See: ```help(ta.rsx)```
|
||||
* _Ehler's Super Smoother Filter_ (**ssf**). Ehler's solution to reduce lag and remove aliasing noise compared to other common moving average indicators. See: ```help(ta.ssf)```
|
||||
* _Elder's Thermometer_ (**thermo**) measures price volatility. See: ```help(ta.thermo)```
|
||||
* _TTM Trend_ (**ttm_trend**) is a trend indicator inspired from John Carter's book "Mastering the Trade" issue of Stocks & Commodities Magazine. It is a moving average based trend indicator consisting of two different simple moving averages. See: ```help(ta.ttm_trend)```
|
||||
* _Variable Index Dynamic Average_ (**vidya**) is a popular Dynamic Moving Average created by Tushar Chande. See: ```help(ta.vidya)```
|
||||
* _Even Better Sinewave_ (**ebsw**) measures market cycles and uses a low pass filter to remove noise. See: ```help(ta.ebsw)```
|
||||
* _Tom DeMark's Sequential_ (**td_seq**) attempts to identify a price point where an uptrend or a downtrend exhausts itself and reverses. Currently exlcuded from ```df.ta.strategy()``` for performance reasons. See: ```help(ta.td_seq)```
|
||||
<br/>
|
||||
|
||||
## **Updated Indicators**
|
||||
* _ADX_ (**adx**): Added ```mamode``` with default "**RMA**" and with the same ```mamode``` options as TradingView. See ```help(ta.adx)```.
|
||||
* _Average True Range_ (**atr**): The default ```mamode``` is now "**RMA**" and with the same ```mamode``` options as TradingView. See ```help(ta.atr)```.
|
||||
* _Bollinger Bands_ (**bbands**): New argument ```ddoff``` to control the Degrees of Freedom. Default is 0. See ```help(ta.bbands)```.
|
||||
* _Decreasing_ (**decreasing**): New argument ```strict``` checks if the series is continuously decreasing over period ```length```. Default: ```False```. See ```help(ta.decreasing)```.
|
||||
* _Increasing_ (**increasing**): New argument ```strict``` checks if the series is continuously increasing over period ```length```. Default: ```False```. See ```help(ta.increasing)```.
|
||||
* _Trend Return_ (**trend_return**): Returns a DataFrame now instead of Series with pertinenet trade info for a _trend_. An example can be found in the [AI Example Notebook](https://github.com/twopirllc/pandas-ta/tree/master/examples/AIExample.ipynb). The notebook is still a work in progress and open to colloboration.
|
||||
@@ -706,8 +820,4 @@ article in the June, 1994 issue of Technical Analysis of Stocks & Commodities Ma
|
||||
<br />
|
||||
|
||||
# **Sources**
|
||||
* [Original TA-LIB](http://ta-lib.org/)
|
||||
* [TradingView](http://www.tradingview.com)
|
||||
* [Sierra Chart](https://search.sierrachart.com/?Query=indicators&submitted=true)
|
||||
* [FM Labs](https://www.fmlabs.com/reference/default.htm)
|
||||
* [User 42](https://user42.tuxfamily.org/chart/manual/index.html)
|
||||
[Original TA-LIB](http://ta-lib.org/) | [TradingView](http://www.tradingview.com) | [Sierra Chart](https://search.sierrachart.com/?Query=indicators&submitted=true) | [MQL5](https://www.mql5.com) | [FM Labs](https://www.fmlabs.com/reference/default.htm) | [Pro Real Code](https://www.prorealcode.com/prorealtime-indicators) | [User 42](https://user42.tuxfamily.org/chart/manual/index.html)
|
||||
+331
-282
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+132
-156
File diff suppressed because one or more lines are too long
+56
-52
@@ -3,11 +3,13 @@ import datetime as dt
|
||||
|
||||
from pathlib import Path
|
||||
from random import random
|
||||
from typing import Tuple
|
||||
|
||||
import pandas as pd # pip install pandas
|
||||
from pandas_datareader import data as pdr
|
||||
import yfinance as yf
|
||||
|
||||
# yf.pdr_override() # <== that's all it takes :-)
|
||||
yf.pdr_override() # <== that's all it takes :-)
|
||||
|
||||
from numpy import arange as npArange
|
||||
from numpy import append as npAppend
|
||||
@@ -72,14 +74,9 @@ class Watchlist(object):
|
||||
- tickers: A list of strings containing tickers. Example: ["SPY", "AAPL"]
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
tickers: list,
|
||||
tf: str = None,
|
||||
name: str = None,
|
||||
strategy: ta.Strategy = None,
|
||||
ds: object = None,
|
||||
**kwargs,
|
||||
def __init__(self,
|
||||
tickers: list, tf: str = None, name: str = None,
|
||||
strategy: ta.Strategy = None, ds_name: str = "av", **kwargs,
|
||||
):
|
||||
self.verbose = kwargs.pop("verbose", False)
|
||||
self.debug = kwargs.pop("debug", False)
|
||||
@@ -92,24 +89,25 @@ class Watchlist(object):
|
||||
self.kwargs = kwargs
|
||||
self.strategy = strategy
|
||||
|
||||
self._init_data_source(ds)
|
||||
self._init_data_source(ds_name)
|
||||
|
||||
def _init_data_source(self, ds: object):
|
||||
if ds is not None:
|
||||
self.ds = ds
|
||||
elif isinstance(ds, str) and ds.lower() == "yahoo":
|
||||
|
||||
def _init_data_source(self, ds: str) -> None:
|
||||
self.ds_name = ds.lower() if isinstance(ds, str) else "av"
|
||||
|
||||
# Default: AlphaVantage
|
||||
AVkwargs = {"api_key": "YOUR API KEY", "clean": True, "export": True, "output_size": "full", "premium": False}
|
||||
self.av_kwargs = self.kwargs.pop("av_kwargs", AVkwargs)
|
||||
self.ds = AV.AlphaVantage(**self.av_kwargs)
|
||||
self.file_path = self.ds.export_path
|
||||
|
||||
if self.ds_name == "yahoo":
|
||||
self.ds = yf
|
||||
else:
|
||||
AVkwargs = {"api_key": "YOUR API KEY", "clean": True, "export": True, "output_size": "full", "premium": False}
|
||||
self.av_kwargs = self.kwargs.pop("av_kwargs", AVkwargs)
|
||||
self.ds = AV.AlphaVantage(**self.av_kwargs)
|
||||
self.file_path = self.ds.export_path
|
||||
|
||||
def _drop_columns(
|
||||
self,
|
||||
df: pd.DataFrame,
|
||||
cols: list = ["Unnamed: 0", "date", "split_coefficient", "dividend"],
|
||||
):
|
||||
def _drop_columns(self, df: pd.DataFrame, cols: list = None) -> pd.DataFrame:
|
||||
if cols is None or not isinstance(cols, list):
|
||||
cols = ["Unnamed: 0", "date", "split_coefficient", "dividend"]
|
||||
else: cols
|
||||
"""Helper methods to drop columns silently."""
|
||||
df_columns = list(df.columns)
|
||||
if any(_ in df_columns for _ in cols):
|
||||
@@ -123,12 +121,10 @@ class Watchlist(object):
|
||||
keyed by ticker."""
|
||||
if (self.tickers is not None and isinstance(self.tickers, list) and
|
||||
len(self.tickers)):
|
||||
self.data = {
|
||||
ticker: self.load(ticker, **kwargs) for ticker in self.tickers
|
||||
}
|
||||
self.data = {ticker: self.load(ticker, **kwargs) for ticker in self.tickers}
|
||||
return self.data
|
||||
|
||||
def _plot(self, df, mas:bool = True, constants:bool = True, **kwargs) -> None:
|
||||
def _plot(self, df, mas:bool = True, constants:bool = False, **kwargs) -> None:
|
||||
|
||||
if constants:
|
||||
chart_lines = npAppend(npArange(-5, 6, 1), npArange(-100, 110, 10))
|
||||
@@ -145,22 +141,25 @@ class Watchlist(object):
|
||||
_grid = kwargs.pop("grid", True)
|
||||
_alpha = kwargs.pop("alpha", 1)
|
||||
_last = kwargs.pop("last", 252)
|
||||
_title = kwargs.pop("title", f"{df.ticker} {_time}")
|
||||
_title = kwargs.pop("title", f"{df.ticker} {_time} [{self.ds_name}]")
|
||||
|
||||
col = kwargs.pop("close", "close")
|
||||
price = df[[col, "SMA_10", "SMA_20", "SMA_50", "SMA_200"]] if mas else df[col]
|
||||
if mas:
|
||||
# df.ta.strategy(self.strategy, append=True)
|
||||
price = df[[col, "SMA_10", "SMA_20", "SMA_50", "SMA_200"]]
|
||||
else:
|
||||
price = df[col]
|
||||
|
||||
price.tail(_last).plot(figsize=_figsize, color=_colors, linewidth=2, title=_title, grid=_grid, alpha=_alpha)
|
||||
if _kind is None:
|
||||
price.tail(_last).plot(figsize=_figsize, color=_colors, linewidth=2, title=_title, grid=_grid, alpha=_alpha)
|
||||
else:
|
||||
print(f"[X] Plot kind not implemented")
|
||||
return
|
||||
|
||||
|
||||
def load(
|
||||
self,
|
||||
ticker: str = None,
|
||||
tf: str = None,
|
||||
index: str = "date",
|
||||
drop: list = [],
|
||||
plot: bool = False,
|
||||
**kwargs
|
||||
def load(self,
|
||||
ticker: str = None, tf: str = None, index: str = "date",
|
||||
drop: list = [], plot: bool = False, **kwargs
|
||||
) -> pd.DataFrame:
|
||||
"""Loads or Downloads (if a local csv does not exist) the data from the
|
||||
Data Source. When successful, it returns a Data Frame for the requested
|
||||
@@ -179,22 +178,28 @@ class Watchlist(object):
|
||||
|
||||
# Load local or from Data Source
|
||||
if current_file.exists():
|
||||
df = pd.read_csv(current_file, index_col=index)
|
||||
if not df.ta.datetime_ordered:
|
||||
df = df.set_index(pd.DatetimeIndex(df.index))
|
||||
print(f"[i] Loaded['{tf}']: {filename_}")
|
||||
file_loaded = f"[i] Loaded {ticker}[{tf}]: {filename_}"
|
||||
# if self.ds_name == "av":
|
||||
if self.ds_name in ["av", "yahoo"]:
|
||||
df = pd.read_csv(current_file, index_col=0)
|
||||
if not df.ta.datetime_ordered:
|
||||
df = df.set_index(pd.DatetimeIndex(df.index))
|
||||
print(file_loaded)
|
||||
else:
|
||||
print(f"[X] {filename_} not found in {Path(self.file_path)}")
|
||||
return
|
||||
else:
|
||||
print(f"[+] Downloading['{tf}']: {ticker}")
|
||||
if isinstance(self.ds, AV.AlphaVantage):
|
||||
print(f"[+] Downloading[{self.ds_name}]: {ticker}[{tf}]")
|
||||
if self.ds_name == "av":
|
||||
df = self.ds.data(ticker, tf)
|
||||
if not df.ta.datetime_ordered:
|
||||
df = df.set_index(pd.DatetimeIndex(df[index]))
|
||||
elif isinstance(self.ds, yfinance):
|
||||
print("[!] In Development")
|
||||
if self.ds_name == "yahoo":
|
||||
yf_data = self.ds.Ticker(ticker)
|
||||
df = yf_data.history(period="max")
|
||||
print(yf_data.info)
|
||||
print(df)
|
||||
to_save = f"{self.file_path}/{ticker}_{tf}.csv"
|
||||
print(f"[+] Saving: {to_save}")
|
||||
df.to_csv(to_save)
|
||||
|
||||
# Remove select columns
|
||||
df = self._drop_columns(df, drop)
|
||||
@@ -207,7 +212,6 @@ class Watchlist(object):
|
||||
df.tf = tf
|
||||
|
||||
if plot: self._plot(df, **kwargs)
|
||||
|
||||
return df
|
||||
|
||||
@property
|
||||
@@ -273,7 +277,7 @@ class Watchlist(object):
|
||||
return self._tickers
|
||||
|
||||
@tickers.setter
|
||||
def tickers(self, value: (list, str)) -> None:
|
||||
def tickers(self, value: Tuple[list, str]) -> None:
|
||||
if value is None:
|
||||
print(f"[X] {value} is not a value in Watchlist ticker.")
|
||||
return
|
||||
@@ -300,7 +304,7 @@ class Watchlist(object):
|
||||
pd.DataFrame().ta.indicators(*args, **kwargs)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
s = f"Watch(name='{self.name}', tickers[{len(self.tickers)}]='{', '.join(self.tickers)}', tf='{self.tf}', strategy[{self.strategy.total_ta()}]='{self.strategy.name}'"
|
||||
s = f"Watch(name='{self.name}', ds_name='{self.ds_name}', tickers[{len(self.tickers)}]='{', '.join(self.tickers)}', tf='{self.tf}', strategy[{self.strategy.total_ta()}]='{self.strategy.name}'"
|
||||
if self.data is not None:
|
||||
s += f", data[{len(self.data.keys())}])"
|
||||
return s
|
||||
|
||||
@@ -25,9 +25,10 @@ Imports = {
|
||||
"scipy": find_spec("scipy") is not None,
|
||||
"sklearn": find_spec("sklearn") is not None,
|
||||
"statsmodels": find_spec("statsmodels") is not None,
|
||||
"stochastic": find_spec("stochastic") is not None,
|
||||
"matplotlib": find_spec("matplotlib") is not None,
|
||||
"mplfinance": find_spec("mplfinance") is not None,
|
||||
"alphaVantage-api ": find_spec("alphaVantageAPI") is not None,
|
||||
"alphaVantage-api": find_spec("alphaVantageAPI") is not None,
|
||||
"yfinance": find_spec("yfinance") is not None,
|
||||
"talib": find_spec("talib") is not None,
|
||||
}
|
||||
@@ -39,17 +40,19 @@ Category = {
|
||||
"candles": [
|
||||
"cdl_doji", "cdl_inside", "ha"
|
||||
],
|
||||
# Cycles
|
||||
"cycles": ["ebsw"],
|
||||
# Momentum
|
||||
"momentum": [
|
||||
"ao", "apo", "bias", "bop", "brar", "cci", "cfo", "cg", "cmo",
|
||||
"coppock", "er", "eri", "fisher", "inertia", "kdj", "kst", "macd",
|
||||
"mom", "pgo", "ppo", "psl", "pvo", "qqe", "roc", "rsi", "rsx", "rvgi",
|
||||
"slope", "smi", "squeeze", "stoch", "stochrsi", "trix", "tsi", "uo",
|
||||
"slope", "smi", "squeeze", "stoch", "stochrsi", "td_seq", "trix", "tsi", "uo",
|
||||
"willr"
|
||||
],
|
||||
# Overlap
|
||||
"overlap": [
|
||||
"dema", "ema", "fwma", "hilo", "hl2", "hlc3", "hma", "ichimoku",
|
||||
"alma", "dema", "ema", "fwma", "hilo", "hl2", "hlc3", "hma", "ichimoku",
|
||||
"kama", "linreg", "mcgd", "midpoint", "midprice", "ohlc4", "pwma", "rma",
|
||||
"sinwma", "sma", "ssf", "supertrend", "swma", "t3", "tema", "trima",
|
||||
"vidya", "vwap", "vwma", "wcp", "wma", "zlma"
|
||||
@@ -69,7 +72,7 @@ Category = {
|
||||
],
|
||||
# Volatility
|
||||
"volatility": [
|
||||
"aberration", "accbands", "atr", "bbands", "donchian", "kc", "massi",
|
||||
"aberration", "accbands", "atr", "bbands", "donchian", "hwc", "kc", "massi",
|
||||
"natr", "pdist", "rvi", "thermo", "true_range", "ui"
|
||||
],
|
||||
|
||||
|
||||
@@ -1,22 +1,24 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from pandas_ta.overlap import sma
|
||||
from pandas_ta.utils import get_offset, high_low_range, is_percent
|
||||
from pandas_ta.utils import non_zero_range, real_body, verify_series
|
||||
from pandas_ta.utils import real_body, verify_series
|
||||
|
||||
|
||||
def cdl_doji( open_, high, low, close, length=None, factor=None, scalar=None, asint=True, offset=None, **kwargs):
|
||||
def cdl_doji(open_, high, low, close, length=None, factor=None, scalar=None, asint=True, offset=None, **kwargs):
|
||||
"""Candle Type: Doji"""
|
||||
# Validate Arguments
|
||||
open_ = verify_series(open_)
|
||||
high = verify_series(high)
|
||||
low = verify_series(low)
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 10
|
||||
factor = float(factor) if is_percent(factor) else 10
|
||||
scalar = float(scalar) if scalar else 100
|
||||
open_ = verify_series(open_, length)
|
||||
high = verify_series(high, length)
|
||||
low = verify_series(low, length)
|
||||
close = verify_series(close, length)
|
||||
offset = get_offset(offset)
|
||||
naive = kwargs.pop("naive", False)
|
||||
|
||||
if open_ is None or high is None or low is None or close is None: return
|
||||
|
||||
# Calculate Result
|
||||
body = real_body(open_, close).abs()
|
||||
hl_range = high_low_range(high, low).abs()
|
||||
@@ -77,7 +79,8 @@ Args:
|
||||
|
||||
Kwargs:
|
||||
naive (bool, optional): If True, prefills potential Doji less than
|
||||
the length if less than a percentage of it's high-low range. Default: False
|
||||
the length if less than a percentage of it's high-low range.
|
||||
Default: False
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
fill_method (value, optional): Type of fill method
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from pandas import DataFrame, set_option
|
||||
from pandas_ta.utils import candle_color, get_drift, get_offset
|
||||
from pandas_ta.utils import non_zero_range, real_body, verify_series
|
||||
from pandas_ta.utils import candle_color, get_offset
|
||||
from pandas_ta.utils import verify_series
|
||||
|
||||
|
||||
def cdl_inside(open_, high, low, close, asbool=False, offset=None, **kwargs):
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import numpy as np
|
||||
from pandas import DataFrame
|
||||
from pandas_ta.utils import get_offset, verify_series
|
||||
|
||||
|
||||
+281
-191
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from .ebsw import ebsw
|
||||
@@ -0,0 +1,115 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from numpy import cos as npCos
|
||||
from numpy import exp as npExp
|
||||
from numpy import NaN as npNaN
|
||||
from numpy import pi as npPi
|
||||
from numpy import sin as npSin
|
||||
from numpy import sqrt as npSqrt
|
||||
from pandas import Series
|
||||
from pandas_ta.utils import get_offset, verify_series
|
||||
|
||||
|
||||
def ebsw(close, length=None, bars=None, offset=None, **kwargs):
|
||||
"""Indicator: Even Better SineWave (EBSW)"""
|
||||
# Validate arguments
|
||||
length = int(length) if length and length > 38 else 40
|
||||
bars = int(bars) if bars and bars > 0 else 10
|
||||
close = verify_series(close, length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# variables
|
||||
alpha1 = HP = 0 # alpha and HighPass
|
||||
a1 = b1 = c1 = c2 = c3 = 0
|
||||
Filt = Pwr = Wave = 0
|
||||
|
||||
lastClose = lastHP = 0
|
||||
FilterHist = [0, 0] # Filter history
|
||||
|
||||
# Calculate Result
|
||||
m = close.size
|
||||
result = [npNaN for _ in range(0, length - 1)] + [0]
|
||||
for i in range(length, m):
|
||||
# HighPass filter cyclic components whose periods are shorter than Duration input
|
||||
alpha1 = (1 - npSin(360 / length)) / npCos(360 / length)
|
||||
HP = 0.5 * (1 + alpha1) * (close[i] - lastClose) + alpha1 * lastHP
|
||||
|
||||
# Smooth with a Super Smoother Filter from equation 3-3
|
||||
a1 = npExp(-npSqrt(2) * npPi / bars)
|
||||
b1 = 2 * a1 * npCos(npSqrt(2) * 180 / bars)
|
||||
c2 = b1
|
||||
c3 = -1 * a1 * a1
|
||||
c1 = 1 - c2 - c3
|
||||
Filt = c1 * (HP + lastHP) / 2 + c2 * FilterHist[1] + c3 * FilterHist[0]
|
||||
# Filt = float("{:.8f}".format(float(Filt))) # to fix for small scientific notations, the big ones fail
|
||||
|
||||
# 3 Bar average of Wave amplitude and power
|
||||
Wave = (Filt + FilterHist[1] + FilterHist[0]) / 3
|
||||
Pwr = (Filt * Filt + FilterHist[1] * FilterHist[1] + FilterHist[0] * FilterHist[0]) / 3
|
||||
|
||||
# Normalize the Average Wave to Square Root of the Average Power
|
||||
Wave = Wave / npSqrt(Pwr)
|
||||
|
||||
# update storage, result
|
||||
FilterHist.append(Filt) # append new Filt value
|
||||
FilterHist.pop(0) # remove first element of list (left) -> updating/trim
|
||||
lastHP = HP
|
||||
lastClose = close[i]
|
||||
result.append(Wave)
|
||||
|
||||
ebsw = Series(result, index=close.index)
|
||||
|
||||
# Offset
|
||||
if offset != 0:
|
||||
ebsw = ebsw.shift(offset)
|
||||
|
||||
# Handle fills
|
||||
if "fillna" in kwargs:
|
||||
ebsw.fillna(kwargs["fillna"], inplace=True)
|
||||
if "fill_method" in kwargs:
|
||||
ebsw.fillna(method=kwargs["fill_method"], inplace=True)
|
||||
|
||||
# Name and Categorize it
|
||||
ebsw.name = f"EBSW_{length}_{bars}"
|
||||
ebsw.category = "cycles"
|
||||
|
||||
return ebsw
|
||||
|
||||
|
||||
ebsw.__doc__ = \
|
||||
"""Even Better SineWave (EBSW) *beta*
|
||||
|
||||
This indicator measures market cycles and uses a low pass filter to remove noise.
|
||||
Its output is bound signal between -1 and 1 and the maximum length of a detected
|
||||
trend is limited by its length input.
|
||||
|
||||
Written by rengel8 for Pandas TA based on a publication at 'prorealcode.com' and
|
||||
a book by J.F.Ehlers.
|
||||
|
||||
* This implementation seems to be logically limited. It would make sense to
|
||||
implement exactly the version from prorealcode and compare the behaviour.
|
||||
|
||||
|
||||
Sources:
|
||||
https://www.prorealcode.com/prorealtime-indicators/even-better-sinewave/
|
||||
J.F.Ehlers 'Cycle Analytics for Traders', 2014
|
||||
|
||||
Calculation:
|
||||
refer to 'sources' or implementation
|
||||
|
||||
Args:
|
||||
close (pd.Series): Series of 'close's
|
||||
length (int): It's max cycle/trend period. Values between 40-48 work like
|
||||
expected with minimum value: 39. Default: 40.
|
||||
bars (int): Period of low pass filtering. Default: 10
|
||||
drift (int): The difference period. Default: 1
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
fill_method (value, optional): Type of fill method
|
||||
|
||||
Returns:
|
||||
pd.Series: New feature generated.
|
||||
"""
|
||||
@@ -31,6 +31,7 @@ from .smi import smi
|
||||
from .squeeze import squeeze
|
||||
from .stoch import stoch
|
||||
from .stochrsi import stochrsi
|
||||
from .td_seq import td_seq
|
||||
from .trix import trix
|
||||
from .tsi import tsi
|
||||
from .uo import uo
|
||||
|
||||
@@ -6,14 +6,17 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def ao(high, low, fast=None, slow=None, offset=None, **kwargs):
|
||||
"""Indicator: Awesome Oscillator (AO)"""
|
||||
# Validate Arguments
|
||||
high = verify_series(high)
|
||||
low = verify_series(low)
|
||||
fast = int(fast) if fast and fast > 0 else 5
|
||||
slow = int(slow) if slow and slow > 0 else 34
|
||||
if slow < fast:
|
||||
fast, slow = slow, fast
|
||||
_length = max(fast, slow)
|
||||
high = verify_series(high, _length)
|
||||
low = verify_series(low, _length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if high is None or low is None: return
|
||||
|
||||
# Calculate Result
|
||||
median_price = 0.5 * (high + low)
|
||||
fast_sma = sma(median_price, fast)
|
||||
@@ -57,9 +60,9 @@ Calculation:
|
||||
Args:
|
||||
high (pd.Series): Series of 'high's
|
||||
low (pd.Series): Series of 'low's
|
||||
fast (int): The short period. Default: 5
|
||||
slow (int): The long period. Default: 34
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
fast (int): The short period. Default: 5
|
||||
slow (int): The long period. Default: 34
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
@@ -6,13 +6,15 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def apo(close, fast=None, slow=None, offset=None, **kwargs):
|
||||
"""Indicator: Absolute Price Oscillator (APO)"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
fast = int(fast) if fast and fast > 0 else 12
|
||||
slow = int(slow) if slow and slow > 0 else 26
|
||||
if slow < fast:
|
||||
fast, slow = slow, fast
|
||||
close = verify_series(close, max(fast, slow))
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
fastma = sma(close, length=fast)
|
||||
slowma = sma(close, length=slow)
|
||||
@@ -40,7 +42,7 @@ apo.__doc__ = \
|
||||
|
||||
The Absolute Price Oscillator is an indicator used to measure a security's
|
||||
momentum. It is simply the difference of two Exponential Moving Averages
|
||||
(EMA) of two different periods. Note: APO and MACD lines are equivalent.
|
||||
(EMA) of two different periods. Note: APO and MACD lines are equivalent.
|
||||
|
||||
Sources:
|
||||
https://www.tradingtechnologies.com/xtrader-help/x-study/technical-indicator-definitions/absolute-price-oscillator-apo/
|
||||
@@ -53,9 +55,9 @@ Calculation:
|
||||
|
||||
Args:
|
||||
close (pd.Series): Series of 'close's
|
||||
fast (int): The short period. Default: 12
|
||||
slow (int): The long period. Default: 26
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
fast (int): The short period. Default: 12
|
||||
slow (int): The long period. Default: 26
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
@@ -6,11 +6,13 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def bias(close, length=None, mamode=None, offset=None, **kwargs):
|
||||
"""Indicator: Bias (BIAS)"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 26
|
||||
mamode = mamode if isinstance(mamode, str) else "sma"
|
||||
close = verify_series(close, length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
bma = ma(mamode, close, length=length, **kwargs)
|
||||
bias = (close / bma) - 1
|
||||
@@ -50,10 +52,10 @@ Calculation:
|
||||
|
||||
Args:
|
||||
close (pd.Series): Series of 'close's
|
||||
length (int): The period. Default: 26
|
||||
mamode (str): Options: 'ema', 'hma', 'rma', 'sma', 'wma'. Default: 'sma'
|
||||
drift (int): The short period. Default: 1
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
length (int): The period. Default: 26
|
||||
mamode (str): Options: 'ema', 'hma', 'rma', 'sma', 'wma'. Default: 'sma'
|
||||
drift (int): The short period. Default: 1
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
@@ -6,17 +6,19 @@ from pandas_ta.utils import get_drift, get_offset, non_zero_range, verify_series
|
||||
def brar(open_, high, low, close, length=None, scalar=None, drift=None, offset=None, **kwargs):
|
||||
"""Indicator: BRAR (BRAR)"""
|
||||
# Validate Arguments
|
||||
open_ = verify_series(open_)
|
||||
high = verify_series(high)
|
||||
low = verify_series(low)
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 26
|
||||
scalar = float(scalar) if scalar else 100
|
||||
high_open_range = non_zero_range(high, open_)
|
||||
open_low_range = non_zero_range(open_, low)
|
||||
open_ = verify_series(open_, length)
|
||||
high = verify_series(high, length)
|
||||
low = verify_series(low, length)
|
||||
close = verify_series(close, length)
|
||||
drift = get_drift(drift)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if open_ is None or high is None or low is None or close is None: return
|
||||
|
||||
# Calculate Result
|
||||
hcy = non_zero_range(high, close.shift(drift))
|
||||
cyl = non_zero_range(close.shift(drift), low)
|
||||
@@ -85,10 +87,10 @@ Args:
|
||||
high (pd.Series): Series of 'high's
|
||||
low (pd.Series): Series of 'low's
|
||||
close (pd.Series): Series of 'close's
|
||||
length (int): The period. Default: 26
|
||||
scalar (float): How much to magnify. Default: 100
|
||||
drift (int): The difference period. Default: 1
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
length (int): The period. Default: 26
|
||||
scalar (float): How much to magnify. Default: 100
|
||||
drift (int): The difference period. Default: 1
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
@@ -7,13 +7,15 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def cci(high, low, close, length=None, c=None, offset=None, **kwargs):
|
||||
"""Indicator: Commodity Channel Index (CCI)"""
|
||||
# Validate Arguments
|
||||
high = verify_series(high)
|
||||
low = verify_series(low)
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 14
|
||||
c = float(c) if c and c > 0 else 0.015
|
||||
high = verify_series(high, length)
|
||||
low = verify_series(low, length)
|
||||
close = verify_series(close, length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if high is None or low is None or close is None: return
|
||||
|
||||
# Calculate Result
|
||||
typical_price = hlc3(high=high, low=low, close=close)
|
||||
mean_typical_price = sma(typical_price, length=length)
|
||||
@@ -62,9 +64,9 @@ Args:
|
||||
high (pd.Series): Series of 'high's
|
||||
low (pd.Series): Series of 'low's
|
||||
close (pd.Series): Series of 'close's
|
||||
length (int): It's period. Default: 14
|
||||
c (float): Scaling Constant. Default: 0.015
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
length (int): It's period. Default: 14
|
||||
c (float): Scaling Constant. Default: 0.015
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
@@ -6,12 +6,14 @@ from pandas_ta.utils import get_drift, get_offset, verify_series
|
||||
def cfo(close, length=None, scalar=None, drift=None, offset=None, **kwargs):
|
||||
"""Indicator: Chande Forcast Oscillator (CFO)"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 9
|
||||
scalar = float(scalar) if scalar else 100
|
||||
close = verify_series(close, length)
|
||||
drift = get_drift(drift)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Finding linear regression of Series
|
||||
cfo = scalar * (close - linreg(close, length=length, tsf=True))
|
||||
cfo /= close
|
||||
|
||||
@@ -5,10 +5,12 @@ from pandas_ta.utils import get_offset, verify_series, weights
|
||||
def cg(close, length=None, offset=None, **kwargs):
|
||||
"""Indicator: Center of Gravity (CG)"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 10
|
||||
close = verify_series(close, length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
coefficients = [length - i for i in range(0, length)]
|
||||
numerator = -close.rolling(length).apply(weights(coefficients), raw=True)
|
||||
@@ -46,8 +48,8 @@ Calculation:
|
||||
|
||||
Args:
|
||||
close (pd.Series): Series of 'close's
|
||||
length (int): The length of the period. Default: 10
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
length (int): The length of the period. Default: 10
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
@@ -6,18 +6,20 @@ from pandas_ta.utils import get_drift, get_offset, verify_series
|
||||
def cmo(close, length=None, scalar=None, drift=None, offset=None, **kwargs):
|
||||
"""Indicator: Chande Momentum Oscillator (CMO)"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 14
|
||||
scalar = float(scalar) if scalar else 100
|
||||
talib = kwargs.pop("talib", True)
|
||||
close = verify_series(close, length)
|
||||
drift = get_drift(drift)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
mom = close.diff(drift)
|
||||
positive = mom.copy().clip(lower=0)
|
||||
negative = mom.copy().clip(upper=0).abs()
|
||||
|
||||
talib = kwargs.pop("talib", True)
|
||||
if talib:
|
||||
pos_ = rma(positive, length)
|
||||
neg_ = rma(negative, length)
|
||||
|
||||
@@ -7,12 +7,14 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def coppock(close, length=None, fast=None, slow=None, offset=None, **kwargs):
|
||||
"""Indicator: Coppock Curve (COPC)"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 10
|
||||
fast = int(fast) if fast and fast > 0 else 11
|
||||
slow = int(slow) if slow and slow > 0 else 14
|
||||
close = verify_series(close, max(length, fast, slow))
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
total_roc = roc(close, fast) + roc(close, slow)
|
||||
coppock = wma(total_roc, length)
|
||||
@@ -58,10 +60,10 @@ Calculation:
|
||||
|
||||
Args:
|
||||
close (pd.Series): Series of 'close's
|
||||
length (int): WMA period. Default: 10
|
||||
fast (int): Fast ROC period. Default: 11
|
||||
slow (int): Slow ROC period. Default: 14
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
length (int): WMA period. Default: 10
|
||||
fast (int): Fast ROC period. Default: 11
|
||||
slow (int): Slow ROC period. Default: 14
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
@@ -6,11 +6,13 @@ from pandas_ta.utils import get_drift, get_offset, verify_series, signals
|
||||
def er(close, length=None, drift=None, offset=None, **kwargs):
|
||||
"""Indicator: Efficiency Ratio (ER)"""
|
||||
# Validate arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 10
|
||||
close = verify_series(close, length)
|
||||
offset = get_offset(offset)
|
||||
drift = get_drift(drift)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
abs_diff = close.diff(length).abs()
|
||||
abs_volatility = close.diff(drift).abs()
|
||||
@@ -79,8 +81,8 @@ Calculation:
|
||||
|
||||
Args:
|
||||
close (pd.Series): Series of 'close's
|
||||
length (int): It's period. Default: 1
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
length (int): It's period. Default: 1
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
@@ -7,12 +7,14 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def eri(high, low, close, length=None, offset=None, **kwargs):
|
||||
"""Indicator: Elder Ray Index (ERI)"""
|
||||
# Validate arguments
|
||||
high = verify_series(high)
|
||||
low = verify_series(low)
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 13
|
||||
high = verify_series(high, length)
|
||||
low = verify_series(low, length)
|
||||
close = verify_series(close, length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if high is None or low is None or close is None: return
|
||||
|
||||
# Calculate Result
|
||||
ema_ = ema(close, length)
|
||||
bull = high - ema_
|
||||
@@ -73,8 +75,8 @@ Args:
|
||||
high (pd.Series): Series of 'high's
|
||||
low (pd.Series): Series of 'low's
|
||||
close (pd.Series): Series of 'close's
|
||||
length (int): It's period. Default: 14
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
length (int): It's period. Default: 14
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
@@ -9,12 +9,15 @@ from pandas_ta.utils import get_offset, high_low_range, verify_series, zero
|
||||
def fisher(high, low, length=None, signal=None, offset=None, **kwargs):
|
||||
"""Indicator: Fisher Transform (FISHT)"""
|
||||
# Validate Arguments
|
||||
high = verify_series(high)
|
||||
low = verify_series(low)
|
||||
length = int(length) if length and length > 0 else 9
|
||||
signal = int(signal) if signal and signal > 0 else 1
|
||||
_length = max(length, signal)
|
||||
high = verify_series(high, _length)
|
||||
low = verify_series(low, _length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if high is None or low is None: return
|
||||
|
||||
# Calculate Result
|
||||
hl2_ = hl2(high, low)
|
||||
highest_hl2 = hl2_.rolling(length).max()
|
||||
@@ -29,7 +32,7 @@ def fisher(high, low, length=None, signal=None, offset=None, **kwargs):
|
||||
m = high.size
|
||||
result = [npNaN for _ in range(0, length - 1)] + [0]
|
||||
for i in range(length, m):
|
||||
v = 0.66 * position[i] + 0.67 * v
|
||||
v = 0.66 * position.iloc[i] + 0.67 * v
|
||||
if v < -0.99:
|
||||
v = -0.999
|
||||
if v > 0.99:
|
||||
@@ -102,9 +105,9 @@ Calculation:
|
||||
Args:
|
||||
high (pd.Series): Series of 'high's
|
||||
low (pd.Series): Series of 'low's
|
||||
length (int): Fisher period. Default: 9
|
||||
signal (int): Fisher Signal period. Default: 1
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
length (int): Fisher period. Default: 9
|
||||
signal (int): Fisher Signal period. Default: 1
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
@@ -1,25 +1,29 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from pandas_ta.overlap import linreg
|
||||
from pandas_ta.volatility import rvi
|
||||
from pandas_ta.utils import get_drift, get_offset, non_zero_range, verify_series
|
||||
from pandas_ta.utils import get_drift, get_offset, verify_series
|
||||
|
||||
|
||||
def inertia(close=None, high=None, low=None, length=None, rvi_length=None, scalar=None, refined=None, thirds=None, mamode=None, drift=None, offset=None, **kwargs):
|
||||
"""Indicator: Inertia (INERTIA)"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 20
|
||||
rvi_length = int(rvi_length) if rvi_length and rvi_length > 0 else 14
|
||||
scalar = float(scalar) if scalar and scalar > 0 else 100
|
||||
refined = False if refined is None else True
|
||||
thirds = False if thirds is None else True
|
||||
mamode = mamode if isinstance(mamode, str) else "ema"
|
||||
_length = max(length, rvi_length)
|
||||
close = verify_series(close, _length)
|
||||
drift = get_drift(drift)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
if refined or thirds:
|
||||
high = verify_series(high)
|
||||
low = verify_series(low)
|
||||
high = verify_series(high, _length)
|
||||
low = verify_series(low, _length)
|
||||
if high is None or low is None: return
|
||||
|
||||
# Calculate Result
|
||||
if refined:
|
||||
@@ -75,10 +79,10 @@ Args:
|
||||
high (pd.Series): Series of 'high's
|
||||
low (pd.Series): Series of 'low's
|
||||
close (pd.Series): Series of 'close's
|
||||
length (int): It's period. Default: 20
|
||||
rvi_length (int): RVI period. Default: 14
|
||||
drift (int): The difference period. Default: 1
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
length (int): It's period. Default: 20
|
||||
rvi_length (int): RVI period. Default: 14
|
||||
drift (int): The difference period. Default: 1
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
@@ -7,13 +7,16 @@ from pandas_ta.utils import get_offset, non_zero_range, verify_series
|
||||
def kdj(high=None, low=None, close=None, length=None, signal=None, offset=None, **kwargs):
|
||||
"""Indicator: KDJ (KDJ)"""
|
||||
# Validate Arguments
|
||||
high = verify_series(high)
|
||||
low = verify_series(low)
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 9
|
||||
signal = int(signal) if signal and signal > 0 else 3
|
||||
_length = max(length, signal)
|
||||
high = verify_series(high, _length)
|
||||
low = verify_series(low, _length)
|
||||
close = verify_series(close, _length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if high is None or low is None or close is None: return
|
||||
|
||||
# Calculate Result
|
||||
highest_high = high.rolling(length).max()
|
||||
lowest_low = low.rolling(length).min()
|
||||
@@ -86,7 +89,7 @@ Args:
|
||||
close (pd.Series): Series of 'close's
|
||||
length (int): Default: 9
|
||||
signal (int): Default: 3
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
+15
-12
@@ -7,7 +7,6 @@ from pandas_ta.utils import get_drift, get_offset, verify_series
|
||||
def kst(close, roc1=None, roc2=None, roc3=None, roc4=None, sma1=None, sma2=None, sma3=None, sma4=None, signal=None, drift=None, offset=None, **kwargs):
|
||||
"""Indicator: 'Know Sure Thing' (KST)"""
|
||||
# Validate arguments
|
||||
close = verify_series(close)
|
||||
roc1 = int(roc1) if roc1 and roc1 > 0 else 10
|
||||
roc2 = int(roc2) if roc2 and roc2 > 0 else 15
|
||||
roc3 = int(roc3) if roc3 and roc3 > 0 else 20
|
||||
@@ -19,9 +18,13 @@ def kst(close, roc1=None, roc2=None, roc3=None, roc4=None, sma1=None, sma2=None,
|
||||
sma4 = int(sma4) if sma4 and sma4 > 0 else 15
|
||||
|
||||
signal = int(signal) if signal and signal > 0 else 9
|
||||
_length = max(roc1, roc2, roc3, roc4, sma1, sma2, sma3, sma4, signal)
|
||||
close = verify_series(close, _length)
|
||||
drift = get_drift(drift)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
rocma1 = roc(close, roc1).rolling(sma1).mean()
|
||||
rocma2 = roc(close, roc2).rolling(sma2).mean()
|
||||
@@ -83,17 +86,17 @@ Calculation:
|
||||
|
||||
Args:
|
||||
close (pd.Series): Series of 'close's
|
||||
roc1 (int): ROC 1 period. Default: 10
|
||||
roc2 (int): ROC 2 period. Default: 15
|
||||
roc3 (int): ROC 3 period. Default: 20
|
||||
roc4 (int): ROC 4 period. Default: 30
|
||||
sma1 (int): SMA 1 period. Default: 10
|
||||
sma2 (int): SMA 2 period. Default: 10
|
||||
sma3 (int): SMA 3 period. Default: 10
|
||||
sma4 (int): SMA 4 period. Default: 15
|
||||
signal (int): It's period. Default: 9
|
||||
drift (int): The difference period. Default: 1
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
roc1 (int): ROC 1 period. Default: 10
|
||||
roc2 (int): ROC 2 period. Default: 15
|
||||
roc3 (int): ROC 3 period. Default: 20
|
||||
roc4 (int): ROC 4 period. Default: 30
|
||||
sma1 (int): SMA 1 period. Default: 10
|
||||
sma2 (int): SMA 2 period. Default: 10
|
||||
sma3 (int): SMA 3 period. Default: 10
|
||||
sma4 (int): SMA 4 period. Default: 15
|
||||
signal (int): It's period. Default: 9
|
||||
drift (int): The difference period. Default: 1
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from pandas import DataFrame, concat
|
||||
from pandas import concat, DataFrame
|
||||
from pandas_ta.overlap import ema
|
||||
from pandas_ta.utils import get_offset, verify_series, signals
|
||||
|
||||
@@ -7,14 +7,16 @@ from pandas_ta.utils import get_offset, verify_series, signals
|
||||
def macd(close, fast=None, slow=None, signal=None, offset=None, **kwargs):
|
||||
"""Indicator: Moving Average, Convergence/Divergence (MACD)"""
|
||||
# Validate arguments
|
||||
close = verify_series(close)
|
||||
fast = int(fast) if fast and fast > 0 else 12
|
||||
slow = int(slow) if slow and slow > 0 else 26
|
||||
signal = int(signal) if signal and signal > 0 else 9
|
||||
if slow < fast:
|
||||
fast, slow = slow, fast
|
||||
close = verify_series(close, max(fast, slow, signal))
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
fastma = ema(close, length=fast)
|
||||
slowma = ema(close, length=slow)
|
||||
@@ -93,7 +95,7 @@ macd.__doc__ = \
|
||||
|
||||
The MACD is a popular indicator to that is used to identify a security's trend.
|
||||
While APO and MACD are the same calculation, MACD also returns two more series
|
||||
called Signal and Histogram. The Signal is an EMA of MACD and the Histogram is
|
||||
called Signal and Histogram. The Signal is an EMA of MACD and the Histogram is
|
||||
the difference of MACD and Signal.
|
||||
|
||||
Sources:
|
||||
@@ -109,10 +111,10 @@ Calculation:
|
||||
|
||||
Args:
|
||||
close (pd.Series): Series of 'close's
|
||||
fast (int): The short period. Default: 12
|
||||
slow (int): The long period. Default: 26
|
||||
signal (int): The signal period. Default: 9
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
fast (int): The short period. Default: 12
|
||||
slow (int): The long period. Default: 26
|
||||
signal (int): The signal period. Default: 9
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
@@ -5,10 +5,12 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def mom(close, length=None, offset=None, **kwargs):
|
||||
"""Indicator: Momentum (MOM)"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 10
|
||||
close = verify_series(close, length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
mom = close.diff(length)
|
||||
|
||||
@@ -45,8 +47,8 @@ Calculation:
|
||||
|
||||
Args:
|
||||
close (pd.Series): Series of 'close's
|
||||
length (int): It's period. Default: 1
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
length (int): It's period. Default: 1
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
@@ -7,12 +7,14 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def pgo(high, low, close, length=None, offset=None, **kwargs):
|
||||
"""Indicator: Pretty Good Oscillator (PGO)"""
|
||||
# Validate arguments
|
||||
high = verify_series(high)
|
||||
low = verify_series(low)
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 14
|
||||
high = verify_series(high, length)
|
||||
low = verify_series(low, length)
|
||||
close = verify_series(close, length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if high is None or low is None or close is None: return
|
||||
|
||||
# Calculate Result
|
||||
pgo = close - sma(close, length)
|
||||
pgo /= ema(atr(high, low, close, length), length)
|
||||
@@ -57,8 +59,8 @@ Args:
|
||||
high (pd.Series): Series of 'high's
|
||||
low (pd.Series): Series of 'low's
|
||||
close (pd.Series): Series of 'close's
|
||||
length (int): It's period. Default: 14
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
length (int): It's period. Default: 14
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
@@ -7,15 +7,17 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def ppo(close, fast=None, slow=None, signal=None, scalar=None, offset=None, **kwargs):
|
||||
"""Indicator: Percentage Price Oscillator (PPO)"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
fast = int(fast) if fast and fast > 0 else 12
|
||||
slow = int(slow) if slow and slow > 0 else 26
|
||||
signal = int(signal) if signal and signal > 0 else 9
|
||||
scalar = float(scalar) if scalar else 100
|
||||
if slow < fast:
|
||||
fast, slow = slow, fast
|
||||
close = verify_series(close, max(fast, slow, signal))
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
fastma = sma(close, length=fast)
|
||||
slowma = sma(close, length=slow)
|
||||
@@ -78,11 +80,11 @@ Calculation:
|
||||
|
||||
Args:
|
||||
close(pandas.Series): Series of 'close's
|
||||
fast(int): The short period. Default: 12
|
||||
slow(int): The long period. Default: 26
|
||||
signal(int): The signal period. Default: 9
|
||||
scalar (float): How much to magnify. Default: 100
|
||||
offset(int): How many periods to offset the result. Default: 0
|
||||
fast(int): The short period. Default: 12
|
||||
slow(int): The long period. Default: 26
|
||||
signal(int): The signal period. Default: 9
|
||||
scalar (float): How much to magnify. Default: 100
|
||||
offset(int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
@@ -6,12 +6,14 @@ from pandas_ta.utils import get_drift, get_offset, verify_series
|
||||
def psl(close, open_=None, length=None, scalar=None, drift=None, offset=None, **kwargs):
|
||||
"""Indicator: Psychological Line (PSL)"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 12
|
||||
scalar = float(scalar) if scalar and scalar > 0 else 100
|
||||
close = verify_series(close, length)
|
||||
drift = get_drift(drift)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
if open_ is not None:
|
||||
open_ = verify_series(open_)
|
||||
@@ -71,10 +73,10 @@ Calculation:
|
||||
Args:
|
||||
close (pd.Series): Series of 'close's
|
||||
open_ (pd.Series, optional): Series of 'open's
|
||||
length (int): It's period. Default: 12
|
||||
scalar (float): How much to magnify. Default: 100
|
||||
drift (int): The difference period. Default: 1
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
length (int): It's period. Default: 12
|
||||
scalar (float): How much to magnify. Default: 100
|
||||
drift (int): The difference period. Default: 1
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
@@ -7,15 +7,17 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def pvo(volume, fast=None, slow=None, signal=None, scalar=None, offset=None, **kwargs):
|
||||
"""Indicator: Percentage Volume Oscillator (PVO)"""
|
||||
# Validate Arguments
|
||||
volume = verify_series(volume)
|
||||
fast = int(fast) if fast and fast > 0 else 12
|
||||
slow = int(slow) if slow and slow > 0 else 26
|
||||
signal = int(signal) if signal and signal > 0 else 9
|
||||
scalar = float(scalar) if scalar else 100
|
||||
if slow < fast:
|
||||
fast, slow = slow, fast
|
||||
volume = verify_series(volume, max(fast, slow, signal))
|
||||
offset = get_offset(offset)
|
||||
|
||||
if volume is None: return
|
||||
|
||||
# Calculate Result
|
||||
fastma = ema(volume, length=fast)
|
||||
slowma = ema(volume, length=slow)
|
||||
@@ -76,11 +78,11 @@ Calculation:
|
||||
|
||||
Args:
|
||||
volume (pd.Series): Series of 'volume's
|
||||
fast (int): The short period. Default: 12
|
||||
slow (int): The long period. Default: 26
|
||||
signal (int): The signal period. Default: 9
|
||||
scalar (float): How much to magnify. Default: 100
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
fast (int): The short period. Default: 12
|
||||
slow (int): The long period. Default: 26
|
||||
signal (int): The signal period. Default: 9
|
||||
scalar (float): How much to magnify. Default: 100
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
@@ -12,14 +12,17 @@ from pandas_ta.utils import get_drift, get_offset, verify_series
|
||||
def qqe(close, length=None, smooth=None, factor=None, mamode=None, drift=None, offset=None, **kwargs):
|
||||
"""Indicator: Quantitative Qualitative Estimation (QQE)"""
|
||||
# Validate arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 14
|
||||
smooth = int(smooth) if smooth and smooth > 0 else 5
|
||||
factor = float(factor) if factor else 4.236
|
||||
wilders_length = 2 * length - 1
|
||||
mamode = mamode if isinstance(mamode, str) else "ema"
|
||||
close = verify_series(close, max(length, smooth, wilders_length))
|
||||
drift = get_drift(drift)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
rsi_ = rsi(close, length)
|
||||
_mode = mamode.lower()[0] if mamode != "ema" else ""
|
||||
@@ -30,7 +33,6 @@ def qqe(close, length=None, smooth=None, factor=None, mamode=None, drift=None, o
|
||||
|
||||
# Double Smooth the RSI MA True Range using Wilder's Length with a default
|
||||
# width of 4.236.
|
||||
wilders_length = 2 * length - 1
|
||||
smoothed_rsi_tr_ma = ma("ema", rsi_ma_tr, length=wilders_length)
|
||||
dar = factor * ma("ema", smoothed_rsi_tr_ma, length=wilders_length)
|
||||
|
||||
@@ -131,7 +133,6 @@ Sources:
|
||||
https://www.tradingview.com/script/IYfA9R2k-QQE-MT4/
|
||||
https://www.tradingpedia.com/forex-trading-indicators/quantitative-qualitative-estimation
|
||||
https://www.prorealcode.com/prorealtime-indicators/qqe-quantitative-qualitative-estimation/
|
||||
|
||||
|
||||
Calculation:
|
||||
Default Inputs:
|
||||
@@ -142,7 +143,8 @@ Args:
|
||||
length (int): RSI period. Default: 14
|
||||
smooth (int): RSI smoothing period. Default: 5
|
||||
factor (float): QQE Factor. Default: 4.236
|
||||
mamode (str): Smoothing MA type: "ema", "hma", "rma", "sma" or "wma". Default: "ema"
|
||||
mamode (str): Smoothing MA type: "ema", "hma", "rma", "sma" or "wma".
|
||||
Default: "ema"
|
||||
drift (int): The difference period. Default: 1
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
|
||||
@@ -6,10 +6,12 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def roc(close, length=None, offset=None, **kwargs):
|
||||
"""Indicator: Rate of Change (ROC)"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 10
|
||||
close = verify_series(close, length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
roc = 100 * mom(close=close, length=length) / close.shift(length)
|
||||
|
||||
@@ -48,8 +50,8 @@ Calculation:
|
||||
|
||||
Args:
|
||||
close (pd.Series): Series of 'close's
|
||||
length (int): It's period. Default: 1
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
length (int): It's period. Default: 1
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
@@ -7,12 +7,14 @@ from pandas_ta.utils import get_drift, get_offset, verify_series, signals
|
||||
def rsi(close, length=None, scalar=None, drift=None, offset=None, **kwargs):
|
||||
"""Indicator: Relative Strength Index (RSI)"""
|
||||
# Validate arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 14
|
||||
scalar = float(scalar) if scalar else 100
|
||||
close = verify_series(close, length)
|
||||
drift = get_drift(drift)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
negative = close.diff(drift)
|
||||
positive = negative.copy()
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from numpy import NaN as npNaN
|
||||
from pandas import DataFrame, Series, concat
|
||||
from pandas import concat, DataFrame, Series
|
||||
from pandas_ta.utils import get_drift, get_offset, verify_series, signals
|
||||
|
||||
|
||||
def rsx(close, length=None, drift=None, offset=None, **kwargs):
|
||||
"""Indicator: Relative Strength Xtra (inspired by Jurik RSX)"""
|
||||
# Validate arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 14
|
||||
close = verify_series(close, length)
|
||||
drift = get_drift(drift)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# variables
|
||||
vC, v1C = 0, 0
|
||||
v4, v8, v10, v14, v18, v20 = 0, 0, 0, 0, 0, 0
|
||||
@@ -30,7 +33,7 @@ def rsx(close, length=None, drift=None, offset=None, **kwargs):
|
||||
f88 = length - 1.0
|
||||
else:
|
||||
f88 = 5.0
|
||||
f8 = 100.0 * close[i]
|
||||
f8 = 100.0 * close.iloc[i]
|
||||
f18 = 3.0 / (length + 2.0)
|
||||
f20 = 1.0 - f18
|
||||
else:
|
||||
@@ -39,7 +42,7 @@ def rsx(close, length=None, drift=None, offset=None, **kwargs):
|
||||
else:
|
||||
f90 = f90 + 1
|
||||
f10 = f8
|
||||
f8 = 100 * close[i]
|
||||
f8 = 100 * close.iloc[i]
|
||||
v8 = f8 - f10
|
||||
f28 = f20 * f28 + f18 * v8
|
||||
f30 = f18 * f28 + f20 * f30
|
||||
|
||||
@@ -7,16 +7,19 @@ from pandas_ta.utils import get_offset, non_zero_range, verify_series
|
||||
def rvgi(open_, high, low, close, length=None, swma_length=None, offset=None, **kwargs):
|
||||
"""Indicator: Relative Vigor Index (RVGI)"""
|
||||
# Validate Arguments
|
||||
open_ = verify_series(open_)
|
||||
high = verify_series(high)
|
||||
low = verify_series(low)
|
||||
close = verify_series(close)
|
||||
high_low_range = non_zero_range(high, low)
|
||||
close_open_range = non_zero_range(close, open_)
|
||||
length = int(length) if length and length > 0 else 14
|
||||
swma_length = int(swma_length) if swma_length and swma_length > 0 else 4
|
||||
_length = max(length, swma_length)
|
||||
open_ = verify_series(open_, _length)
|
||||
high = verify_series(high, _length)
|
||||
low = verify_series(low, _length)
|
||||
close = verify_series(close, _length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if open_ is None or high is None or low is None or close is None: return
|
||||
|
||||
# Calculate Result
|
||||
numerator = swma(close_open_range, length=swma_length).rolling(length).sum()
|
||||
denominator = swma(high_low_range, length=swma_length).rolling(length).sum()
|
||||
@@ -74,9 +77,9 @@ Args:
|
||||
high (pd.Series): Series of 'high's
|
||||
low (pd.Series): Series of 'low's
|
||||
close (pd.Series): Series of 'close's
|
||||
length (int): It's period. Default: 14
|
||||
swma_length (int): It's period. Default: 4
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
length (int): It's period. Default: 14
|
||||
swma_length (int): It's period. Default: 4
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
@@ -1,23 +1,26 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from math import atan, pi
|
||||
from numpy import arctan as npAtan
|
||||
from numpy import pi as npPi
|
||||
from pandas_ta.utils import get_offset, verify_series
|
||||
|
||||
|
||||
def slope( close, length=None, as_angle=None, to_degrees=None, vertical=None, offset=None, **kwargs):
|
||||
"""Indicator: Slope"""
|
||||
# Validate arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 1
|
||||
as_angle = True if isinstance(as_angle, bool) else False
|
||||
to_degrees = True if isinstance(to_degrees, bool) else False
|
||||
close = verify_series(close, length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
slope = close.diff(length) / length
|
||||
if as_angle:
|
||||
slope = slope.apply(atan)
|
||||
slope = slope.apply(npAtan)
|
||||
if to_degrees:
|
||||
slope *= 180 / pi
|
||||
slope *= 180 / npPi
|
||||
|
||||
# Offset
|
||||
if offset != 0:
|
||||
@@ -39,7 +42,8 @@ def slope( close, length=None, as_angle=None, to_degrees=None, vertical=None, of
|
||||
slope.__doc__ = \
|
||||
"""Slope
|
||||
|
||||
Returns the slope of a series of length n. Can convert the slope to angle. Default: slope.
|
||||
Returns the slope of a series of length n. Can convert the slope to angle.
|
||||
Default: slope.
|
||||
|
||||
Sources: Algebra I
|
||||
|
||||
|
||||
@@ -1,22 +1,24 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from pandas import concat, DataFrame
|
||||
from pandas import DataFrame
|
||||
from .tsi import tsi
|
||||
from pandas_ta.overlap import ema
|
||||
from pandas_ta.utils import get_offset, verify_series, signals
|
||||
from pandas_ta.utils import get_offset, verify_series
|
||||
|
||||
|
||||
def smi(close, fast=None, slow=None, signal=None, scalar=None, offset=None, **kwargs):
|
||||
"""Indicator: SMI Ergodic Indicator (SMIIO)"""
|
||||
# Validate arguments
|
||||
close = verify_series(close)
|
||||
fast = int(fast) if fast and fast > 0 else 5
|
||||
slow = int(slow) if slow and slow > 0 else 20
|
||||
signal = int(signal) if signal and signal > 0 else 5
|
||||
if slow < fast:
|
||||
fast, slow = slow, fast
|
||||
scalar = float(scalar) if scalar else 1
|
||||
close = verify_series(close, max(fast, slow, signal))
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
smi = tsi(close, fast=fast, slow=slow, scalar=scalar)
|
||||
signalma = ema(smi, signal)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from numpy import NaN as npNaN
|
||||
from pandas import DataFrame
|
||||
|
||||
from pandas_ta.momentum import mom
|
||||
from pandas_ta.overlap import ema, linreg, sma
|
||||
from pandas_ta.trend import decreasing, increasing
|
||||
@@ -13,17 +12,19 @@ from pandas_ta.utils import unsigned_differences, verify_series
|
||||
def squeeze(high, low, close, bb_length=None, bb_std=None, kc_length=None, kc_scalar=None, mom_length=None, mom_smooth=None, use_tr=None, offset=None, **kwargs):
|
||||
"""Indicator: Squeeze Momentum (SQZ)"""
|
||||
# Validate arguments
|
||||
high = verify_series(high)
|
||||
low = verify_series(low)
|
||||
close = verify_series(close)
|
||||
offset = get_offset(offset)
|
||||
|
||||
bb_length = int(bb_length) if bb_length and bb_length > 0 else 20
|
||||
bb_std = float(bb_std) if bb_std and bb_std > 0 else 2.0
|
||||
kc_length = int(kc_length) if kc_length and kc_length > 0 else 20
|
||||
kc_scalar = float(kc_scalar) if kc_scalar and kc_scalar > 0 else 1.5
|
||||
mom_length = int(mom_length) if mom_length and mom_length > 0 else 12
|
||||
mom_smooth = int(mom_smooth) if mom_smooth and mom_smooth > 0 else 6
|
||||
_length = max(bb_length, kc_length, mom_length, mom_smooth)
|
||||
high = verify_series(high, _length)
|
||||
low = verify_series(low, _length)
|
||||
close = verify_series(close, _length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if high is None or low is None or close is None: return
|
||||
|
||||
use_tr = kwargs.setdefault("tr", True)
|
||||
asint = kwargs.pop("asint", True)
|
||||
@@ -203,7 +204,7 @@ Args:
|
||||
mom_length (int): Momentum Period. Default: 12
|
||||
mom_smooth (int): Smoothing Period of Momentum. Default: 6
|
||||
mamode (str): Only "ema" or "sma". Default: "sma"
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
tr (value, optional): Use True Range for Keltner Channels. Default: True
|
||||
|
||||
@@ -7,14 +7,17 @@ from pandas_ta.utils import get_offset, non_zero_range, verify_series
|
||||
def stoch(high, low, close, k=None, d=None, smooth_k=None, offset=None, **kwargs):
|
||||
"""Indicator: Stochastic Oscillator (STOCH)"""
|
||||
# Validate arguments
|
||||
high = verify_series(high)
|
||||
low = verify_series(low)
|
||||
close = verify_series(close)
|
||||
k = k if k and k > 0 else 14
|
||||
d = d if d and d > 0 else 3
|
||||
smooth_k = smooth_k if smooth_k and smooth_k > 0 else 3
|
||||
_length = max(k, d, smooth_k)
|
||||
high = verify_series(high, _length)
|
||||
low = verify_series(low, _length)
|
||||
close = verify_series(close, _length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if high is None or low is None or close is None: return
|
||||
|
||||
# Calculate Result
|
||||
lowest_low = low.rolling(k).min()
|
||||
highest_high = high.rolling(k).max()
|
||||
@@ -88,7 +91,7 @@ Args:
|
||||
k (int): The Fast %K period. Default: 14
|
||||
d (int): The Slow %K period. Default: 3
|
||||
smooth_k (int): The Slow %D period. Default: 3
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
@@ -8,13 +8,15 @@ from pandas_ta.utils import get_offset, non_zero_range, verify_series
|
||||
def stochrsi(close, length=None, rsi_length=None, k=None, d=None, offset=None, **kwargs):
|
||||
"""Indicator: Stochastic RSI Oscillator (STOCHRSI)"""
|
||||
# Validate arguments
|
||||
close = verify_series(close)
|
||||
length = length if length and length > 0 else 14
|
||||
rsi_length = rsi_length if rsi_length and rsi_length > 0 else 14
|
||||
k = k if k and k > 0 else 3
|
||||
d = d if d and d > 0 else 3
|
||||
close = verify_series(close, max(length, rsi_length, k, d))
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
rsi_ = rsi(close, length=rsi_length)
|
||||
lowest_rsi = rsi_.rolling(length).min()
|
||||
@@ -90,7 +92,7 @@ Args:
|
||||
rsi_length (int): RSI period. Default: 14
|
||||
k (int): The Fast %K period. Default: 3
|
||||
d (int): The Slow %K period. Default: 3
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# import numpy as np
|
||||
from numpy import where as npWhere
|
||||
from pandas import DataFrame, Series
|
||||
from pandas_ta.utils import get_offset, verify_series
|
||||
|
||||
|
||||
def td_seq(close, asint=None, offset=None, **kwargs):
|
||||
"""Indicator: Tom Demark Sequential (TD_SEQ)"""
|
||||
# Validate arguments
|
||||
close = verify_series(close)
|
||||
offset = get_offset(offset)
|
||||
asint = asint if isinstance(asint, bool) else False
|
||||
show_all = kwargs.setdefault("show_all", True)
|
||||
|
||||
def true_sequence_count(series: Series):
|
||||
index = series.where(series == False).last_valid_index()
|
||||
|
||||
if index is None:
|
||||
return series.count()
|
||||
else:
|
||||
s = series[series.index > index]
|
||||
return s.count()
|
||||
|
||||
def calc_td(series: Series, direction: str, show_all: bool):
|
||||
td_bool = series.diff(4) > 0 if direction=="up" else series.diff(4) < 0
|
||||
td_num = npWhere(
|
||||
td_bool, td_bool.rolling(13, min_periods=0).apply(true_sequence_count), 0
|
||||
)
|
||||
td_num = Series(td_num)
|
||||
|
||||
if show_all:
|
||||
td_num = td_num.mask(td_num == 0)
|
||||
else:
|
||||
td_num = td_num.mask(~td_num.between(6,9))
|
||||
|
||||
return td_num
|
||||
|
||||
up_seq = calc_td(close, "up", show_all)
|
||||
down_seq = calc_td(close, "down", show_all)
|
||||
|
||||
if asint:
|
||||
if up_seq.hasnans and down_seq.hasnans:
|
||||
up_seq.fillna(0, inplace=True)
|
||||
down_seq.fillna(0, inplace=True)
|
||||
up_seq = up_seq.astype(int)
|
||||
down_seq = down_seq.astype(int)
|
||||
|
||||
# Offset
|
||||
if offset != 0:
|
||||
up_seq = up_seq.shift(offset)
|
||||
down_seq = down_seq.shift(offset)
|
||||
|
||||
# Handle fills
|
||||
if "fillna" in kwargs:
|
||||
up_seq.fillna(kwargs["fillna"], inplace=True)
|
||||
down_seq.fillna(kwargs["fillna"], inplace=True)
|
||||
|
||||
if "fill_method" in kwargs:
|
||||
up_seq.fillna(method=kwargs["fill_method"], inplace=True)
|
||||
down_seq.fillna(method=kwargs["fill_method"], inplace=True)
|
||||
|
||||
# Name & Category
|
||||
up_seq.name = f"TD_SEQ_UPa" if show_all else f"TD_SEQ_UP"
|
||||
down_seq.name = f"TD_SEQ_DNa" if show_all else f"TD_SEQ_DN"
|
||||
up_seq.category = down_seq.category = "momentum"
|
||||
|
||||
# Prepare Dataframe to return
|
||||
data = {
|
||||
up_seq.name: up_seq,
|
||||
down_seq.name: down_seq
|
||||
}
|
||||
df = DataFrame(data)
|
||||
df.name = "TD_SEQ"
|
||||
df.category = up_seq.category
|
||||
|
||||
return df
|
||||
|
||||
|
||||
td_seq.__doc__ = \
|
||||
"""TD Sequential (TD_SEQ)
|
||||
|
||||
Tom DeMark's Sequential indicator attempts to identify a price point where an
|
||||
uptrend or a downtrend exhausts itself and reverses.
|
||||
|
||||
Sources:
|
||||
https://tradetrekker.wordpress.com/tdsequential/
|
||||
|
||||
Calculation:
|
||||
Compare current close price with 4 days ago price, up to 13 days. For the
|
||||
consecutive ascending or descending price sequence, display 6th to 9th day
|
||||
value.
|
||||
|
||||
Args:
|
||||
close (pd.Series): Series of 'close's
|
||||
asint (bool): If True, fillnas with 0 and change type to int. Default: False
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
show_all (bool): Show 1 - 13. If set to False, show 6 - 9. Default: True
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
Returns:
|
||||
pd.DataFrame: New feature generated.
|
||||
"""
|
||||
@@ -7,13 +7,15 @@ from pandas_ta.utils import get_drift, get_offset, verify_series
|
||||
def trix(close, length=None, signal=None, scalar=None, drift=None, offset=None, **kwargs):
|
||||
"""Indicator: Trix (TRIX)"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 30
|
||||
signal = int(signal) if signal and signal > 0 else 9
|
||||
scalar = float(scalar) if scalar else 100
|
||||
close = verify_series(close, max(length, signal))
|
||||
drift = get_drift(drift)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
ema1 = ema(close=close, length=length, **kwargs)
|
||||
ema2 = ema(close=ema1, length=length, **kwargs)
|
||||
@@ -68,11 +70,11 @@ Calculation:
|
||||
|
||||
Args:
|
||||
close (pd.Series): Series of 'close's
|
||||
length (int): It's period. Default: 18
|
||||
signal (int): It's period. Default: 9
|
||||
scalar (float): How much to magnify. Default: 100
|
||||
drift (int): The difference period. Default: 1
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
length (int): It's period. Default: 18
|
||||
signal (int): It's period. Default: 9
|
||||
scalar (float): How much to magnify. Default: 100
|
||||
drift (int): The difference period. Default: 1
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
@@ -6,14 +6,17 @@ from pandas_ta.utils import get_drift, get_offset, verify_series
|
||||
def tsi(close, fast=None, slow=None, scalar=None, drift=None, offset=None, **kwargs):
|
||||
"""Indicator: True Strength Index (TSI)"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
fast = int(fast) if fast and fast > 0 else 13
|
||||
slow = int(slow) if slow and slow > 0 else 25
|
||||
# if slow < fast:
|
||||
# fast, slow = slow, fast
|
||||
scalar = float(scalar) if scalar else 100
|
||||
close = verify_series(close, max(fast, slow))
|
||||
drift = get_drift(drift)
|
||||
offset = get_offset(offset)
|
||||
if "length" in kwargs: kwargs.pop("length")
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
diff = close.diff(drift)
|
||||
@@ -73,7 +76,7 @@ Args:
|
||||
slow (int): The long period. Default: 25
|
||||
scalar (float): How much to magnify. Default: 100
|
||||
drift (int): The difference period. Default: 1
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
+19
-19
@@ -6,20 +6,20 @@ from pandas_ta.utils import get_drift, get_offset, verify_series
|
||||
def uo(high, low, close, fast=None, medium=None, slow=None, fast_w=None, medium_w=None, slow_w=None, drift=None, offset=None, **kwargs):
|
||||
"""Indicator: Ultimate Oscillator (UO)"""
|
||||
# Validate arguments
|
||||
high = verify_series(high)
|
||||
low = verify_series(low)
|
||||
close = verify_series(close)
|
||||
fast = int(fast) if fast and fast > 0 else 7
|
||||
fast_w = float(fast_w) if fast_w and fast_w > 0 else 4.0
|
||||
medium = int(medium) if medium and medium > 0 else 14
|
||||
medium_w = float(medium_w) if medium_w and medium_w > 0 else 2.0
|
||||
slow = int(slow) if slow and slow > 0 else 28
|
||||
slow_w = float(slow_w) if slow_w and slow_w > 0 else 1.0
|
||||
_length = max(fast, medium, slow)
|
||||
high = verify_series(high, _length)
|
||||
low = verify_series(low, _length)
|
||||
close = verify_series(close, _length)
|
||||
drift = get_drift(drift)
|
||||
offset = get_offset(offset)
|
||||
|
||||
fast = int(fast) if fast and fast > 0 else 7
|
||||
fast_w = float(fast_w) if fast_w and fast_w > 0 else 4.0
|
||||
|
||||
medium = int(medium) if medium and medium > 0 else 14
|
||||
medium_w = float(medium_w) if medium_w and medium_w > 0 else 2.0
|
||||
|
||||
slow = int(slow) if slow and slow > 0 else 28
|
||||
slow_w = float(slow_w) if slow_w and slow_w > 0 else 1.0
|
||||
if high is None or low is None or close is None: return
|
||||
|
||||
# Calculate Result
|
||||
tdf = DataFrame({
|
||||
@@ -90,14 +90,14 @@ Args:
|
||||
high (pd.Series): Series of 'high's
|
||||
low (pd.Series): Series of 'low's
|
||||
close (pd.Series): Series of 'close's
|
||||
fast (int): The Fast %K period. Default: 7
|
||||
medium (int): The Slow %K period. Default: 14
|
||||
slow (int): The Slow %D period. Default: 28
|
||||
fast_w (float): The Fast %K period. Default: 4.0
|
||||
medium_w (float): The Slow %K period. Default: 2.0
|
||||
slow_w (float): The Slow %D period. Default: 1.0
|
||||
drift (int): The difference period. Default: 1
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
fast (int): The Fast %K period. Default: 7
|
||||
medium (int): The Slow %K period. Default: 14
|
||||
slow (int): The Slow %D period. Default: 28
|
||||
fast_w (float): The Fast %K period. Default: 4.0
|
||||
medium_w (float): The Slow %K period. Default: 2.0
|
||||
slow_w (float): The Slow %D period. Default: 1.0
|
||||
drift (int): The difference period. Default: 1
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from pandas_ta.utils import get_drift, get_offset, verify_series
|
||||
from pandas_ta.utils import get_offset, verify_series
|
||||
|
||||
|
||||
def willr(high, low, close, length=None, offset=None, **kwargs):
|
||||
"""Indicator: William's Percent R (WILLR)"""
|
||||
# Validate arguments
|
||||
high = verify_series(high)
|
||||
low = verify_series(low)
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 14
|
||||
min_periods = int(kwargs["min_periods"]) if "min_periods" in kwargs and kwargs["min_periods"] is not None else length
|
||||
_length = max(length, min_periods)
|
||||
high = verify_series(high, _length)
|
||||
low = verify_series(low, _length)
|
||||
close = verify_series(close, _length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if high is None or low is None or close is None: return
|
||||
|
||||
# Calculate Result
|
||||
lowest_low = low.rolling(length, min_periods=min_periods).min()
|
||||
highest_high = high.rolling(length, min_periods=min_periods).max()
|
||||
@@ -56,8 +59,8 @@ Args:
|
||||
high (pd.Series): Series of 'high's
|
||||
low (pd.Series): Series of 'low's
|
||||
close (pd.Series): Series of 'close's
|
||||
length (int): It's period. Default: 14
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
length (int): It's period. Default: 14
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from .alma import alma
|
||||
from .dema import dema
|
||||
from .ema import ema
|
||||
from .fwma import fwma
|
||||
@@ -6,6 +7,7 @@ from .hilo import hilo
|
||||
from .hl2 import hl2
|
||||
from .hlc3 import hlc3
|
||||
from .hma import hma
|
||||
from .hwma import hwma
|
||||
from .kama import kama
|
||||
from .ichimoku import ichimoku
|
||||
from .linreg import linreg
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from numpy import exp as npExp
|
||||
from numpy import NaN as npNaN
|
||||
from pandas import Series
|
||||
from pandas_ta.utils import get_offset, verify_series
|
||||
|
||||
|
||||
def alma(close, length=None, sigma=None, distribution_offset=None, offset=None, **kwargs):
|
||||
"""Indicator: Arnaud Legoux Moving Average (ALMA)"""
|
||||
# Validate Arguments
|
||||
length = int(length) if length and length > 0 else 10
|
||||
sigma = float(sigma) if sigma and sigma > 0 else 6.0
|
||||
distribution_offset = float(distribution_offset) if distribution_offset and distribution_offset > 0 else 0.85
|
||||
close = verify_series(close, length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Pre-Calculations
|
||||
m = distribution_offset * (length - 1)
|
||||
s = length / sigma
|
||||
wtd = list(range(length))
|
||||
for i in range(0, length):
|
||||
wtd[i] = npExp(-1 * ((i - m) * (i - m)) / (2 * s * s))
|
||||
|
||||
# Calculate Result
|
||||
result = [npNaN for _ in range(0, length - 1)] + [0]
|
||||
for i in range(length, close.size):
|
||||
window_sum = 0
|
||||
cum_sum = 0
|
||||
for j in range(0, length):
|
||||
# wtd = math.exp(-1 * ((j - m) * (j - m)) / (2 * s * s)) # moved to pre-calc for efficiency
|
||||
window_sum = window_sum + wtd[j] * close.iloc[i - j]
|
||||
cum_sum = cum_sum + wtd[j]
|
||||
|
||||
almean = window_sum / cum_sum
|
||||
result.append(npNaN) if i == length else result.append(almean)
|
||||
|
||||
alma = Series(result, index=close.index)
|
||||
|
||||
# Offset
|
||||
if offset != 0:
|
||||
alma = alma.shift(offset)
|
||||
|
||||
# Handle fills
|
||||
if "fillna" in kwargs:
|
||||
alma.fillna(kwargs["fillna"], inplace=True)
|
||||
if "fill_method" in kwargs:
|
||||
alma.fillna(method=kwargs["fill_method"], inplace=True)
|
||||
|
||||
# Name & Category
|
||||
alma.name = f"ALMA_{length}_{sigma}_{distribution_offset}"
|
||||
alma.category = "overlap"
|
||||
|
||||
return alma
|
||||
|
||||
|
||||
alma.__doc__ = \
|
||||
"""Arnaud Legoux Moving Average (ALMA)
|
||||
|
||||
The ALMA moving average uses the curve of the Normal (Gauss) distribution, which
|
||||
can be shifted from 0 to 1. This allows regulating the smoothness and high
|
||||
sensitivity of the indicator. Sigma is another parameter that is responsible for
|
||||
the shape of the curve coefficients. This moving average reduces lag of the data
|
||||
in conjunction with smoothing to reduce noise.
|
||||
|
||||
Implemented for Pandas TA by rengel8 based on the source provided below.
|
||||
|
||||
Sources:
|
||||
https://www.prorealcode.com/prorealtime-indicators/alma-arnaud-legoux-moving-average/
|
||||
|
||||
Calculation:
|
||||
refer to provided source
|
||||
|
||||
Args:
|
||||
close (pd.Series): Series of 'close's
|
||||
length (int): It's period, window size. Default: 10
|
||||
sigma (float): Smoothing value. Default 6.0
|
||||
distribution_offset (float): Value to offset the distribution min 0
|
||||
(smoother), max 1 (more responsive). Default 0.85
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
fill_method (value, optional): Type of fill method
|
||||
|
||||
Returns:
|
||||
pd.Series: New feature generated.
|
||||
"""
|
||||
@@ -6,10 +6,12 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def dema(close, length=None, offset=None, **kwargs):
|
||||
"""Indicator: Double Exponential Moving Average (DEMA)"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 10
|
||||
close = verify_series(close, length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
ema1 = ema(close=close, length=length)
|
||||
ema2 = ema(close=ema1, length=length)
|
||||
@@ -46,8 +48,8 @@ Calculation:
|
||||
|
||||
Args:
|
||||
close (pd.Series): Series of 'close's
|
||||
length (int): It's period. Default: 10
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
length (int): It's period. Default: 10
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
@@ -6,12 +6,14 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def ema(close, length=None, offset=None, **kwargs):
|
||||
"""Indicator: Exponential Moving Average (EMA)"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 10
|
||||
adjust = kwargs.pop("adjust", False)
|
||||
sma = kwargs.pop("sma", True)
|
||||
close = verify_series(close, length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
if sma:
|
||||
close = close.copy()
|
||||
@@ -55,8 +57,8 @@ Calculation:
|
||||
|
||||
Args:
|
||||
close (pd.Series): Series of 'close's
|
||||
length (int): It's period. Default: 10
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
length (int): It's period. Default: 10
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
adjust (bool, optional): Default: False
|
||||
|
||||
@@ -5,11 +5,13 @@ from pandas_ta.utils import fibonacci, get_offset, verify_series, weights
|
||||
def fwma(close, length=None, asc=None, offset=None, **kwargs):
|
||||
"""Indicator: Fibonacci's Weighted Moving Average (FWMA)"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 10
|
||||
asc = asc if asc else True
|
||||
close = verify_series(close, length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
fibs = fibonacci(n=length, weighted=True)
|
||||
fwma = close.rolling(length, min_periods=length).apply(weights(fibs), raw=True)
|
||||
@@ -47,9 +49,9 @@ Calculation:
|
||||
|
||||
Args:
|
||||
close (pd.Series): Series of 'close's
|
||||
length (int): It's period. Default: 10
|
||||
asc (bool): Recent values weigh more. Default: True
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
length (int): It's period. Default: 10
|
||||
asc (bool): Recent values weigh more. Default: True
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from numpy import NaN as npNaN
|
||||
from pandas import DataFrame, Series
|
||||
# from pandas_ta.overlap.ma import ma
|
||||
from .ma import ma
|
||||
from pandas_ta.utils import get_offset, verify_series
|
||||
|
||||
@@ -9,14 +8,17 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def hilo(high, low, close, high_length=None, low_length=None, mamode=None, offset=None, **kwargs):
|
||||
"""Indicator: Gann HiLo (HiLo)"""
|
||||
# Validate Arguments
|
||||
high = verify_series(high)
|
||||
low = verify_series(low)
|
||||
close = verify_series(close)
|
||||
high_length = int(high_length) if high_length and high_length > 0 else 13
|
||||
low_length = int(low_length) if low_length and low_length > 0 else 21
|
||||
mamode = mamode.lower() if isinstance(mamode, str) else "sma"
|
||||
_length = max(high_length, low_length)
|
||||
high = verify_series(high, _length)
|
||||
low = verify_series(low, _length)
|
||||
close = verify_series(close, _length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if high is None or low is None or close is None: return
|
||||
|
||||
# Calculate Result
|
||||
m = close.size
|
||||
hilo = Series(npNaN, index=close.index)
|
||||
@@ -113,8 +115,8 @@ Args:
|
||||
close (pd.Series): Series of 'close's
|
||||
high_length (int): It's period. Default: 13
|
||||
low_length (int): It's period. Default: 21
|
||||
mamode (str): Options: 'sma' or 'ema'. Default: 'sma'
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
mamode (str): Options: 'sma' or 'ema'. Default: 'sma'
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
adjust (bool): Default: True
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from math import sqrt
|
||||
from numpy import sqrt as npSqrt
|
||||
from .wma import wma
|
||||
from pandas_ta.utils import get_offset, verify_series
|
||||
|
||||
@@ -7,13 +7,15 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def hma(close, length=None, offset=None, **kwargs):
|
||||
"""Indicator: Hull Moving Average (HMA)"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 10
|
||||
close = verify_series(close, length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
half_length = int(length / 2)
|
||||
sqrt_length = int(sqrt(length))
|
||||
sqrt_length = int(npSqrt(length))
|
||||
|
||||
wmaf = wma(close=close, length=half_length)
|
||||
wmas = wma(close=close, length=length)
|
||||
@@ -44,7 +46,7 @@ Calculation:
|
||||
length=10
|
||||
WMA = Weighted Moving Average
|
||||
half_length = int(0.5 * length)
|
||||
sqrt_length = int(math.sqrt(length))
|
||||
sqrt_length = int(sqrt(length))
|
||||
|
||||
wmaf = WMA(close, half_length)
|
||||
wmas = WMA(close, length)
|
||||
@@ -52,8 +54,8 @@ Calculation:
|
||||
|
||||
Args:
|
||||
close (pd.Series): Series of 'close's
|
||||
length (int): It's period. Default: 10
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
length (int): It's period. Default: 10
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from pandas import Series
|
||||
from pandas_ta.utils import get_offset, verify_series
|
||||
|
||||
|
||||
def hwma(close, na=None, nb=None, nc=None, offset=None, **kwargs):
|
||||
"""Indicator: Holt-Winter Moving Average"""
|
||||
# Validate Arguments
|
||||
na = float(na) if na and na > 0 and na < 1 else 0.2
|
||||
nb = float(nb) if nb and nb > 0 and nb < 1 else 0.1
|
||||
nc = float(nc) if nc and nc > 0 and nc < 1 else 0.1
|
||||
close = verify_series(close)
|
||||
offset = get_offset(offset)
|
||||
|
||||
# Calculate Result
|
||||
last_a = last_v = 0
|
||||
last_f = close.iloc[0]
|
||||
|
||||
result = []
|
||||
m = close.size
|
||||
for i in range(m):
|
||||
F = (1.0 - na) * (last_f + last_v + 0.5 * last_a) + na * close.iloc[i]
|
||||
V = (1.0 - nb) * (last_v + last_a) + nb * (F - last_f)
|
||||
A = (1.0 - nc) * last_a + nc * (V - last_v)
|
||||
result.append((F + V + 0.5 * A))
|
||||
last_a, last_f, last_v = A, F, V # update values
|
||||
|
||||
hwma = Series(result, index=close.index)
|
||||
|
||||
# Offset
|
||||
if offset != 0:
|
||||
hwma = hwma.shift(offset)
|
||||
|
||||
# Handle fills
|
||||
if "fillna" in kwargs:
|
||||
hwma.fillna(kwargs["fillna"], inplace=True)
|
||||
if "fill_method" in kwargs:
|
||||
hwma.fillna(method=kwargs["fill_method"], inplace=True)
|
||||
|
||||
# Name & Category
|
||||
suffix = f"{na}_{nb}_{nc}"
|
||||
hwma.name = f"HWMA_{suffix}"
|
||||
hwma.category = "overlap"
|
||||
|
||||
return hwma
|
||||
|
||||
|
||||
|
||||
hwma.__doc__ = \
|
||||
"""HWMA (Holt-Winter Moving Average)
|
||||
|
||||
Indicator HWMA (Holt-Winter Moving Average) is a three-parameter moving average
|
||||
by the Holt-Winter method; the three parameters should be selected to obtain a
|
||||
forecast.
|
||||
|
||||
This version has been implemented for Pandas TA by rengel8 based
|
||||
on a publication for MetaTrader 5.
|
||||
|
||||
Sources:
|
||||
https://www.mql5.com/en/code/20856
|
||||
|
||||
Calculation:
|
||||
HWMA[i] = F[i] + V[i] + 0.5 * A[i]
|
||||
where..
|
||||
F[i] = (1-na) * (F[i-1] + V[i-1] + 0.5 * A[i-1]) + na * Price[i]
|
||||
V[i] = (1-nb) * (V[i-1] + A[i-1]) + nb * (F[i] - F[i-1])
|
||||
A[i] = (1-nc) * A[i-1] + nc * (V[i] - V[i-1])
|
||||
|
||||
Args:
|
||||
close (pd.Series): Series of 'close's
|
||||
na (float): Smoothed series parameter (from 0 to 1). Default: 0.2
|
||||
nb (float): Trend parameter (from 0 to 1). Default: 0.1
|
||||
nc (float): Seasonality parameter (from 0 to 1). Default: 0.1
|
||||
close (pd.Series): Series of 'close's
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
fill_method (value, optional): Type of fill method
|
||||
|
||||
Returns:
|
||||
pd.Series: hwma
|
||||
"""
|
||||
@@ -6,14 +6,17 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
|
||||
def ichimoku(high, low, close, tenkan=None, kijun=None, senkou=None, offset=None, **kwargs):
|
||||
"""Indicator: Ichimoku Kinkō Hyō (Ichimoku)"""
|
||||
high = verify_series(high)
|
||||
low = verify_series(low)
|
||||
close = verify_series(close)
|
||||
tenkan = int(tenkan) if tenkan and tenkan > 0 else 9
|
||||
kijun = int(kijun) if kijun and kijun > 0 else 26
|
||||
senkou = int(senkou) if senkou and senkou > 0 else 52
|
||||
_length = max(tenkan, kijun, senkou)
|
||||
high = verify_series(high, _length)
|
||||
low = verify_series(low, _length)
|
||||
close = verify_series(close, _length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if high is None or low is None or close is None: return None, None
|
||||
|
||||
# Calculate Result
|
||||
tenkan_sen = midprice(high=high, low=low, length=tenkan)
|
||||
kijun_sen = midprice(high=high, low=low, length=kijun)
|
||||
@@ -115,10 +118,10 @@ Args:
|
||||
high (pd.Series): Series of 'high's
|
||||
low (pd.Series): Series of 'low's
|
||||
close (pd.Series): Series of 'close's
|
||||
tenkan (int): Tenkan period. Default: 9
|
||||
kijun (int): Kijun period. Default: 26
|
||||
senkou (int): Senkou period. Default: 52
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
tenkan (int): Tenkan period. Default: 9
|
||||
kijun (int): Kijun period. Default: 26
|
||||
senkou (int): Senkou period. Default: 52
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
+12
-11
@@ -1,22 +1,22 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from numpy import NaN as npNaN
|
||||
from pandas import Series, DataFrame
|
||||
from pandas import Series
|
||||
from pandas_ta.utils import get_drift, get_offset, non_zero_range, verify_series
|
||||
|
||||
|
||||
def kama(close, length=None, fast=None, slow=None, drift=None, offset=None, **kwargs):
|
||||
"""Indicator: Kaufman's Adaptive Moving Average (HMA)"""
|
||||
"""Indicator: Kaufman's Adaptive Moving Average (KAMA)"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 10
|
||||
fast = int(fast) if fast and fast > 0 else 2
|
||||
slow = int(slow) if slow and slow > 0 else 30
|
||||
close = verify_series(close, max(fast, slow, length))
|
||||
drift = get_drift(drift)
|
||||
offset = get_offset(offset)
|
||||
|
||||
# Calculate Result
|
||||
m = close.size
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
def weight(length: int) -> float:
|
||||
return 2 / (length + 1)
|
||||
|
||||
@@ -30,9 +30,10 @@ def kama(close, length=None, fast=None, slow=None, drift=None, offset=None, **kw
|
||||
x = er * (fr - sr) + sr
|
||||
sc = x * x
|
||||
|
||||
m = close.size
|
||||
result = [npNaN for _ in range(0, length - 1)] + [0]
|
||||
for i in range(length, m):
|
||||
result.append(sc[i] * close[i] + (1 - sc[i]) * result[i - 1])
|
||||
result.append(sc.iloc[i] * close.iloc[i] + (1 - sc.iloc[i]) * result[i - 1])
|
||||
|
||||
kama = Series(result, index=close.index)
|
||||
|
||||
@@ -66,11 +67,11 @@ Calculation:
|
||||
|
||||
Args:
|
||||
close (pd.Series): Series of 'close's
|
||||
length (int): It's period. Default: 10
|
||||
fast (int): Fast MA period. Default: 2
|
||||
slow (int): Slow MA period. Default: 30
|
||||
drift (int): The difference period. Default: 1
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
length (int): It's period. Default: 10
|
||||
fast (int): Fast MA period. Default: 2
|
||||
slow (int): Slow MA period. Default: 30
|
||||
drift (int): The difference period. Default: 1
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
+18
-10
@@ -1,13 +1,15 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import math
|
||||
from numpy import arctan as npAtan
|
||||
from numpy import pi as npPi
|
||||
from numpy import sqrt as npSqrt
|
||||
from pandas_ta.utils import get_offset, verify_series
|
||||
|
||||
|
||||
def linreg(close, length=None, offset=None, **kwargs):
|
||||
"""Indicator: Linear Regression"""
|
||||
# Validate arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 14
|
||||
close = verify_series(close, length)
|
||||
offset = get_offset(offset)
|
||||
angle = kwargs.pop("angle", False)
|
||||
intercept = kwargs.pop("intercept", False)
|
||||
@@ -16,6 +18,8 @@ def linreg(close, length=None, offset=None, **kwargs):
|
||||
slope = kwargs.pop("slope", False)
|
||||
tsf = kwargs.pop("tsf", False)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
x = range(1, length + 1) # [1, 2, ..., n] from 1 to n keeps Sum(xy) low
|
||||
x_sum = 0.5 * length * (length + 1)
|
||||
@@ -34,15 +38,15 @@ def linreg(close, length=None, offset=None, **kwargs):
|
||||
return b
|
||||
|
||||
if angle:
|
||||
theta = math.atan(m)
|
||||
theta = npAtan(m)
|
||||
if degrees:
|
||||
theta *= 180 / math.pi
|
||||
theta *= 180 / npPi
|
||||
return theta
|
||||
|
||||
if r:
|
||||
y2_sum = (series * series).sum()
|
||||
rn = length * xy_sum - x_sum * y_sum
|
||||
rd = math.sqrt(divisor * (length * y2_sum - y_sum * y_sum))
|
||||
rd = npSqrt(divisor * (length * y2_sum - y_sum * y_sum))
|
||||
return rn / rd
|
||||
|
||||
return m * length + b if tsf else m * (length - 1) + b
|
||||
@@ -105,12 +109,16 @@ Args:
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
angle (bool, optional): If True, returns the angle of the slope in radians. Default: False.
|
||||
degrees (bool, optional): If True, returns the angle of the slope in degrees. Default: False.
|
||||
intercept (bool, optional): If True, returns the angle of the slope in radians. Default: False.
|
||||
r (bool, optional): If True, returns it's correlation 'r'. Default: False.
|
||||
angle (bool, optional): If True, returns the angle of the slope in radians.
|
||||
Default: False.
|
||||
degrees (bool, optional): If True, returns the angle of the slope in
|
||||
degrees. Default: False.
|
||||
intercept (bool, optional): If True, returns the angle of the slope in
|
||||
radians. Default: False.
|
||||
r (bool, optional): If True, returns it's correlation 'r'. Default: False.
|
||||
slope (bool, optional): If True, returns the slope. Default: False.
|
||||
tsf (bool, optional): If True, returns the Time Series Forecast value. Default: False.
|
||||
tsf (bool, optional): If True, returns the Time Series Forecast value.
|
||||
Default: False.
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
fill_method (value, optional): Type of fill method
|
||||
|
||||
|
||||
@@ -5,11 +5,13 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def mcgd(close, length=None, offset=None, c=None, **kwargs):
|
||||
"""Indicator: McGinley Dynamic Indicator"""
|
||||
# Validate arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 10
|
||||
c = float(c) if c and 0 < c <= 1 else 1
|
||||
close = verify_series(close, length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
close = close.copy()
|
||||
|
||||
|
||||
@@ -5,11 +5,13 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def midpoint(close, length=None, offset=None, **kwargs):
|
||||
"""Indicator: Midpoint"""
|
||||
# Validate arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 2
|
||||
min_periods = int(kwargs["min_periods"]) if "min_periods" in kwargs and kwargs["min_periods"] is not None else length
|
||||
close = verify_series(close, max(length, min_periods))
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
lowest = close.rolling(length, min_periods=min_periods).min()
|
||||
highest = close.rolling(length, min_periods=min_periods).max()
|
||||
|
||||
@@ -5,12 +5,15 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def midprice(high, low, length=None, offset=None, **kwargs):
|
||||
"""Indicator: Midprice"""
|
||||
# Validate arguments
|
||||
high = verify_series(high)
|
||||
low = verify_series(low)
|
||||
length = int(length) if length and length > 0 else 2
|
||||
min_periods = int(kwargs["min_periods"]) if "min_periods" in kwargs and kwargs["min_periods"] is not None else length
|
||||
_length = max(length, min_periods)
|
||||
high = verify_series(high, _length)
|
||||
low = verify_series(low, _length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if high is None or low is None: return
|
||||
|
||||
# Calculate Result
|
||||
lowest_low = low.rolling(length, min_periods=min_periods).min()
|
||||
highest_high = high.rolling(length, min_periods=min_periods).max()
|
||||
|
||||
@@ -5,12 +5,13 @@ from pandas_ta.utils import get_offset, pascals_triangle, verify_series, weights
|
||||
def pwma(close, length=None, asc=None, offset=None, **kwargs):
|
||||
"""Indicator: Pascals Weighted Moving Average (PWMA)"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 10
|
||||
min_periods = int(kwargs["min_periods"]) if "min_periods" in kwargs and kwargs["min_periods"] is not None else length
|
||||
asc = asc if asc else True
|
||||
close = verify_series(close, length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
triangle = pascals_triangle(n=length - 1, weighted=True)
|
||||
pwma = close.rolling(length, min_periods=length).apply(weights(triangle), raw=True)
|
||||
@@ -29,8 +30,8 @@ def pwma(close, length=None, asc=None, offset=None, **kwargs):
|
||||
pwma.__doc__ = \
|
||||
"""Pascal's Weighted Moving Average (PWMA)
|
||||
|
||||
Pascal's Weighted Moving Average is similar to a symmetric triangular
|
||||
window except PWMA's weights are based on Pascal's Triangle.
|
||||
Pascal's Weighted Moving Average is similar to a symmetric triangular window
|
||||
except PWMA's weights are based on Pascal's Triangle.
|
||||
|
||||
Source: Kevin Johnson
|
||||
|
||||
@@ -49,8 +50,8 @@ Calculation:
|
||||
Args:
|
||||
close (pd.Series): Series of 'close's
|
||||
length (int): It's period. Default: 10
|
||||
asc (bool): Recent values weigh more. Default: True
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
asc (bool): Recent values weigh more. Default: True
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
@@ -5,10 +5,12 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def rma(close, length=None, offset=None, **kwargs):
|
||||
"""Indicator: wildeR's Moving Average (RMA)"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 10
|
||||
offset = get_offset(offset)
|
||||
alpha = (1.0 / length) if length > 0 else 0.5
|
||||
close = verify_series(close, length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
rma = close.ewm(alpha=alpha, min_periods=length).mean()
|
||||
@@ -27,7 +29,8 @@ def rma(close, length=None, offset=None, **kwargs):
|
||||
rma.__doc__ = \
|
||||
"""wildeR's Moving Average (RMA)
|
||||
|
||||
The WildeR's Moving Average is simply an Exponential Moving Average (EMA) with a modified alpha = 1 / length.
|
||||
The WildeR's Moving Average is simply an Exponential Moving Average (EMA) with
|
||||
a modified alpha = 1 / length.
|
||||
|
||||
Sources:
|
||||
https://tlc.thinkorswim.com/center/reference/Tech-Indicators/studies-library/V-Z/WildersSmoothing
|
||||
@@ -42,8 +45,8 @@ Calculation:
|
||||
|
||||
Args:
|
||||
close (pd.Series): Series of 'close's
|
||||
length (int): It's period. Default: 10
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
length (int): It's period. Default: 10
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from math import pi
|
||||
from math import sin
|
||||
from numpy import pi as npPi
|
||||
from numpy import sin as npSin
|
||||
from pandas import Series
|
||||
from pandas_ta.utils import get_offset, verify_series, weights
|
||||
|
||||
@@ -8,12 +8,14 @@ from pandas_ta.utils import get_offset, verify_series, weights
|
||||
def sinwma(close, length=None, offset=None, **kwargs):
|
||||
"""Indicator: Sine Weighted Moving Average (SINWMA) by Everget of TradingView"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 14
|
||||
close = verify_series(close, length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
sines = Series([sin((i + 1) * pi / (length + 1)) for i in range(0, length)])
|
||||
sines = Series([npSin((i + 1) * npPi / (length + 1)) for i in range(0, length)])
|
||||
w = sines / sines.sum()
|
||||
|
||||
sinwma = close.rolling(length, min_periods=length).apply(weights(w), raw=True)
|
||||
@@ -32,8 +34,8 @@ def sinwma(close, length=None, offset=None, **kwargs):
|
||||
sinwma.__doc__ = \
|
||||
"""Sine Weighted Moving Average (SWMA)
|
||||
|
||||
A weighted average using sine cycles. The middle term(s) of the average have the highest
|
||||
weight(s).
|
||||
A weighted average using sine cycles. The middle term(s) of the average have the
|
||||
highest weight(s).
|
||||
|
||||
Source:
|
||||
https://www.tradingview.com/script/6MWFvnPO-Sine-Weighted-Moving-Average/
|
||||
@@ -54,8 +56,8 @@ Calculation:
|
||||
|
||||
Args:
|
||||
close (pd.Series): Series of 'close's
|
||||
length (int): It's period. Default: 10
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
length (int): It's period. Default: 10
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
@@ -5,11 +5,13 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def sma(close, length=None, offset=None, **kwargs):
|
||||
"""Indicator: Simple Moving Average (SMA)"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 10
|
||||
min_periods = int(kwargs["min_periods"]) if "min_periods" in kwargs and kwargs["min_periods"] is not None else length
|
||||
close = verify_series(close, max(length, min_periods))
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
sma = close.rolling(length, min_periods=min_periods).mean()
|
||||
|
||||
@@ -46,8 +48,8 @@ Calculation:
|
||||
|
||||
Args:
|
||||
close (pd.Series): Series of 'close's
|
||||
length (int): It's period. Default: 10
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
length (int): It's period. Default: 10
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
adjust (bool): Default: True
|
||||
|
||||
@@ -3,18 +3,19 @@ from numpy import cos as npCos
|
||||
from numpy import exp as npExp
|
||||
from numpy import pi as npPi
|
||||
from numpy import sqrt as npSqrt
|
||||
from pandas import Series
|
||||
from pandas_ta.utils import get_offset, verify_series
|
||||
|
||||
|
||||
def ssf(close, length=None, poles=None, offset=None, **kwargs):
|
||||
"""Indicator: Ehler's Super Smoother Filter (SSF)"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 10
|
||||
poles = int(poles) if poles in [2, 3] else 2
|
||||
close = verify_series(close, length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
m = close.size
|
||||
ssf = close.copy()
|
||||
|
||||
@@ -9,13 +9,15 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def supertrend(high, low, close, length=None, multiplier=None, offset=None, **kwargs):
|
||||
"""Indicator: Supertrend"""
|
||||
# Validate Arguments
|
||||
high = verify_series(high)
|
||||
low = verify_series(low)
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 7
|
||||
multiplier = float(multiplier) if multiplier and multiplier > 0 else 3.0
|
||||
high = verify_series(high, length)
|
||||
low = verify_series(low, length)
|
||||
close = verify_series(close, length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if high is None or low is None or close is None: return
|
||||
|
||||
# Calculate Results
|
||||
m = close.size
|
||||
dir_, trend = [1] * m, [0] * m
|
||||
@@ -109,8 +111,9 @@ Args:
|
||||
low (pd.Series): Series of 'low's
|
||||
close (pd.Series): Series of 'close's
|
||||
length (int) : length for ATR calculation. Default: 7
|
||||
multiplier (float): Coefficient for upper and lower band distance to midrange. Default: 3.0
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
multiplier (float): Coefficient for upper and lower band distance to
|
||||
midrange. Default: 3.0
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
@@ -5,15 +5,18 @@ from pandas_ta.utils import get_offset, symmetric_triangle, verify_series, weigh
|
||||
def swma(close, length=None, asc=None, offset=None, **kwargs):
|
||||
"""Indicator: Symmetric Weighted Moving Average (SWMA)"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 10
|
||||
min_periods = int(kwargs["min_periods"]) if "min_periods" in kwargs and kwargs["min_periods"] is not None else length
|
||||
# min_periods = int(kwargs["min_periods"]) if "min_periods" in kwargs and kwargs["min_periods"] is not None else length
|
||||
asc = asc if asc else True
|
||||
close = verify_series(close, length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
triangle = symmetric_triangle(length, weighted=True)
|
||||
swma = close.rolling(length, min_periods=length).apply(weights(triangle), raw=True)
|
||||
# swma = close.rolling(length).apply(weights(triangle), raw=True)
|
||||
|
||||
# Offset
|
||||
if offset != 0:
|
||||
@@ -30,8 +33,9 @@ swma.__doc__ = \
|
||||
"""Symmetric Weighted Moving Average (SWMA)
|
||||
|
||||
Symmetric Weighted Moving Average where weights are based on a symmetric
|
||||
triangle. For example: n=3 -> [1, 2, 1], n=4 -> [1, 2, 2, 1], etc... This moving
|
||||
average has variable length in contrast to TradingView's fixed length of 4.
|
||||
triangle. For example: n=3 -> [1, 2, 1], n=4 -> [1, 2, 2, 1], etc...
|
||||
This moving average has variable length in contrast to TradingView's fixed
|
||||
length of 4.
|
||||
|
||||
Source:
|
||||
https://www.tradingview.com/study-script-reference/#fun_swma
|
||||
@@ -50,9 +54,9 @@ Calculation:
|
||||
|
||||
Args:
|
||||
close (pd.Series): Series of 'close's
|
||||
length (int): It's period. Default: 10
|
||||
asc (bool): Recent values weigh more. Default: True
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
length (int): It's period. Default: 10
|
||||
asc (bool): Recent values weigh more. Default: True
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
@@ -6,11 +6,13 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def t3(close, length=None, a=None, offset=None, **kwargs):
|
||||
"""Indicator: T3"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 10
|
||||
a = float(a) if a and a > 0 and a < 1 else 0.7
|
||||
close = verify_series(close, length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
c1 = -a * a**2
|
||||
c2 = 3 * a**2 + 3 * a**3
|
||||
@@ -62,9 +64,9 @@ Calculation:
|
||||
|
||||
Args:
|
||||
close (pd.Series): Series of 'close's
|
||||
length (int): It's period. Default: 10
|
||||
a (float): 0 < a < 1. Default: 0.7
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
length (int): It's period. Default: 10
|
||||
a (float): 0 < a < 1. Default: 0.7
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
adjust (bool): Default: True
|
||||
|
||||
@@ -6,10 +6,12 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def tema(close, length=None, offset=None, **kwargs):
|
||||
"""Indicator: Triple Exponential Moving Average (TEMA)"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 10
|
||||
close = verify_series(close, length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
ema1 = ema(close=close, length=length, **kwargs)
|
||||
ema2 = ema(close=ema1, length=length, **kwargs)
|
||||
@@ -46,8 +48,8 @@ Calculation:
|
||||
|
||||
Args:
|
||||
close (pd.Series): Series of 'close's
|
||||
length (int): It's period. Default: 10
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
length (int): It's period. Default: 10
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
adjust (bool): Default: True
|
||||
|
||||
@@ -6,10 +6,12 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def trima(close, length=None, offset=None, **kwargs):
|
||||
"""Indicator: Triangular Moving Average (TRIMA)"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 10
|
||||
close = verify_series(close, length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
half_length = round(0.5 * (length + 1))
|
||||
sma1 = sma(close, length=half_length)
|
||||
@@ -41,14 +43,14 @@ Calculation:
|
||||
Default Inputs:
|
||||
length=10
|
||||
SMA = Simple Moving Average
|
||||
half_length = math.round(0.5 * (length + 1))
|
||||
half_length = round(0.5 * (length + 1))
|
||||
SMA1 = SMA(close, half_length)
|
||||
TRIMA = SMA(SMA1, half_length)
|
||||
|
||||
Args:
|
||||
close (pd.Series): Series of 'close's
|
||||
length (int): It's period. Default: 10
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
length (int): It's period. Default: 10
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
adjust (bool): Default: True
|
||||
|
||||
@@ -7,11 +7,13 @@ from pandas_ta.utils import get_drift, get_offset, verify_series
|
||||
def vidya(close, length=None, drift=None, offset=None, **kwargs):
|
||||
"""Indicator: Variable Index Dynamic Average (VIDYA)"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 14
|
||||
close = verify_series(close, length)
|
||||
drift = get_drift(drift)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
def _cmo(source: Series, n:int , d: int):
|
||||
"""Chande Momentum Oscillator (CMO) Patch
|
||||
For some reason: from pandas_ta.momentum import cmo causes
|
||||
|
||||
@@ -6,11 +6,13 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def vwma(close, volume, length=None, offset=None, **kwargs):
|
||||
"""Indicator: Volume Weighted Moving Average (VWMA)"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
volume = verify_series(volume)
|
||||
length = int(length) if length and length > 0 else 10
|
||||
close = verify_series(close, length)
|
||||
volume = verify_series(volume, length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None or volume is None: return
|
||||
|
||||
# Calculate Result
|
||||
pv = close * volume
|
||||
vwma = sma(close=pv, length=length) / sma(close=volume, length=length)
|
||||
@@ -44,8 +46,8 @@ Calculation:
|
||||
Args:
|
||||
close (pd.Series): Series of 'close's
|
||||
volume (pd.Series): Series of 'volume's
|
||||
length (int): It's period. Default: 10
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
length (int): It's period. Default: 10
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
@@ -40,7 +40,7 @@ Args:
|
||||
high (pd.Series): Series of 'high's
|
||||
low (pd.Series): Series of 'low's
|
||||
close (pd.Series): Series of 'close's
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
@@ -8,11 +8,13 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def wma(close, length=None, asc=None, offset=None, **kwargs):
|
||||
"""Indicator: Weighted Moving Average (WMA)"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 10
|
||||
asc = asc if asc else True
|
||||
close = verify_series(close, length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
total_weight = 0.5 * length * (length + 1)
|
||||
weights_ = Series(npArange(1, length + 1))
|
||||
@@ -62,9 +64,9 @@ Calculation:
|
||||
|
||||
Args:
|
||||
close (pd.Series): Series of 'close's
|
||||
length (int): It's period. Default: 10
|
||||
asc (bool): Recent values weigh more. Default: True
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
length (int): It's period. Default: 10
|
||||
asc (bool): Recent values weigh more. Default: True
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
@@ -8,10 +8,12 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def zlma(close, length=None, mamode=None, offset=None, **kwargs):
|
||||
"""Indicator: Zero Lag Moving Average (ZLMA)"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 10
|
||||
offset = get_offset(offset)
|
||||
mamode = mamode.lower() if isinstance(mamode, str) else "ema"
|
||||
close = verify_series(close, length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
lag = int(0.5 * (length - 1))
|
||||
@@ -60,9 +62,9 @@ Calculation:
|
||||
|
||||
Args:
|
||||
close (pd.Series): Series of 'close's
|
||||
length (int): It's period. Default: 10
|
||||
mamode (str): Options: 'ema', 'hma', 'sma', 'wma'. Default: 'ema'
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
length (int): It's period. Default: 10
|
||||
mamode (str): Options: 'ema', 'hma', 'sma', 'wma'. Default: 'ema'
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
@@ -6,10 +6,12 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def log_return(close, length=None, cumulative=False, offset=None, **kwargs):
|
||||
"""Indicator: Log Return"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 1
|
||||
close = verify_series(close, length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
log_return = nplog(close).diff(periods=length)
|
||||
|
||||
@@ -50,9 +52,9 @@ Calculation:
|
||||
|
||||
Args:
|
||||
close (pd.Series): Series of 'close's
|
||||
length (int): It's period. Default: 20
|
||||
cumulative (bool): If True, returns the cumulative returns. Default: False
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
length (int): It's period. Default: 20
|
||||
cumulative (bool): If True, returns the cumulative returns. Default: False
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
@@ -5,10 +5,12 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def percent_return(close, length=None, cumulative=False, offset=None, **kwargs):
|
||||
"""Indicator: Percent Return"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 1
|
||||
close = verify_series(close, length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
pct_return = close.pct_change(length)
|
||||
|
||||
@@ -43,9 +45,9 @@ Calculation:
|
||||
|
||||
Args:
|
||||
close (pd.Series): Series of 'close's
|
||||
length (int): It's period. Default: 20
|
||||
cumulative (bool): If True, returns the cumulative returns. Default: False
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
length (int): It's period. Default: 20
|
||||
cumulative (bool): If True, returns the cumulative returns. Default: False
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from pandas import DataFrame, Series
|
||||
from pandas import DataFrame
|
||||
from .log_return import log_return
|
||||
from .percent_return import percent_return
|
||||
from pandas_ta.utils import get_offset, verify_series, zero
|
||||
@@ -12,7 +12,8 @@ def trend_return(close, trend, log=True, cumulative=None, trend_reset=0, trade_o
|
||||
trend = verify_series(trend)
|
||||
cumulative = cumulative if cumulative is not None and isinstance(cumulative, bool) else False
|
||||
trend_reset = int(trend_reset) if trend_reset and isinstance(trend_reset, int) else 0
|
||||
trade_offset = int(trade_offset) if trade_offset and isinstance(trade_offset, int) else -1
|
||||
if trade_offset !=0:
|
||||
trade_offset = int(trade_offset) if trade_offset and isinstance(trade_offset, int) else -1
|
||||
offset = get_offset(offset)
|
||||
|
||||
# Calculate Result
|
||||
|
||||
@@ -6,11 +6,13 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def entropy(close, length=None, base=None, offset=None, **kwargs):
|
||||
"""Indicator: Entropy (ENTP)"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 10
|
||||
base = float(base) if base and base > 0 else 2.0
|
||||
close = verify_series(close, length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
p = close / close.rolling(length).sum()
|
||||
entropy = (-p * npLog(p) / npLog(base)).rolling(length).sum()
|
||||
|
||||
@@ -5,11 +5,13 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def kurtosis(close, length=None, offset=None, **kwargs):
|
||||
"""Indicator: Kurtosis"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 30
|
||||
min_periods = int(kwargs["min_periods"]) if "min_periods" in kwargs and kwargs["min_periods"] is not None else length
|
||||
close = verify_series(close, max(length, min_periods))
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
kurtosis = close.rolling(length, min_periods=min_periods).kurt()
|
||||
|
||||
|
||||
@@ -6,11 +6,13 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def mad(close, length=None, offset=None, **kwargs):
|
||||
"""Indicator: Mean Absolute Deviation"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 30
|
||||
min_periods = int(kwargs["min_periods"]) if "min_periods" in kwargs and kwargs["min_periods"] is not None else length
|
||||
close = verify_series(close, max(length, min_periods))
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
def mad_(series):
|
||||
"""Mean Absolute Deviation"""
|
||||
|
||||
@@ -5,11 +5,13 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def median(close, length=None, offset=None, **kwargs):
|
||||
"""Indicator: Median"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 30
|
||||
min_periods = int(kwargs["min_periods"]) if "min_periods" in kwargs and kwargs["min_periods"] is not None else length
|
||||
close = verify_series(close, max(length, min_periods))
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
median = close.rolling(length, min_periods=min_periods).median()
|
||||
|
||||
@@ -27,7 +29,7 @@ def median(close, length=None, offset=None, **kwargs):
|
||||
median.__doc__ = \
|
||||
"""Rolling Median
|
||||
|
||||
Rolling Median of over 'n' periods. Sibling of a Simple Moving Average.
|
||||
Rolling Median of over 'n' periods. Sibling of a Simple Moving Average.
|
||||
|
||||
Sources:
|
||||
https://www.incrediblecharts.com/indicators/median_price.php
|
||||
|
||||
@@ -5,12 +5,14 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def quantile(close, length=None, q=None, offset=None, **kwargs):
|
||||
"""Indicator: Quantile"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 30
|
||||
min_periods = int(kwargs["min_periods"]) if "min_periods" in kwargs and kwargs["min_periods"] is not None else length
|
||||
q = float(q) if q and q > 0 and q < 1 else 0.5
|
||||
close = verify_series(close, max(length, min_periods))
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
quantile = close.rolling(length, min_periods=min_periods).quantile(q)
|
||||
|
||||
|
||||
@@ -5,11 +5,13 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def skew(close, length=None, offset=None, **kwargs):
|
||||
"""Indicator: Skew"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 30
|
||||
min_periods = int(kwargs["min_periods"]) if "min_periods" in kwargs and kwargs["min_periods"] is not None else length
|
||||
close = verify_series(close, max(length, min_periods))
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
skew = close.rolling(length, min_periods=min_periods).skew()
|
||||
|
||||
|
||||
@@ -7,11 +7,13 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def stdev(close, length=None, ddof=1, offset=None, **kwargs):
|
||||
"""Indicator: Standard Deviation"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 30
|
||||
ddof = int(ddof) if ddof >= 0 and ddof < length else 1
|
||||
close = verify_series(close, length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
stdev = variance(close=close, length=length, ddof=ddof).apply(npsqrt)
|
||||
|
||||
|
||||
@@ -5,13 +5,14 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def variance(close, length=None, ddof=None, offset=None, **kwargs):
|
||||
"""Indicator: Variance"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 1 else 30
|
||||
ddof = int(ddof) if ddof and ddof >= 0 and ddof < length else 0
|
||||
|
||||
min_periods = int(kwargs["min_periods"]) if "min_periods" in kwargs and kwargs["min_periods"] is not None else length
|
||||
close = verify_series(close, max(length, min_periods))
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
variance = close.rolling(length, min_periods=min_periods).var(ddof)
|
||||
|
||||
|
||||
@@ -7,11 +7,13 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def zscore(close, length=None, std=None, offset=None, **kwargs):
|
||||
"""Indicator: Z Score"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 1 else 30
|
||||
std = float(std) if std and std > 1 else 1
|
||||
close = verify_series(close, length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
std *= stdev(close=close, length=length, **kwargs)
|
||||
mean = sma(close=close, length=length, **kwargs)
|
||||
|
||||
+11
-8
@@ -1,21 +1,24 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from pandas import DataFrame
|
||||
from pandas_ta.overlap import rma
|
||||
from pandas_ta.overlap import ma
|
||||
from pandas_ta.volatility import atr
|
||||
from pandas_ta.utils import get_drift, get_offset, verify_series, zero
|
||||
|
||||
|
||||
def adx(high, low, close, length=None, scalar=None, drift=None, offset=None, **kwargs):
|
||||
def adx(high, low, close, length=None, scalar=None, mamode=None, drift=None, offset=None, **kwargs):
|
||||
"""Indicator: ADX"""
|
||||
# Validate Arguments
|
||||
high = verify_series(high)
|
||||
low = verify_series(low)
|
||||
close = verify_series(close)
|
||||
length = length if length and length > 0 else 14
|
||||
mamode = mamode if isinstance(mamode, str) else "rma"
|
||||
scalar = float(scalar) if scalar else 100
|
||||
high = verify_series(high, length)
|
||||
low = verify_series(low, length)
|
||||
close = verify_series(close, length)
|
||||
drift = get_drift(drift)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if high is None or low is None or close is None: return
|
||||
|
||||
# Calculate Result
|
||||
atr_ = atr(high=high, low=low, close=close, length=length)
|
||||
|
||||
@@ -29,11 +32,11 @@ def adx(high, low, close, length=None, scalar=None, drift=None, offset=None, **k
|
||||
neg = neg.apply(zero)
|
||||
|
||||
k = scalar / atr_
|
||||
dmp = k * rma(close=pos, length=length)
|
||||
dmn = k * rma(close=neg, length=length)
|
||||
dmp = k * ma(mamode, pos, length=length)
|
||||
dmn = k * ma(mamode, neg, length=length)
|
||||
|
||||
dx = scalar * (dmp - dmn).abs() / (dmp + dmn)
|
||||
adx = rma(close=dx, length=length)
|
||||
adx = ma(mamode, dx, length=length)
|
||||
|
||||
# Offset
|
||||
if offset != 0:
|
||||
|
||||
@@ -6,15 +6,18 @@ from pandas_ta.overlap import ma
|
||||
from pandas_ta.utils import get_offset, verify_series
|
||||
|
||||
|
||||
def amat(close=None, fast=None, slow=None, mamode=None, lookback=None, offset=None, **kwargs):
|
||||
def amat(close=None, fast=None, slow=None, mamode=None, lookback=None, slope_length=None, offset=None, **kwargs):
|
||||
"""Indicator: Archer Moving Averages Trends (AMAT)"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
fast = int(fast) if fast and fast > 0 else 8
|
||||
slow = int(slow) if slow and slow > 0 else 21
|
||||
lookback = int(lookback) if lookback and lookback > 0 else 2
|
||||
mamode = mamode if isinstance(mamode, str) else "ema"
|
||||
mamode = mamode.lower() if isinstance(mamode, str) else "ema"
|
||||
close = verify_series(close, max(fast, slow, lookback))
|
||||
offset = get_offset(offset)
|
||||
if "length" in kwargs: kwargs.pop("length")
|
||||
|
||||
if close is None: return
|
||||
|
||||
# # Calculate Result
|
||||
fast_ma = ma(mamode, close, length=fast, **kwargs)
|
||||
@@ -38,10 +41,9 @@ def amat(close=None, fast=None, slow=None, mamode=None, lookback=None, offset=No
|
||||
mas_short.fillna(method=kwargs["fill_method"], inplace=True)
|
||||
|
||||
# Prepare DataFrame to return
|
||||
_lmode = mamode.lower()[0]
|
||||
amatdf = DataFrame({
|
||||
f"AMAT{_lmode}_{mas_long.name}": mas_long,
|
||||
f"AMAT{_lmode}_{mas_short.name}": mas_short
|
||||
f"AMAT{mamode[0]}_{mas_long.name}": mas_long,
|
||||
f"AMAT{mamode[0]}_{mas_short.name}": mas_short
|
||||
})
|
||||
|
||||
# Name and Categorize it
|
||||
|
||||
@@ -7,12 +7,14 @@ from pandas_ta.utils import recent_maximum_index, recent_minimum_index
|
||||
def aroon(high, low, length=None, scalar=None, offset=None, **kwargs):
|
||||
"""Indicator: Aroon & Aroon Oscillator"""
|
||||
# Validate Arguments
|
||||
high = verify_series(high)
|
||||
low = verify_series(low)
|
||||
length = length if length and length > 0 else 14
|
||||
scalar = float(scalar) if scalar else 100
|
||||
high = verify_series(high, length)
|
||||
low = verify_series(low, length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if high is None or low is None: return
|
||||
|
||||
# Calculate Result
|
||||
periods_from_hh = high.rolling(length + 1).apply(recent_maximum_index, raw=True)
|
||||
periods_from_ll = low.rolling(length + 1).apply(recent_minimum_index, raw=True)
|
||||
|
||||
+11
-11
@@ -1,6 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from numpy import log10 as npLog10
|
||||
from pandas import DataFrame
|
||||
from pandas_ta.volatility import atr
|
||||
from pandas_ta.utils import get_offset, get_drift, verify_series
|
||||
|
||||
@@ -8,16 +7,17 @@ from pandas_ta.utils import get_offset, get_drift, verify_series
|
||||
def chop(high, low, close, length=None, atr_length=None, scalar=None, drift=None, offset=None, **kwargs):
|
||||
"""Indicator: Choppiness Index (CHOP)"""
|
||||
# Validate Arguments
|
||||
high = verify_series(high)
|
||||
low = verify_series(low)
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 14
|
||||
atr_length = int(
|
||||
atr_length) if atr_length is not None and atr_length > 0 else 1
|
||||
atr_length = int(atr_length) if atr_length is not None and atr_length > 0 else 1
|
||||
scalar = float(scalar) if scalar else 100
|
||||
high = verify_series(high, length)
|
||||
low = verify_series(low, length)
|
||||
close = verify_series(close, length)
|
||||
drift = get_drift(drift)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if high is None or low is None or close is None: return
|
||||
|
||||
# Calculate Result
|
||||
diff = high.rolling(length).max() - low.rolling(length).min()
|
||||
|
||||
@@ -71,11 +71,11 @@ Args:
|
||||
high (pd.Series): Series of 'high's
|
||||
low (pd.Series): Series of 'low's
|
||||
close (pd.Series): Series of 'close's
|
||||
length (int): It's period. Default: 14
|
||||
atr_length (int): Length for ATR. Default: 1
|
||||
scalar (float): How much to magnify. Default: 100
|
||||
drift (int): The difference period. Default: 1
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
length (int): It's period. Default: 14
|
||||
atr_length (int): Length for ATR. Default: 1
|
||||
scalar (float): How much to magnify. Default: 100
|
||||
drift (int): The difference period. Default: 1
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
+13
-11
@@ -7,14 +7,17 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def cksp(high, low, close, p=None, x=None, q=None, offset=None, **kwargs):
|
||||
"""Indicator: Chande Kroll Stop (CKSP)"""
|
||||
# Validate Arguments
|
||||
high = verify_series(high)
|
||||
low = verify_series(low)
|
||||
close = verify_series(close)
|
||||
p = int(p) if p and p > 0 else 10
|
||||
x = float(x) if x and x > 0 else 1
|
||||
q = int(q) if q and q > 0 else 9
|
||||
_length = max(p, q, x)
|
||||
high = verify_series(high, _length)
|
||||
low = verify_series(low, _length)
|
||||
close = verify_series(close, _length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if high is None or low is None or close is None: return
|
||||
|
||||
# Calculate Result
|
||||
atr_ = atr(high=high, low=low, close=close, length=p)
|
||||
|
||||
@@ -54,10 +57,9 @@ def cksp(high, low, close, p=None, x=None, q=None, offset=None, **kwargs):
|
||||
cksp.__doc__ = \
|
||||
"""Chande Kroll Stop (CKSP)
|
||||
|
||||
The Tushar Chande and Stanley Kroll in their book
|
||||
“The New Technical Trader”. It is a trend-following indicator,
|
||||
identifying your stop by calculating the average true range of
|
||||
the recent market volatility.
|
||||
The Tushar Chande and Stanley Kroll in their book “The New Technical Trader”.
|
||||
It is a trend-following indicator, identifying your stop by calculating the
|
||||
average true range of the recent market volatility.
|
||||
|
||||
Sources:
|
||||
https://www.multicharts.com/discussion/viewtopic.php?t=48914
|
||||
@@ -75,10 +77,10 @@ Calculation:
|
||||
|
||||
Args:
|
||||
close (pd.Series): Series of 'close's
|
||||
p (int): ATR and first stop period. Default: 10
|
||||
x (float): ATR scalar. Default: 1
|
||||
q (int): Second stop period. Default: 9
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
p (int): ATR and first stop period. Default: 10
|
||||
x (float): ATR scalar. Default: 1
|
||||
q (int): Second stop period. Default: 9
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from math import exp
|
||||
from numpy import exp as npExp
|
||||
from pandas import DataFrame
|
||||
from pandas_ta.utils import get_offset, verify_series
|
||||
|
||||
@@ -7,16 +7,18 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def decay(close, kind=None, length=None, mode=None, offset=None, **kwargs):
|
||||
"""Indicator: Decay"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 5
|
||||
mode = mode.lower() if isinstance(mode, str) else "linear"
|
||||
close = verify_series(close, length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
_mode = "L"
|
||||
if mode == "exp" or kind == "exponential":
|
||||
_mode = "EXP"
|
||||
diff = close.shift(1) - exp(-length)
|
||||
diff = close.shift(1) - npExp(-length)
|
||||
else: # "linear"
|
||||
diff = close.shift(1) - (1 / length)
|
||||
diff[0] = close[0]
|
||||
|
||||
@@ -5,19 +5,22 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def decreasing(close, length=None, strict=None, asint=None, offset=None, **kwargs):
|
||||
"""Indicator: Decreasing"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 1
|
||||
strict = strict if isinstance(strict, bool) else False
|
||||
asint = asint if isinstance(asint, bool) else True
|
||||
close = verify_series(close, length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
def stricly_decreasing(series, n):
|
||||
return all([i > j for i,j in zip(series[-n:], series[1:])])
|
||||
|
||||
# Calculate Result
|
||||
if strict:
|
||||
# Returns value as float64? Have to cast to bool
|
||||
decreasing = close.rolling(length, min_periods=length).apply(stricly_decreasing, args=(length,), raw=False)
|
||||
decreasing = close.rolling(length, min_periods=length) \
|
||||
.apply(stricly_decreasing, args=(length,), raw=False)
|
||||
decreasing.fillna(0, inplace=True)
|
||||
decreasing = decreasing.astype(bool)
|
||||
else:
|
||||
@@ -46,7 +49,10 @@ def decreasing(close, length=None, strict=None, asint=None, offset=None, **kwarg
|
||||
decreasing.__doc__ = \
|
||||
"""Decreasing
|
||||
|
||||
Returns True if the series is decreasing over a period, False otherwise. If the kwarg 'strict' is True, it returns True if it is continuously decreasing over the period. When using the kwarg 'asint', then it returns 1 for True or 0 for False.
|
||||
Returns True if the series is decreasing over a period, False otherwise.
|
||||
If the kwarg 'strict' is True, it returns True if it is continuously decreasing
|
||||
over the period. When using the kwarg 'asint', then it returns 1 for True
|
||||
or 0 for False.
|
||||
|
||||
Calculation:
|
||||
if strict:
|
||||
|
||||
@@ -6,10 +6,12 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def dpo(close, length=None, centered=True, offset=None, **kwargs):
|
||||
"""Indicator: Detrend Price Oscillator (DPO)"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 20
|
||||
close = verify_series(close, length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
# Calculate Result
|
||||
t = int(0.5 * length) + 1
|
||||
ma = sma(close, length)
|
||||
@@ -58,9 +60,9 @@ Calculation:
|
||||
|
||||
Args:
|
||||
close (pd.Series): Series of 'close's
|
||||
length (int): It's period. Default: 1
|
||||
centered (bool): Shift the dpo back by int(0.5 * length) + 1. Default: True
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
length (int): It's period. Default: 1
|
||||
centered (bool): Shift the dpo back by int(0.5 * length) + 1. Default: True
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
fillna (value, optional): pd.DataFrame.fillna(value)
|
||||
|
||||
@@ -5,19 +5,22 @@ from pandas_ta.utils import get_offset, verify_series
|
||||
def increasing(close, length=None, strict=None, asint=None, offset=None, **kwargs):
|
||||
"""Indicator: Increasing"""
|
||||
# Validate Arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 1
|
||||
strict = strict if isinstance(strict, bool) else False
|
||||
asint = asint if isinstance(asint, bool) else True
|
||||
close = verify_series(close, length)
|
||||
offset = get_offset(offset)
|
||||
|
||||
if close is None: return
|
||||
|
||||
def stricly_increasing(series, n):
|
||||
return all([i < j for i,j in zip(series[-n:], series[1:])])
|
||||
|
||||
# Calculate Result
|
||||
if strict:
|
||||
# Returns value as float64? Have to cast to bool
|
||||
increasing = close.rolling(length, min_periods=length).apply(stricly_increasing, args=(length,), raw=False)
|
||||
increasing = close.rolling(length, min_periods=length) \
|
||||
.apply(stricly_increasing, args=(length,), raw=False)
|
||||
increasing.fillna(0, inplace=True)
|
||||
increasing = increasing.astype(bool)
|
||||
else:
|
||||
@@ -46,7 +49,10 @@ def increasing(close, length=None, strict=None, asint=None, offset=None, **kwarg
|
||||
increasing.__doc__ = \
|
||||
"""Increasing
|
||||
|
||||
Returns True if the series is increasing over a period, False otherwise. If the kwarg 'strict' is True, it returns True if it is continuously increasing over the period. When using the kwarg 'asint', then it returns 1 for True or 0 for False.
|
||||
Returns True if the series is increasing over a period, False otherwise.
|
||||
If the kwarg 'strict' is True, it returns True if it is continuously increasing
|
||||
over the period. When using the kwarg 'asint', then it returns 1 for True
|
||||
or 0 for False.
|
||||
|
||||
Calculation:
|
||||
if strict:
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user