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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
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 件のコメント:
コメントを投稿