import polars as pl
from polars import col
from numpy.polynomial import Polynomial
from pandas import DataFrame


def cal_intercept_and_slope(df: DataFrame) -> tuple[float, float]:
    """ 计算截距和斜率 """
    x = df['conv_value'].astype('float')
    y = df['conv_prem_log'].astype('float')
    p = Polynomial.fit(x, y, 1)  # 1 次多项式拟合
    intercept = p.convert().coef[0]
    slope = p.convert().coef[1]
    return intercept, slope


def plan_conv_prem(lf: pl.LazyFrame) -> pl.LazyFrame:
    """ 计算转股溢价率 """
    # 计算截距和斜率
    cond = (
        (col("conv_prem") > 0.01)  # 排除转股溢价率 ≤1% 的标的
        & (~col("is_call").is_in(['公告实施强赎', '公告提示强赎', '公告到期赎回', '已满足强赎条件']))  # 排除强赎状态
        & (col("close") < 150)  # 剔除价格 ≥150 的标的
        & (col("left_years") > 1)  # 剔除剩余年限 <1 年的
    )
    conv_prem_data = (
        lf.filter(cond)
        .select(["conv_prem", "conv_value"])
        .with_columns(
            col("conv_prem").log().alias("conv_prem_log"),
        )
    ).collect().to_pandas()
    intercept, slope = cal_intercept_and_slope(conv_prem_data)
    # 生成理论溢价率和修正溢价率
    return (
        lf.with_columns(
            # 理论溢价率: exp(slope * conv_value + intercept)
            (col("conv_value").cast(pl.Float64) * slope + intercept).exp().alias("theory_conv_prem"),
            # 修正溢价率: conv_prem - theory_conv_prem
            (col("conv_prem") - (col("conv_value").cast(pl.Float64) * slope + intercept).exp()).alias("mod_conv_prem"),
        )
    )
    