DEV Community

Swatantra goswami
Swatantra goswami

Posted on

CISD plot

!pip install ccxt plotly pandas -q
Enter fullscreen mode Exit fullscreen mode
# ============================================================
# Cell 2 — Fetch OHLCV Data (OKX + IST to match TradingView)
# ============================================================
import ccxt
import pandas as pd

exchange = ccxt.okx()
ohlcv = exchange.fetch_ohlcv("ENJ/USDT", timeframe="15m", limit=200)

df = pd.DataFrame(ohlcv, columns=["timestamp", "open", "high", "low", "close", "volume"])
df["timestamp"] = pd.to_datetime(df["timestamp"], unit="ms")

# ✅ Convert UTC → IST to match TradingView (India)
df["timestamp"] = df["timestamp"].dt.tz_localize("UTC").dt.tz_convert("Asia/Kolkata")

df.set_index("timestamp", inplace=True)

print(df.tail(5))
Enter fullscreen mode Exit fullscreen mode
# ============================================================
# Cell 3 — CISD Detection
# ============================================================
import numpy as np

def detect_swing_points(df, left=5, right=5):
    df["swing_high"] = False
    df["swing_low"]  = False

    for i in range(left, len(df) - right):
        window_high = df["high"].iloc[i - left: i + right + 1]
        window_low  = df["low"].iloc[i - left: i + right + 1]

        if df["high"].iloc[i] == window_high.max():
            df.at[df.index[i], "swing_high"] = True

        if df["low"].iloc[i] == window_low.min():
            df.at[df.index[i], "swing_low"] = True

    return df


def detect_cisd(df):
    """
    Bullish CISD → bias was bearish + close breaks ABOVE last swing high
    Bearish CISD → bias was bullish + close breaks BELOW last swing low
    """
    df = detect_swing_points(df)

    df["cisd_bullish"] = False
    df["cisd_bearish"] = False
    df["cisd_level"]   = np.nan

    bias = None
    swing_highs = []
    swing_lows  = []
    last_swing_high_price = None
    last_swing_low_price  = None

    for i in range(len(df)):
        row = df.iloc[i]

        if row["swing_high"]:
            if swing_highs:
                bias = "bullish" if row["high"] > swing_highs[-1] else "bearish"
            swing_highs.append(row["high"])
            last_swing_high_price = row["high"]

        if row["swing_low"]:
            if swing_lows:
                bias = "bearish" if row["low"] < swing_lows[-1] else "bullish"
            swing_lows.append(row["low"])
            last_swing_low_price = row["low"]

        # Bullish CISD
        if (bias == "bearish"
                and last_swing_high_price is not None
                and row["close"] > last_swing_high_price):
            df.at[df.index[i], "cisd_bullish"] = True
            df.at[df.index[i], "cisd_level"]   = last_swing_high_price
            bias = "bullish"

        # Bearish CISD
        elif (bias == "bullish"
                and last_swing_low_price is not None
                and row["close"] < last_swing_low_price):
            df.at[df.index[i], "cisd_bearish"] = True
            df.at[df.index[i], "cisd_level"]   = last_swing_low_price
            bias = "bearish"

    return df


df = detect_cisd(df)

bullish_cisd = df[df["cisd_bullish"]]
bearish_cisd = df[df["cisd_bearish"]]

print(f"✅ Bullish CISDs : {len(bullish_cisd)}")
print(f"🔻 Bearish CISDs : {len(bearish_cisd)}")

signals = df[df["cisd_bullish"] | df["cisd_bearish"]][
    ["open","high","low","close","cisd_bullish","cisd_bearish","cisd_level"]
]
print("\nRecent CISD Signals:")
print(signals.tail(5))
Enter fullscreen mode Exit fullscreen mode
# ============================================================
# Cell 4 — Chart Visualization
# ============================================================
import plotly.graph_objects as go

fig = go.Figure()

# Candlestick
fig.add_trace(go.Candlestick(
    x=df.index,
    open=df["open"],
    high=df["high"],
    low=df["low"],
    close=df["close"],
    name="ENJ/USDT",
    increasing_line_color="#26a69a",
    decreasing_line_color="#ef5350"
))

# Swing Highs
swing_h = df[df["swing_high"]]
fig.add_trace(go.Scatter(
    x=swing_h.index,
    y=swing_h["high"] * 1.001,
    mode="markers",
    marker=dict(symbol="triangle-down", size=8, color="orange"),
    name="Swing High"
))

# Swing Lows
swing_l = df[df["swing_low"]]
fig.add_trace(go.Scatter(
    x=swing_l.index,
    y=swing_l["low"] * 0.999,
    mode="markers",
    marker=dict(symbol="triangle-up", size=8, color="cyan"),
    name="Swing Low"
))

# Bullish CISD
fig.add_trace(go.Scatter(
    x=bullish_cisd.index,
    y=bullish_cisd["low"] * 0.998,
    mode="markers+text",
    marker=dict(symbol="star", size=14, color="lime"),
    text=["CISD↑"] * len(bullish_cisd),
    textposition="bottom center",
    textfont=dict(color="lime", size=10),
    name="Bullish CISD"
))

# Bearish CISD
fig.add_trace(go.Scatter(
    x=bearish_cisd.index,
    y=bearish_cisd["high"] * 1.002,
    mode="markers+text",
    marker=dict(symbol="star", size=14, color="red"),
    text=["CISD↓"] * len(bearish_cisd),
    textposition="top center",
    textfont=dict(color="red", size=10),
    name="Bearish CISD"
))

# CISD level dotted lines
for idx, row in df[df["cisd_bullish"] | df["cisd_bearish"]].iterrows():
    color = "lime" if row["cisd_bullish"] else "red"
    fig.add_hline(
        y=row["cisd_level"],
        line_dash="dot",
        line_color=color,
        line_width=1,
        opacity=0.4
    )

fig.update_layout(
    title="ENJ/USDT 15m — CISD Detection (IST | Matches TradingView)",
    xaxis_title="Time (IST +5:30)",
    yaxis_title="Price (USDT)",
    template="plotly_dark",
    xaxis_rangeslider_visible=False,
    height=700,
    legend=dict(orientation="h", yanchor="bottom", y=1.02)
)

fig.show()
Enter fullscreen mode Exit fullscreen mode
# ============================================================
# Cell 4 — Chart with CISD + Session Highlights (IST)
# ============================================================
import plotly.graph_objects as go
import pandas as pd

fig = go.Figure()

# --- Candlestick ---
fig.add_trace(go.Candlestick(
    x=df.index,
    open=df["open"],
    high=df["high"],
    low=df["low"],
    close=df["close"],
    name="BTC/USDT",
    increasing_line_color="#26a69a",
    decreasing_line_color="#ef5350"
))

# --- Swing Highs ---
swing_h = df[df["swing_high"]]
fig.add_trace(go.Scatter(
    x=swing_h.index,
    y=swing_h["high"] * 1.001,
    mode="markers",
    marker=dict(symbol="triangle-down", size=8, color="orange"),
    name="Swing High"
))

# --- Swing Lows ---
swing_l = df[df["swing_low"]]
fig.add_trace(go.Scatter(
    x=swing_l.index,
    y=swing_l["low"] * 0.999,
    mode="markers",
    marker=dict(symbol="triangle-up", size=8, color="cyan"),
    name="Swing Low"
))

# --- Bullish CISD ---
fig.add_trace(go.Scatter(
    x=bullish_cisd.index,
    y=bullish_cisd["low"] * 0.998,
    mode="markers+text",
    marker=dict(symbol="star", size=14, color="lime"),
    text=["CISD↑"] * len(bullish_cisd),
    textposition="bottom center",
    textfont=dict(color="lime", size=10),
    name="Bullish CISD"
))

# --- Bearish CISD ---
fig.add_trace(go.Scatter(
    x=bearish_cisd.index,
    y=bearish_cisd["high"] * 1.002,
    mode="markers+text",
    marker=dict(symbol="star", size=14, color="red"),
    text=["CISD↓"] * len(bearish_cisd),
    textposition="top center",
    textfont=dict(color="red", size=10),
    name="Bearish CISD"
))

# --- CISD level dotted lines ---
for idx, row in df[df["cisd_bullish"] | df["cisd_bearish"]].iterrows():
    color = "lime" if row["cisd_bullish"] else "red"
    fig.add_hline(
        y=row["cisd_level"],
        line_dash="dot",
        line_color=color,
        line_width=1,
        opacity=0.4
    )

# ============================================================
# --- Session Highlighting (IST timings) ---
# ============================================================
sessions = {
    "Asia"    : {"start": "05:30", "end": "09:15", "color": "rgba(0, 100, 255, 0.10)"},
    "London"  : {"start": "11:30", "end": "14:15", "color": "rgba(255, 50, 50, 0.10)"},
    "New York": {"start": "19:00", "end": "20:00", "color": "rgba(0, 200, 100, 0.10)"},
}

# Get unique dates in the dataframe
unique_dates = df.index.normalize().unique()

for date in unique_dates:
    date_str = str(date.date())

    for session_name, session in sessions.items():
        start_dt = pd.Timestamp(f"{date_str} {session['start']}", tz="Asia/Kolkata")
        end_dt   = pd.Timestamp(f"{date_str} {session['end']}",   tz="Asia/Kolkata")

        # Only draw if session overlaps with our data range
        if start_dt > df.index[-1] or end_dt < df.index[0]:
            continue

        fig.add_vrect(
            x0=start_dt,
            x1=end_dt,
            fillcolor=session["color"],
            line_width=0,
            annotation_text=session_name,
            annotation_position="top left",
            annotation_font=dict(size=9, color="white"),
            layer="below"
        )

# ============================================================
# Layout
# ============================================================
fig.update_layout(
    title="ENJ/USDT 15m — CISD + Sessions (IST)",
    xaxis_title="Time (IST +5:30)",
    yaxis_title="Price (USDT)",
    template="plotly_dark",
    xaxis_rangeslider_visible=False,
    height=750,
    legend=dict(orientation="h", yanchor="bottom", y=1.02),
    shapes=[],
)

fig.show()
Enter fullscreen mode Exit fullscreen mode

Top comments (0)