REF: Add Straetgy.data.<array>.to_series() method

This commit is contained in:
Kernc
2019-01-15 11:30:02 +01:00
parent 7711732612
commit b157c48a3c
6 changed files with 16 additions and 14 deletions

View File

@@ -2,6 +2,7 @@
from numbers import Number
import numpy as np
import pandas as pd
def _as_str(value):
@@ -52,6 +53,9 @@ class _Array(np.ndarray):
except IndexError:
return super().__float__()
def to_series(self):
return pd.Series(self, index=self._opts['data'].index, name=self.name)
class _Indicator(_Array):
pass

View File

@@ -231,7 +231,9 @@ class Strategy(metaclass=ABCMeta):
`backtesting.backtesting.Backtest` internally),
the last array value (e.g. `data.Close[-1]`)
is always the _most recent_ value.
* If you need data arrays (e.g. `data.Close`) to be indexed
Pandas series, you can call their `.to_series()` method
(e.g. `data.Close.to_series()`).
"""
return self._data

View File

@@ -22,7 +22,7 @@ import pandas as pd
from .backtesting import Strategy
from ._plotting import plot_heatmaps as _plot_heatmaps
from ._util import _Indicator, _as_str
from ._util import _Array, _Indicator, _as_str
OHLCV_AGG = OrderedDict((
@@ -175,9 +175,7 @@ def resample_apply(rule: str,
def init(self):
# Strategy exposes `self.data` as raw NumPy arrays.
# Let's convert closing prices back to pandas Series.
close = pd.Series(self.data.Close,
index=self.data.index,
name='Close')
close = self.data.Close.to_series()
# Resample to daily resolution. Aggregate groups
# using their last value (i.e. closing price at the end
@@ -200,9 +198,9 @@ def resample_apply(rule: str,
"""
if not isinstance(series, pd.Series):
series = pd.Series(series,
index=series._opts['data'].index,
name=series.name)
assert isinstance(series, _Array), \
'resample_apply() takes either a `pd.Series` or a `Strategy.data.*` array'
series = series.to_series()
resampled = series.resample(rule, label='right').agg('last').dropna()
resampled.name = _as_str(series) + '[' + rule + ']'

View File

@@ -456,7 +456,7 @@ class TestLib(TestCase):
def test_SignalStrategy(self):
class S(SignalStrategy):
def init(self):
sma = pd.Series(self.data.Close).rolling(10).mean()
sma = self.data.Close.to_series().rolling(10).mean()
self.set_signal(self.data.Close > sma,
self.data.Close < sma)
@@ -469,9 +469,7 @@ class TestLib(TestCase):
super().init()
self.set_atr_periods(40)
self.set_trailing_sl(3)
self.sma = self.I(
lambda: pd.Series(self.data.Close,
index=self.data.index).rolling(10).mean())
self.sma = self.I(lambda: self.data.Close.to_series().rolling(10).mean())
def next(self):
super().next()

View File

@@ -563,7 +563,7 @@
"\n",
"In `init()`, the whole series of points was available, whereas **in `next()`, the length of `self.data` and any declared indicator arrays is adjusted** on each `next()` call so that `array[-1]` (e.g. `self.data.Close[-1]` or `self.sma1[-1]`) always contains the most recent value, `array[-2]` the previous value, etc. (ordinary Python indexing of ascending-sorted 1D arrays).\n",
"\n",
"**Note**: `self.data` and any indicators wrapped with `self.I` (e.g. `self.sma1`) are **NumPy arrays** for performance reasons. If you need `pandas.Series`, use, e.g., `pd.Series(self.data.Close, index=self.data.index)`.\n",
"**Note**: `self.data` and any indicators wrapped with `self.I` (e.g. `self.sma1`) are **NumPy arrays for performance reasons**. If you need `pandas.Series`, use `.to_series()` method (e.g. `self.data.Close.to_series()`) or construct the series manually (e.g. `pd.Series(self.data.Close, index=self.data.index)`).\n",
"\n",
"Let's see how our strategy performs on historical Google data. We begin with 10,000 units of cash and set broker's commission to realistic 0.2%."
]

View File

@@ -127,7 +127,7 @@ class SmaCross(Strategy):
#
# In `init()`, the whole series of points was available, whereas **in `next()`, the length of `self.data` and any declared indicator arrays is adjusted** on each `next()` call so that `array[-1]` (e.g. `self.data.Close[-1]` or `self.sma1[-1]`) always contains the most recent value, `array[-2]` the previous value, etc. (ordinary Python indexing of ascending-sorted 1D arrays).
#
# **Note**: `self.data` and any indicators wrapped with `self.I` (e.g. `self.sma1`) are **NumPy arrays** for performance reasons. If you need `pandas.Series`, use, e.g., `pd.Series(self.data.Close, index=self.data.index)`.
# **Note**: `self.data` and any indicators wrapped with `self.I` (e.g. `self.sma1`) are **NumPy arrays for performance reasons**. If you need `pandas.Series`, use `.to_series()` method (e.g. `self.data.Close.to_series()`) or construct the series manually (e.g. `pd.Series(self.data.Close, index=self.data.index)`).
#
# Let's see how our strategy performs on historical Google data. We begin with 10,000 units of cash and set broker's commission to realistic 0.2%.