mirror of
https://github.com/wassname/pandas-ta.git
synced 2026-09-10 12:23:49 +08:00
ENH bbands #202 ENH core added ordered and chunksize args ENH chunksize optimizing
This commit is contained in:
@@ -83,7 +83,7 @@ $ pip install pandas_ta
|
||||
|
||||
Latest Version
|
||||
--------------
|
||||
Best choice! Version: *0.2.45b*
|
||||
Best choice! Version: *0.2.47b*
|
||||
```sh
|
||||
$ pip install -U git+https://github.com/twopirllc/pandas-ta
|
||||
```
|
||||
@@ -715,6 +715,7 @@ article in the June, 1994 issue of Technical Analysis of Stocks & Commodities Ma
|
||||
|
||||
## **Updated Indicators**
|
||||
* _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.
|
||||
|
||||
+20
-10
@@ -1,6 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from dataclasses import dataclass, field
|
||||
from datetime import datetime
|
||||
from math import log as mlog
|
||||
from multiprocessing import cpu_count, Pool
|
||||
from time import perf_counter
|
||||
from typing import List, Tuple
|
||||
@@ -582,6 +583,8 @@ class AnalysisIndicators(BasePandasObject):
|
||||
# cpus = cpu_count()
|
||||
# Ensure indicators are appended to the DataFrame
|
||||
kwargs["append"] = True
|
||||
all_ordered = kwargs.pop("ordered", False)
|
||||
mp_chunksize = kwargs.pop("chunksize", self.cores)
|
||||
|
||||
# Initialize
|
||||
initial_column_count = len(self._df.columns)
|
||||
@@ -657,11 +660,14 @@ class AnalysisIndicators(BasePandasObject):
|
||||
use_multiprocessing = False
|
||||
|
||||
if use_multiprocessing:
|
||||
if verbose:
|
||||
print(f"[i] Multiprocessing: {self.cores} of {cpu_count()} cores.")
|
||||
|
||||
_total_ta = len(ta)
|
||||
pool = Pool(self.cores)
|
||||
# Some magic to optimize chunksize for speed based on total ta indicators
|
||||
_chunksize = mp_chunksize - 1 if mp_chunksize > _total_ta else int(mlog(_total_ta)) + 1
|
||||
if verbose:
|
||||
print(f"[i] Multiprocessing: {self.cores} of {cpu_count()} cores of {_total_ta} indicators.")
|
||||
|
||||
results = None
|
||||
if mode["custom"]:
|
||||
# Create a list of all the custom indicators into a list
|
||||
custom_ta = [(
|
||||
@@ -671,15 +677,21 @@ class AnalysisIndicators(BasePandasObject):
|
||||
) for ind in ta]
|
||||
# Custom multiprocessing pool. Must be ordered for Chained Strategies
|
||||
# May fix this to cpus if Chaining/Composition if it remains
|
||||
# inconsistent
|
||||
results = pool.imap(self._mp_worker, custom_ta, self.cores)
|
||||
results = pool.imap(self._mp_worker, custom_ta, _chunksize)
|
||||
else:
|
||||
default_ta = [(ind, tuple(), kwargs) for ind in ta]
|
||||
# All and Categorical multiprocessing pool. Speed over Order.
|
||||
results = pool.imap_unordered(self._mp_worker, default_ta, self.cores)
|
||||
# All and Categorical multiprocessing pool.
|
||||
if all_ordered:
|
||||
results = pool.imap(self._mp_worker, default_ta, _chunksize) # Order over Speed
|
||||
else:
|
||||
results = pool.imap_unordered(self._mp_worker, default_ta, _chunksize) # Speed over Order
|
||||
if results is None:
|
||||
print(f"[X] ta.strategy('{name}') has no results.")
|
||||
return
|
||||
|
||||
pool.close()
|
||||
pool.join()
|
||||
|
||||
else:
|
||||
# Without multiprocessing:
|
||||
if verbose:
|
||||
@@ -705,9 +717,7 @@ class AnalysisIndicators(BasePandasObject):
|
||||
|
||||
if verbose:
|
||||
print(f"[i] Total indicators: {len(ta)}")
|
||||
print(
|
||||
f"[i] Columns added: {len(self._df.columns) - initial_column_count}"
|
||||
)
|
||||
print(f"[i] Columns added: {len(self._df.columns) - initial_column_count}")
|
||||
if timed:
|
||||
print(f"[i] Runtime: {ftime}")
|
||||
|
||||
|
||||
@@ -5,21 +5,21 @@ from pandas_ta.statistics import stdev
|
||||
from pandas_ta.utils import get_offset, verify_series
|
||||
|
||||
|
||||
def bbands(close, length=None, std=None, mamode=None, offset=None, **kwargs):
|
||||
def bbands(close, length=None, std=None, mamode=None, ddof=0, offset=None, **kwargs):
|
||||
"""Indicator: Bollinger Bands (BBANDS)"""
|
||||
# Validate arguments
|
||||
close = verify_series(close)
|
||||
length = int(length) if length and length > 0 else 5
|
||||
std = float(std) if std and std > 0 else 2.0
|
||||
mamode = mamode if isinstance(mamode, str) else "sma"
|
||||
ddof = int(ddof) if ddof >= 0 and ddof < length else 1
|
||||
offset = get_offset(offset)
|
||||
|
||||
# Calculate Result
|
||||
standard_deviation = stdev(close=close, length=length)
|
||||
standard_deviation = stdev(close=close, length=length, ddof=ddof)
|
||||
deviations = std * standard_deviation
|
||||
|
||||
mid = ma(mamode, close, length=length, **kwargs)
|
||||
|
||||
lower = mid - deviations
|
||||
upper = mid + deviations
|
||||
|
||||
@@ -74,11 +74,11 @@ Sources:
|
||||
|
||||
Calculation:
|
||||
Default Inputs:
|
||||
length=5, std=2, mamode="sma"
|
||||
length=5, std=2, mamode="sma", ddof=0
|
||||
EMA = Exponential Moving Average
|
||||
SMA = Simple Moving Average
|
||||
STDEV = Standard Deviation
|
||||
stdev = STDEV(close, length)
|
||||
stdev = STDEV(close, length, ddof)
|
||||
if "ema":
|
||||
MID = EMA(close, length)
|
||||
else:
|
||||
@@ -94,6 +94,7 @@ Args:
|
||||
length (int): The short period. Default: 5
|
||||
std (int): The long period. Default: 2
|
||||
mamode (str): Two options: "sma" or "ema". Default: "sma"
|
||||
ddof (int): Degrees of Freedom to use. Default: 0
|
||||
offset (int): How many periods to offset the result. Default: 0
|
||||
|
||||
Kwargs:
|
||||
|
||||
@@ -18,7 +18,7 @@ setup(
|
||||
"pandas_ta.volatility",
|
||||
"pandas_ta.volume"
|
||||
],
|
||||
version=".".join(("0", "2", "46b")),
|
||||
version=".".join(("0", "2", "47b")),
|
||||
description=long_description,
|
||||
long_description=long_description,
|
||||
author="Kevin Johnson",
|
||||
|
||||
@@ -67,6 +67,11 @@ class TestStrategyMethods(TestCase):
|
||||
self.category = "All"
|
||||
self.data.ta.strategy(verbose=verbose, timed=strategy_timed)
|
||||
|
||||
def test_all_ordered(self):
|
||||
self.category = "All"
|
||||
self.data.ta.strategy(ordered=True, verbose=verbose, timed=strategy_timed)
|
||||
self.category = "All Ordered" # Rename for Speed Table
|
||||
|
||||
@skipUnless(verbose, "verbose mode only")
|
||||
def test_all_strategy(self):
|
||||
self.data.ta.strategy(pandas_ta.AllStrategy, verbose=verbose, timed=strategy_timed)
|
||||
@@ -76,12 +81,13 @@ class TestStrategyMethods(TestCase):
|
||||
self.category = "All"
|
||||
self.data.ta.strategy(self.category, verbose=verbose, timed=strategy_timed)
|
||||
|
||||
@skipUnless(verbose, "verbose mode only")
|
||||
# @skipUnless(verbose, "verbose mode only")
|
||||
def test_all_multiparams_strategy(self):
|
||||
self.category = "All"
|
||||
self.data.ta.strategy(self.category, length=10, verbose=verbose, timed=strategy_timed)
|
||||
self.data.ta.strategy(self.category, length=50, verbose=verbose, timed=strategy_timed)
|
||||
self.data.ta.strategy(self.category, fast=5, verbose=verbose, timed=strategy_timed)
|
||||
self.data.ta.strategy(self.category, fast=5, slow=10, verbose=verbose, timed=strategy_timed)
|
||||
self.category = "All Multiruns with diff Args" # Rename for Speed Table
|
||||
|
||||
# @skip
|
||||
def test_candles_category(self):
|
||||
|
||||
Reference in New Issue
Block a user