Files
Bithumb/deepcoin/analysis/general_analysis_candles.py
dsyoon b52d61b777 WLD DeepCoin 단계별 구조 재편 및 설정·문서 통합
로고스/루트 레거시를 제거하고 deepcoin 패키지·scripts 01~05 CLI·docs/reference로
데이터·GT·분석·매칭·운영 단계를 정리했다. config와 .env 기반 설정, trade_anaysis.html 동기화 포함.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-30 22:58:25 +09:00

115 lines
3.4 KiB
Python

"""
general_analysis 캔들·차트 변환 (Heikin-Ashi, 복수봉 패턴).
"""
from __future__ import annotations
import numpy as np
import pandas as pd
from deepcoin.analysis.general_analysis_core import ga_col
def general_analysis_apply_candles(df: pd.DataFrame) -> pd.DataFrame:
"""
단일·복수 봉 캔들 패턴 및 Heikin-Ashi 컬럼 추가.
Args:
df: OHLCV.
Returns:
ga_* 캔들 컬럼이 추가된 DataFrame.
"""
out = df.copy()
o = out["Open"].astype(float)
h = out["High"].astype(float)
l = out["Low"].astype(float)
c = out["Close"].astype(float)
rng = (h - l).replace(0, np.nan)
body = (c - o).abs()
out[ga_col("body_ratio")] = (body / rng).fillna(0).clip(0, 1)
upper_wick = h - np.maximum(o, c)
lower_wick = np.minimum(o, c) - l
out[ga_col("upper_wick_ratio")] = (upper_wick / rng).fillna(0).clip(0, 1)
out[ga_col("lower_wick_ratio")] = (lower_wick / rng).fillna(0).clip(0, 1)
out[ga_col("bullish")] = (c > o).astype(int)
out[ga_col("bearish")] = (c < o).astype(int)
out[ga_col("hammer")] = (
(out[ga_col("lower_wick_ratio")] > 0.45) & (out[ga_col("body_ratio")] < 0.35)
).astype(int)
out[ga_col("shooting_star")] = (
(out[ga_col("upper_wick_ratio")] > 0.45) & (out[ga_col("body_ratio")] < 0.35)
).astype(int)
out[ga_col("doji")] = (out[ga_col("body_ratio")] < 0.1).astype(int)
prev_o, prev_c = o.shift(1), c.shift(1)
out[ga_col("bullish_engulfing")] = (
(c > o) & (prev_c < prev_o) & (c >= prev_o) & (o <= prev_c)
).astype(int)
out[ga_col("bearish_engulfing")] = (
(c < o) & (prev_c > prev_o) & (c <= prev_o) & (o >= prev_c)
).astype(int)
o2, c2 = o.shift(2), c.shift(2)
mid1 = (o.shift(1) + c.shift(1)) / 2
out[ga_col("morning_star")] = (
(c2 < o2)
& (abs(c.shift(1) - o.shift(1)) < rng.shift(1) * 0.15)
& (c > o)
& (c > mid1)
).astype(int)
out[ga_col("evening_star")] = (
(c2 > o2)
& (abs(c.shift(1) - o.shift(1)) < rng.shift(1) * 0.15)
& (c < o)
& (c < mid1)
).astype(int)
out[ga_col("three_white_soldiers")] = (
(c > o)
& (c.shift(1) > o.shift(1))
& (c.shift(2) > o.shift(2))
& (c > c.shift(1))
& (c.shift(1) > c.shift(2))
).astype(int)
out[ga_col("three_black_crows")] = (
(c < o)
& (c.shift(1) < o.shift(1))
& (c.shift(2) < o.shift(2))
& (c < c.shift(1))
& (c.shift(1) < c.shift(2))
).astype(int)
# Heikin-Ashi
ha_close = (o + h + l + c) / 4
ha_open = ha_close.copy()
ha_open.iloc[0] = (o.iloc[0] + c.iloc[0]) / 2
for i in range(1, len(out)):
ha_open.iloc[i] = (ha_open.iloc[i - 1] + ha_close.iloc[i - 1]) / 2
out[ga_col("ha_close")] = ha_close
out[ga_col("ha_open")] = ha_open
out[ga_col("ha_bull")] = (ha_close > ha_open).astype(int)
out[ga_col("ha_trend_up")] = (
(ha_close > ha_close.shift(1)) & (ha_close.shift(1) > ha_close.shift(2))
).astype(int)
return out
def general_analysis_candle_columns() -> list[str]:
return [
"body_ratio",
"hammer",
"shooting_star",
"doji",
"bullish_engulfing",
"bearish_engulfing",
"morning_star",
"evening_star",
"three_white_soldiers",
"three_black_crows",
"ha_bull",
"ha_trend_up",
]