Pandas Dataframe に datetime インデックスを含む OHLC 価格データがあり、トレード エントリー シグナルをバックテストしています。
そのうちの 1 つは、以前の大幅な安値を破った買いエントリー パターンをマークすることです。正しく動作するコードを以下に記述しましたが、可能であれば、「FooBuy」列のベクトル関数を返すようにベクトル化したいと考えています。
最終的にはライブ システムでこのコードを使用することを計画しているため、データの変化に自動的に応答するベクトルを用意することは大きな利点となります。
誰でも何か提案できますか?
class FooBuy(PricePattern):
def df_apply(self, df):
if not ("SigLow" in df.columns):
df["SigLow"] = SigLow().df_apply(df) # correct pattern
df["SigLowBrokenAt"] = None
df["FooBuy"] = False
for date, row in df[df.SigLow].iterrows():
df_sorted_lows = df[date:].sort("Low", ascending=False)
df_later_and_lower = df_sorted_lows[df_sorted_lows.Low < row["Low"]]
if len(df_later_and_lower) > 0:
df["SigLowBrokenAt"].ix[date] = df_later_and_lower.ix[0].name
for date in df.SigLowBrokenAt.dropna():
df["FooBuy"].ix[date] = True
SigLow のコードは次のとおりです。
class PricePattern(object):
def __init__(self, shift=0, **kwargs):
self.shift = shift
def __repr__(self):
return "{0}({1})".format(self.__class__.__name__, "" if self.shift == 0 else "shift=\"{0}\"".format(self.shift))
def df_apply(self, df):
raise NotImplementedError()
class SigLow(PricePattern):
def __init__(self, **kwargs):
super(SigLow, self).__init__(**kwargs)
def df_apply(self, df):
return (df.Low.shift(self.shift) < df.Low.shift(self.shift + 1)) & \
(df.Low.shift(self.shift) < df.Low.shift(self.shift - 1))
合格するテストコードを次に示します。
class TestBase(unittest.TestCase):
def _create_df(self, data):
return 1 + pd.DataFrame(data, columns=['Open', 'High', 'Low', 'Close'],
index=pd.date_range('2/25/2013 06:00', periods=len(data),
freq='H')) / 100
def _assert_true_alone(self, series, index):
for i in arange(len(series)):
self.assertTrue(series[i] or (i not in index))
def _assert_all_false(self, series):
for i in arange(len(series)):
self.assertFalse(series[i])
class TestFooBuy(TestBase):
def test_matches(self):
data1 = [[48, 49, 34, 48],
[48, 50, 46, 48],
[47, 49, 38, 48], # SL
[48, 59, 48, 58],
[57, 57, 50, 54],
[53, 53, 36, 40], # FB
[39, 39, 29, 32]]
df = self._create_df(data1)
#df["FooBuy"] = FooBuy().df_apply(df) # correct pattern
FooBuy().df_apply(df)
self._assert_true_alone(df.SigLow, [2])
self._assert_true_alone(df.FooBuy, [5])
def test_does_not_match(self):
data1 = [[48, 49, 34, 48],
[48, 50, 46, 48],
[47, 49, 38, 48], # SL
[48, 59, 48, 58],
[57, 57, 42, 48], # SL
[48, 50, 43, 44],
[45, 52, 45, 51]]
df = self._create_df(data1)
#df["FooBuy"] = FooBuy().df_apply(df, config_defaults) # correct pattern
FooBuy().df_apply(df, config_defaults)
#print df
self._assert_true_alone(df.SigLow, [2, 4])
self._assert_all_false(df.FooBuy)