Realtime Parabolic SAR

2025-03-21 公開 / 2025-04-13 更新

Parabolic SAR は、値動きにトレンドがある局面で、相場のトレンド転換点を探る時に有効なテクニカル指標です。日足や週足のチャートで利用していますが、デイトレに応用しようとしたときに、反応の遅れがどうにも気になってしまいます。

そこで、ティックデータに対して Parabolic SAR を適用できるクラスを作成してみました。

下記の OS 環境で開発および動作確認をしています。

Fedora Linux 42 Workstation x86_64
Python 3.13.2
numpy 2.2.4
pandas 2.2.3

以下にティックデータに対して Parabolic SAR を算出するクラスを示しました。

rtpsar.py
import numpy as np
import pandas as pd
class RealTimePSAR:
"""
Realtime Parabolic SAR
検証用クラス
"""
__version__ = '1.3.0'
def __init__(self, af_init=0.000, af_step=0.001, af_max=0.01):
self.af_init = af_init
self.af_step = af_step
self.af_max = af_max
# トレンド反転したときの株価
self.baseline = np.nan
# クラス内で使用するデータフレーム
df = pd.DataFrame()
df.index.name = 'Datetime'
self.df = df.astype(float)
def add(self, dt1: pd.Timestamp, price1: float) -> int:
# データフレームの行数
r = len(self.df)
if r == 0:
# 最初は時刻と中立トレンドを記録
trend1 = 0
ep1 = np.nan
af1 = np.nan
psar1 = np.nan
else:
# 一つ前のデータをデータフレームから取得
dt0 = self.df.index[r - 1]
price0 = self.df.loc[dt0, 'Price']
trend0 = self.df.loc[dt0, 'TREND']
ep0 = self.df.loc[dt0, 'EP']
af0 = self.df.loc[dt0, 'AF']
psar0 = self.df.loc[dt0, 'PSAR']
if r == 1:
trend1 = self.trend_from_prices(price0, price1)
ep1 = price1
af1 = self.af_init
psar1 = price1
self.baseline = price1
elif trend0 == 0:
# トレンドが中立の時
trend1 = self.trend_from_prices(price0, price1)
ep1 = ep0
af1 = af0
psar1 = self.update_psar(ep1, af1, psar0)
self.baseline = price1
elif self.cmp_psar(trend0, price1, psar0):
# トレンド反転
trend1 = trend0 * -1
ep1 = price1
af1 = self.af_init
psar1 = ep0
self.baseline = price1
else:
# 同一トレンド
trend1 = trend0
if self.cmp_ep(trend0, price1, ep0):
# EP と AF の更新
ep1, af1 = self.update_ep_af(price1, af0)
else:
ep1 = ep0
af1 = af0
psar1 = self.update_psar(ep1, af1, psar0)
# データフレームに新たな行を追加
self.df.loc[dt1, 'Price'] = price1
self.df.loc[dt1, 'TREND'] = trend1
self.df.loc[dt1, 'EP'] = ep1
self.df.loc[dt1, 'AF'] = af1
self.df.loc[dt1, 'PSAR'] = psar1
self.df.loc[dt1, 'Baseline'] = self.baseline
# 現在のトレンドを返す
return trend1
@staticmethod
def cmp_psar(trend: int, price: float, psar: float) -> bool:
if 0 < trend:
if price < psar:
return True
else:
return False
else:
if psar < price:
return True
else:
return False
@staticmethod
def cmp_ep(trend: int, price: float, ep: float) -> bool:
if 0 < trend:
if ep < price:
return True
else:
return False
else:
if price < ep:
return True
else:
return False
def getPSAR(self) -> pd.DataFrame:
"""
PSAR のデータフレームを返す
:return: PSAR のデータフレーム
"""
return self.df
@staticmethod
def trend_from_prices(price0: float, price1: float) -> int:
"""
p0 と p1 を比較してトレンドを返す。
:param price0:
:param price1:
:return:
"""
if price0 < price1:
return 1
elif price1 < price0:
return -1
else:
return 0
def update_ep_af(self, price: float, af: float) -> tuple[float, float]:
"""
EP(極値)と AF(加速因数)の更新
:param price:
:param af:
:return:
"""
# EP の更新
ep_new = price
# AF の更新
if af < self.af_max - self.af_step:
af_new = af + self.af_step
else:
af_new = self.af_max
return ep_new, af_new
def update_psar(self, ep: float, af: float, psar: float) -> float:
"""
PSAR を AF で更新
:param ep:
:param af:
:param psar:
:return:
"""
return psar + af * (ep - psar)
view raw rtpsar.py hosted with ❤ by GitHub

Jupyter Lab で実行するデモプラグラムを用意しました。トレンドシグナルが変わったタイミングで単純にドテン売買をした場合において、含み損益がプラスになる部分を青系色、マイナスになる部分を赤系色で塗りつぶしています。

デモプログラムでは、下記の Excel 形式で保存されたティックデータを使用します。

デモ用ティックデータ tick_8306_20250313.xlsx
sample_rtpsar.ipynb
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 件のコメント:

コメントを投稿