
import pandas as pd
import numpy as np
import json

def calculate_python_score(row, weights):
    stoch_value = row['stoch_value']
    macd_prediction = row['macd_prediction']
    osc = row['osc_1d']
    macd_flipped_bullish = row['macd_flipped_bullish']
    m3_momentum = row['m3_momentum']
    m2_diff_tiny = row['m2_diff_abs_tinyoffset_to_future']
    rsid_osc = row['rsid_osc']
    stoch_div_osc = row['stoch_div_osc']
    vwap_div_osc = row['vwap_div_osc']
    stoch_is_peaking = row['stoch_is_peaking']
    stoch_is_bottoming = row['stoch_is_bottoming']
    m3_div_osc = row['m3_div_osc']
    m2_div_osc_tiny = row['m2_div_osc']
    bearish_engulfing_score = row['bearish_engulfing_score']
    m2_div_osc_noOffset = row['m2_div_osc_nooffset']

    w_stoch = weights.get('i_w_stoch', 0)
    w_macd_pred = weights.get('i_w_macd_pred', 0)
    w_osc = weights.get('i_w_osc', 0)
    w_macd_bullish = weights.get('i_w_macd_bullish', 0)
    w_m3_momentum = weights.get('i_w_m3_momentum', 0)
    w_m2_tiny = weights.get('i_w_m2_tiny', 0)
    w_rsid_osc = weights.get('i_w_rsid_osc', 0)
    w_stoch_div_osc = weights.get('i_w_stoch_div_osc', 0)
    w_vwap_div_osc = weights.get('i_w_vwap_div_osc', 0)
    w_stoch_peaking = weights.get('i_w_stoch_peaking', 0)
    w_stoch_bottoming = weights.get('i_w_stoch_bottoming', 0)
    w_m3_div_osc = weights.get('i_w_m3_div_osc', 0)
    w_m2_div_osc = weights.get('i_w_m2_div_osc', 0)
    w_bearish_engulfing = weights.get('i_w_bearish_engulfing', 0)
    w_m2_div_osc_noOffset = weights.get('i_w_m2_div_osc_noOffset', 0)

    # Normalization
    stoch_norm = (stoch_value - 50) / 50 if not np.isnan(stoch_value) else 0
    macd_pred_norm = 1 if macd_prediction > 0 else -1
    osc_norm = (osc - 50) / 50 if not np.isnan(osc) else 0
    macd_bullish_norm = 1 if macd_flipped_bullish else 0
    m3_momentum_norm = 1 if m3_momentum > 0 else -1
    m2_tiny_momentum_norm = 1 if m2_diff_tiny > 0 else -1 if m2_diff_tiny < 0 else 0
    rsid_osc_norm = -(rsid_osc - 42) / 28 if not np.isnan(rsid_osc) else 0
    stoch_div_osc_norm = 1 if stoch_div_osc > 0 else -1
    vwap_div_osc_norm = np.clip(vwap_div_osc, -1.0, 1.0) if not np.isnan(vwap_div_osc) else 0
    stoch_peaking_norm = -1 if stoch_is_peaking else 0
    stoch_bottoming_norm = 1 if stoch_is_bottoming else 0
    m3_div_osc_norm = 1 if m3_div_osc > 0 else -1
    m2_div_osc_norm = 1 if m2_div_osc_tiny > 0 else -1
    bearish_engulfing_norm = bearish_engulfing_score
    m2_div_osc_noOffset_norm = 1 if m2_div_osc_noOffset > 0 else -1

    score = (
        (macd_pred_norm * w_macd_pred) +
        (stoch_norm * w_stoch) +
        (osc_norm * w_osc) +
        (macd_bullish_norm * w_macd_bullish) +
        (m3_momentum_norm * w_m3_momentum) +
        (m2_tiny_momentum_norm * w_m2_tiny) +
        (rsid_osc_norm * w_rsid_osc) +
        (stoch_div_osc_norm * w_stoch_div_osc) +
        (vwap_div_osc_norm * w_vwap_div_osc) +
        (stoch_peaking_norm * w_stoch_peaking) +
        (stoch_bottoming_norm * w_stoch_bottoming) +
        (m3_div_osc_norm * w_m3_div_osc) +
        (m2_div_osc_norm * w_m2_div_osc) +
        (bearish_engulfing_norm * w_bearish_engulfing) +
        (m2_div_osc_noOffset_norm * w_m2_div_osc_noOffset)
    )
    return score

def main():
    # Load data
    df = pd.read_csv('results/TV_Export.csv')
    df.columns = df.columns.str.strip()
    df_features = df.rename(columns=lambda x: x.strip().lower())

    # Load weights
        weights = {
            "i_w_stoch": 6.52,
            "i_w_macd_pred": 69.0,
            "i_w_osc": -5.6,
            "i_w_macd_bullish": 0.5581,
            "i_w_m3_momentum": 0.6912,
            "i_w_m2_tiny": 68,
            "i_w_rsid_osc": 2.835,
            "i_w_stoch_div_osc": -4.73,
            "i_w_vwap_div_osc": 23.0,
            "i_w_stoch_peaking": -7.26,
            "i_w_stoch_bottoming": 180.0,
            "i_w_m3_div_osc": -3.148,
            "i_w_m2_div_osc": 54.0,
            "i_w_bearish_engulfing": 39.0,
            "i_w_m2_div_osc_noOffset": 1.0
        }

    print("--- Detailed Calculation for First Row ---")
    first_row = df_features.iloc[0]
    stoch_value = first_row['stoch_value']
    macd_prediction = first_row['macd_prediction']
    osc = first_row['osc_1d']
    macd_flipped_bullish = first_row['macd_flipped_bullish']
    m3_momentum = first_row['m3_momentum']
    m2_diff_tiny = first_row['m2_diff_abs_tinyoffset_to_future']
    rsid_osc = first_row['rsid_osc']
    stoch_div_osc = first_row['stoch_div_osc']
    vwap_div_osc = first_row['vwap_div_osc']
    stoch_is_peaking = first_row['stoch_is_peaking']
    stoch_is_bottoming = first_row['stoch_is_bottoming']
    m3_div_osc = first_row['m3_div_osc']
    m2_div_osc_tiny = first_row['m2_div_osc']
    bearish_engulfing_score = first_row['bearish_engulfing_score']
    m2_div_osc_noOffset = first_row['m2_div_osc_nooffset']

    w_stoch = weights.get('i_w_stoch', 0)
    w_macd_pred = weights.get('i_w_macd_pred', 0)
    w_osc = weights.get('i_w_osc', 0)
    w_macd_bullish = weights.get('i_w_macd_bullish', 0)
    w_m3_momentum = weights.get('i_w_m3_momentum', 0)
    w_m2_tiny = weights.get('i_w_m2_tiny', 0)
    w_rsid_osc = weights.get('i_w_rsid_osc', 0)
    w_stoch_div_osc = weights.get('i_w_stoch_div_osc', 0)
    w_vwap_div_osc = weights.get('i_w_vwap_div_osc', 0)
    w_stoch_peaking = weights.get('i_w_stoch_peaking', 0)
    w_stoch_bottoming = weights.get('i_w_stoch_bottoming', 0)
    w_m3_div_osc = weights.get('i_w_m3_div_osc', 0)
    w_m2_div_osc = weights.get('i_w_m2_div_osc', 0)

    stoch_norm = (stoch_value - 50) / 50 if not np.isnan(stoch_value) else 0
    macd_pred_norm = 1 if macd_prediction > 0 else -1
    osc_norm = (osc - 50) / 50 if not np.isnan(osc) else 0
    macd_bullish_norm = 1 if macd_flipped_bullish else 0
    m3_momentum_norm = 1 if m3_momentum > 0 else -1
    m2_tiny_momentum_norm = 1 if m2_diff_tiny > 0 else -1 if m2_diff_tiny < 0 else 0
    rsid_osc_norm = -(rsid_osc - 42) / 28 if not np.isnan(rsid_osc) else 0
    stoch_div_osc_norm = 1 if stoch_div_osc > 0 else -1
    vwap_div_osc_norm = np.clip(vwap_div_osc, -1.0, 1.0) if not np.isnan(vwap_div_osc) else 0
    stoch_peaking_norm = -1 if stoch_is_peaking else 0
    stoch_bottoming_norm = 1 if stoch_is_bottoming else 0
    m3_div_osc_norm = 1 if m3_div_osc > 0 else -1
    m2_div_osc_norm = 1 if m2_div_osc_tiny > 0 else -1

    print(f"{'Component':<25} {'Raw Value':>15} {'Norm Value':>15} {'Weight':>10} {'Weighted Score':>20}")
    print(f"-"*85)
    print(f"{'stoch_value':<25} {stoch_value:>15.4f} {stoch_norm:>15.4f} {w_stoch:>10.2f} {stoch_norm * w_stoch:>20.4f}")
    print(f"{'macd_prediction':<25} {macd_prediction:>15.4f} {macd_pred_norm:>15.4f} {w_macd_pred:>10.2f} {macd_pred_norm * w_macd_pred:>20.4f}")
    print(f"{'osc_1d':<25} {osc:>15.4f} {osc_norm:>15.4f} {w_osc:>10.2f} {osc_norm * w_osc:>20.4f}")
    print(f"{'macd_flipped_bullish':<25} {macd_flipped_bullish:>15.4f} {macd_bullish_norm:>15.4f} {w_macd_bullish:>10.2f} {macd_bullish_norm * w_macd_bullish:>20.4f}")
    print(f"{'m3_momentum':<25} {m3_momentum:>15.4f} {m3_momentum_norm:>15.4f} {w_m3_momentum:>10.2f} {m3_momentum_norm * w_m3_momentum:>20.4f}")
    print(f"{'m2_diff_tiny':<25} {m2_diff_tiny:>15.4f} {m2_tiny_momentum_norm:>15.4f} {w_m2_tiny:>10.2f} {m2_tiny_momentum_norm * w_m2_tiny:>20.4f}")
    print(f"{'rsid_osc':<25} {rsid_osc:>15.4f} {rsid_osc_norm:>15.4f} {w_rsid_osc:>10.2f} {rsid_osc_norm * w_rsid_osc:>20.4f}")
    print(f"{'stoch_div_osc':<25} {stoch_div_osc:>15.4f} {stoch_div_osc_norm:>15.4f} {w_stoch_div_osc:>10.2f} {stoch_div_osc_norm * w_stoch_div_osc:>20.4f}")
    print(f"{'vwap_div_osc':<25} {vwap_div_osc:>15.4f} {vwap_div_osc_norm:>15.4f} {w_vwap_div_osc:>10.2f} {vwap_div_osc_norm * w_vwap_div_osc:>20.4f}")
    print(f"{'stoch_is_peaking':<25} {stoch_is_peaking:>15.4f} {stoch_peaking_norm:>15.4f} {w_stoch_peaking:>10.2f} {stoch_peaking_norm * w_stoch_peaking:>20.4f}")
    print(f"{'stoch_is_bottoming':<25} {stoch_is_bottoming:>15.4f} {stoch_bottoming_norm:>15.4f} {w_stoch_bottoming:>10.2f} {stoch_bottoming_norm * w_stoch_bottoming:>20.4f}")
    print(f"{'m3_div_osc':<25} {m3_div_osc:>15.4f} {m3_div_osc_norm:>15.4f} {w_m3_div_osc:>10.2f} {m3_div_osc_norm * w_m3_div_osc:>20.4f}")
    print(f"{'m2_div_osc':<25} {m2_div_osc_tiny:>15.4f} {m2_div_osc_norm:>15.4f} {w_m2_div_osc:>10.2f} {m2_div_osc_norm * w_m2_div_osc:>20.4f}")
    print(f"{'bearish_engulfing':<25} {bearish_engulfing_score:>15.4f} {bearish_engulfing_norm:>15.4f} {w_bearish_engulfing:>10.2f} {bearish_engulfing_norm * w_bearish_engulfing:>20.4f}")
    print(f"{'m2_div_osc_noOffset':<25} {m2_div_osc_noOffset:>15.4f} {m2_div_osc_noOffset_norm:>15.4f} {w_m2_div_osc_noOffset:>10.2f} {m2_div_osc_noOffset_norm * w_m2_div_osc_noOffset:>20.4f}")
    print(f"-"*85)
    python_score_manual = (
        (macd_pred_norm * w_macd_pred) +
        (stoch_norm * w_stoch) +
        (osc_norm * w_osc) +
        (macd_bullish_norm * w_macd_bullish) +
        (m3_momentum_norm * w_m3_momentum) +
        (m2_tiny_momentum_norm * w_m2_tiny) +
        (rsid_osc_norm * w_rsid_osc) +
        (stoch_div_osc_norm * w_stoch_div_osc) +
        (vwap_div_osc_norm * w_vwap_div_osc) +
        (stoch_peaking_norm * w_stoch_peaking) +
        (stoch_bottoming_norm * w_stoch_bottoming) +
        (m3_div_osc_norm * w_m3_div_osc) +
        (m2_div_osc_norm * w_m2_div_osc) +
        (bearish_engulfing_norm * w_bearish_engulfing) +
        (m2_div_osc_noOffset_norm * w_m2_div_osc_noOffset)
    )
    print(f"{'Manual Python Score:':<60} {python_score_manual:>20.4f}")
    print(f"{'Function Python Score:':<60} {calculate_python_score(first_row, weights):>20.4f}")
    print(f"{'TV PoC Score:':<60} {first_row['activation_score_poc']:>20.4f}")
    print(f"{'TV DB Score:':<60} {first_row['db_score']:>20.4f}")
    print(f"-"*85)



    results = []
    for index, row in df_features.iterrows():
        python_score = calculate_python_score(row, weights)
        tv_poc_score = row['activation_score_poc']
        tv_db_score = row['db_score']
        diff_poc = python_score - tv_poc_score
        diff_db = python_score - tv_db_score
        
        result_row = {
            'time': row['time'],
            'tv_poc_score': tv_poc_score,
            'tv_db_score': tv_db_score,
            'python_score': python_score,
            'diff_poc': diff_poc,
            'diff_db': diff_db
        }
        results.append(result_row)

    results_df = pd.DataFrame(results)
    pd.set_option('display.max_columns', None)
    pd.set_option('display.width', 200)

    print("Comparison of Activation Scores (first 15 rows):")
    print(results_df.head(15).to_string())

    print("\nComparison of Activation Scores (last 15 rows):")
    print(results_df.tail(15).to_string())

if __name__ == "__main__":
    main()
