from lseg_analytics.pricing.instruments import structured_products as sp 

import json
import datetime as dt
import pandas as pd
from IPython.display import display

# 1. Create SP definition object

SN_definition = sp.StructuredProductsDefinition(
    deal_ccy = "EUR",
    instrument_tag = "Reverse_Convertible_basket",
    inputs = [
        sp.NameTypeValue(name="notional", type = "string", value="1000"),
        sp.NameTypeValue(name="Basket", type = "string", value="TTEF_PA|IBE_MC|ENEI_MI"),
        sp.NameTypeValue(name="FirstAsset", type = "string", value="Perf_TTEF_PA"),
        sp.NameTypeValue(name="LastAsset", type = "string", value="Perf_ENEI_MI"),
        sp.NameTypeValue(name="BasketFunction", type = "string", value="WorstOf"),
        sp.NameTypeValue(name="BasketPerf", type = "string", value="If(\"BasketFunction\" == \"WorstOf\", Min(FirstAsset[t]:LastAsset[t]), IF(\"BasketFunction\" == \"Average\", Average(FirstAsset[t]:LastAsset[t],True), 0))"),
        sp.NameTypeValue(name="StrikeDate", type = "date", value="09/07/2025"),
        sp.NameTypeValue(name="MaturityDate", type = "date", value="23/07/2029"),
        sp.NameTypeValue(name="LastValuationDate", type = "date", value="09/07/2029"),
        sp.NameTypeValue(name="Schedule", type = "schedule", value=[
                    ["09/07/2026", "09/07/2026", "23/07/2026", "23/07/2026"],
                    ["09/07/2027", "09/07/2027", "23/07/2027", "23/07/2027"],
                    ["10/07/2028", "10/07/2028", "24/07/2028", "24/07/2028"]]),
        sp.NameTypeValue(name="RedemptionBarrier", type = "string", value="30%"),
        sp.NameTypeValue(name="CouponRate", type = "string", value="5.15%"),
        sp.NameTypeValue(name="Leverage", type = "string", value="100%")
    ],
    payoff_description = [
          [
            "Schedule type",
            "Schedule description",
            "Repeat(Basket,#)",
            "Repeat(Basket,Perf_#)",
            "Performance",
            "Coupon",
            "Settlement",
            "OptionAtMaturity",
            "PriceIn%",
            "Price"
          ],
          [
            "AtDate",
            "StrikeDate",
            "EqSpot(#)",
            "",
            "",
            "",
            "",
            "",
            "",
            ""
          ],
          [
            "OnUserSchedule",
            "Schedule",
            "",
            "",
            "",
            "Receive CouponRate",
            "",
            "",
            "",
            ""
          ],
          [
            "AtDate",
            "LastValuationDate",
            "EqSpot(#)",
            "#[t]/#[StrikeDate]",
            "BasketPerf",
            "Receive (MaturityDate, CouponRate)",
            "Receive (MaturityDate, 100%)",
            "Receive (MaturityDate, If(Performance[t]>=RedemptionBarrier,0,(Performance[t] / Leverage -1)))",
            "Report((columnval(Coupon)+columnval(OptionAtMaturity)+columnval(Settlement))*100)",
            "Report(columnval(PriceIn%)/100*Notional)"
          ]
        ]
)

# 2. Create SP instrument definition object

rev_convert_basket = sp.StructuredProductsDefinitionInstrument(definition = SN_definition)
print("Instrument definition created")

# 3. Create SP parameters object - optional

rev_convert_basket_pricing_params = sp.StructuredProductsPricingParameters(
    valuation_date= dt.date(2025, 9, 10),  # Set your desired valuation date
    report_ccy="EUR",  # Set your reporting currency
    numerical_method = sp.GenericNumericalMethod(method="MonteCarlo"),
    models=[sp.ModelDefinition(
                  underlying_code = "TTEF.PA",
                  underlying_name = "TTEF_PA",
                  underlying_currency = "EUR",
                  asset_class = "Equity",
                  model_name= "Dupire"),
            sp.ModelDefinition(
                  underlying_code = "IBE.MC",
                  underlying_name = "IBE_MC",
                  underlying_currency = "EUR",
                  asset_class = "Equity",
                  model_name= "Dupire"),
            sp.ModelDefinition(
                  underlying_code = "ENEI.MI",
                  underlying_name = "ENEI_MI",
                  underlying_currency = "EUR",
                  asset_class = "Equity",
                  model_name= "Dupire")
          ]
)

print("Pricing parameters configured")

# Execute the calculation using the price() function
# The 'definitions' parameter accepts a list of instruments definitions for batch processing

try:
    response = sp.price(
        definitions=[rev_convert_basket],
        pricing_preferences=rev_convert_basket_pricing_params,
        market_data=None,
        return_market_data=True,  # or False
        fields=None  # or specify fields as a string
    )

    errors = [a.error for a in response.data.analytics if a.error]
    if errors:
        raise Exception(errors[0].message)
    print("Pricing execution completed")
    
except Exception as e:
    print(f"Price calculation failed: {str(e)}")
    raise

# Extract description from response
description = response.data.analytics[0].description

# Convert to dictionary for display
print(json.dumps(description.as_dict(), indent=4))

# Extract vauation from the response
valuation = response.data.analytics[0].valuation

# Convert the dictionary to a DataFrame
df_rev_convert_basket_valuation = pd.DataFrame(list(valuation.items()), columns=["Field", "Value"])

display(df_rev_convert_basket_valuation)

# Extract Greeks from the response
greeks = response.data.analytics[0].greeks

# Convert the dictionary to a DataFrame
df_df_rev_convert_basket_greeks = pd.DataFrame(list(greeks.items()), columns=["Greeks", "Value"])

display(df_df_rev_convert_basket_greeks)