mirror of
https://github.com/quachtinh113/main-fx.git
synced 2026-08-02 13:27:43 +00:00
rsi update
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
from __future__ import annotations
|
||||
import pandas as pd
|
||||
import pandas_ta as ta
|
||||
|
||||
class RSIMultiTimeframe:
|
||||
def __init__(self, rsi_period: int = 14, low: float = 30, high: float = 70, mid: float = 50):
|
||||
self.rsi_period = rsi_period
|
||||
self.low = low
|
||||
self.high = high
|
||||
self.mid = mid
|
||||
|
||||
def compute_rsi(self, df: pd.DataFrame, tf_name: str) -> pd.Series:
|
||||
# Trả về Series để tiết kiệm bộ nhớ thay vì DataFrame
|
||||
return ta.rsi(df["close"], length=self.rsi_period).rename(f"rsi_{tf_name}")
|
||||
|
||||
def align_timeframes(
|
||||
self,
|
||||
df_m15: pd.DataFrame,
|
||||
df_h1: pd.DataFrame,
|
||||
df_h4: pd.DataFrame,
|
||||
) -> pd.DataFrame:
|
||||
# Sắp xếp index để merge_asof hoạt động chính xác
|
||||
df_m15 = df_m15.sort_index()
|
||||
|
||||
# TÍNH RSI VÀ SHIFT 1 NẾN:
|
||||
# Việc shift(1) đảm bảo M15 chỉ sử dụng RSI của nến H1/H4 ĐÃ ĐÓNG HOÀN TOÀN
|
||||
rsi_h1 = self.compute_rsi(df_h1, "h1").shift(1)
|
||||
rsi_h4 = self.compute_rsi(df_h4, "h4").shift(1)
|
||||
rsi_m15 = self.compute_rsi(df_m15, "m15") # M15 không shift vì ta coi như trigger tại giá đóng nến M15
|
||||
|
||||
# Merge H1
|
||||
df = pd.merge_asof(
|
||||
df_m15,
|
||||
rsi_h1,
|
||||
left_index=True,
|
||||
right_index=True,
|
||||
direction="backward",
|
||||
)
|
||||
|
||||
# Merge H4
|
||||
df = pd.merge_asof(
|
||||
df,
|
||||
rsi_h4,
|
||||
left_index=True,
|
||||
right_index=True,
|
||||
direction="backward",
|
||||
)
|
||||
|
||||
df["rsi_m15"] = rsi_m15
|
||||
|
||||
# Bỏ qua các nến đầu tiên bị NaN do chưa đủ chu kỳ RSI
|
||||
return df.dropna(subset=["rsi_h4", "rsi_h1", "rsi_m15"])
|
||||
|
||||
def classify(self, df: pd.DataFrame) -> pd.DataFrame:
|
||||
df = df.copy()
|
||||
|
||||
# Thêm vùng đệm (Buffer) 52/48 để tránh nhiễu tại vùng 50
|
||||
df["trend"] = 0
|
||||
df.loc[df["rsi_h4"] > 52, "trend"] = 1
|
||||
df.loc[df["rsi_h4"] < 48, "trend"] = -1
|
||||
|
||||
df["bias"] = 0
|
||||
df.loc[df["rsi_h1"] > 50, "bias"] = 1
|
||||
df.loc[df["rsi_h1"] < 50, "bias"] = -1
|
||||
|
||||
# TRIGGER (M15) - Giữ nguyên logic Reversal của bạn vì nó rất tốt
|
||||
df["rsi_prev"] = df["rsi_m15"].shift(1)
|
||||
df["trigger_buy"] = (df["rsi_prev"] < self.low) & (df["rsi_m15"] >= self.low)
|
||||
df["trigger_sell"] = (df["rsi_prev"] > self.high) & (df["rsi_m15"] <= self.high)
|
||||
|
||||
return df
|
||||
|
||||
def generate_signal(self, df: pd.DataFrame) -> pd.DataFrame:
|
||||
df["signal"] = 0
|
||||
# Mua khi: H4 Trend tăng + H1 Bias tăng + M15 RSI cắt lên từ vùng Oversold
|
||||
buy_cond = (df["trend"] == 1) & (df["bias"] == 1) & df["trigger_buy"]
|
||||
# Bán khi: H4 Trend giảm + H1 Bias giảm + M15 RSI cắt xuống từ vùng Overbought
|
||||
sell_cond = (df["trend"] == -1) & (df["bias"] == -1) & df["trigger_sell"]
|
||||
|
||||
df.loc[buy_cond, "signal"] = 1
|
||||
df.loc[sell_cond, "signal"] = -1
|
||||
return df
|
||||
|
||||
def run(self, df_m15: pd.DataFrame, df_h1: pd.DataFrame, df_h4: pd.DataFrame) -> pd.DataFrame:
|
||||
df = self.align_timeframes(df_m15, df_h1, df_h4)
|
||||
df = self.classify(df)
|
||||
df = self.generate_signal(df)
|
||||
return df
|
||||
Reference in New Issue
Block a user