primo commit

This commit is contained in:
fredmaloggia
2026-01-05 19:15:03 +01:00
commit f707b9c95b
61 changed files with 2928 additions and 0 deletions

342
pricer/cli.py Normal file
View File

@@ -0,0 +1,342 @@
import sys
import time
from typing import List
from tabulate import tabulate
from . import calc
from .comparison import clone_context, compare_fair_values
from .db import default_sql_query
from .payoffs import PayoffContext
def _prompt_with_default(prompt: str, default: str) -> str:
value = input(prompt)
return default if not value else value
def _print_table(title: str, headers: List[str], rows: List[List[object]]) -> None:
print()
print(title)
print(tabulate(rows, headers=headers, tablefmt="github"))
def get_caso_string(airbag: int, sigma: int, relief: int, twinwin: int, onestar: int) -> str:
componenti = []
if airbag == 1:
componenti.append("Airbag")
if sigma == 1:
componenti.append("Sigma")
if relief == 1:
componenti.append("Relief")
if twinwin == 1:
componenti.append("TwinWin")
if onestar == 1:
componenti.append("OneStar")
return " + ".join(componenti) if componenti else "Standard"
def restart_or_exit():
print()
print("Premere Invio per finire o R per riavviare il programma...")
restart = input()
if restart and restart.upper() == "R":
main()
else:
sys.exit(0)
def main():
version = "2.2 - [12/06/2025]"
print(f"Pricer v.{version}")
fs_db = default_sql_query()
isin = _prompt_with_default("Inserire ISIN (default IT0006767633): ", "IT0006767633")
check_isin = fs_db.check_isin(isin)
if check_isin is not None:
check_value = check_isin[0] if check_isin else None
if check_value == "KO":
print(f"ISIN {isin} non processabile!")
print("Certificati nel pricer devono avere le seguenti caratteristiche : ")
print("- Categoria: Coupon,StepUp,Bonus (con Barriera Discreta)")
print("- Status: In Quotazione")
print("- Direction: Long")
print("- Basket Type : Worst")
print("- Currency : EUR")
print("- CedolaVariabile : FALSE")
print("- Darwin : FALSE")
print("- Domino : FALSE")
print("- Magnet : FALSE")
restart_or_exit()
prezzi_eod = _prompt_with_default(
"Num. Prezzi EOD per calcolo matrice correlazione e volatilita (default 252): ", "252"
)
num_prezzi_eod = int(prezzi_eod)
corr_matrix = calc.correl_certificates(isin, num_prezzi_eod, True)
volatility = calc.volatility_certificates(isin, num_prezzi_eod, True)
is_dividend = _prompt_with_default("Considerare i dividendi ? s/n (default s): ", "s")
num_sims = int(_prompt_with_default("Inserire # simulazioni montecarlo (default = 10000) : ", "10000"))
t_montecarlo_choice = time.perf_counter()
details_ul_model = fs_db.get_details_ul(isin)
nomi_sottostanti = [r.sottostante for r in details_ul_model]
corr_rows = calc.array_to_table(corr_matrix, nomi_sottostanti)
_print_table(f"Matrix Correl {isin}", nomi_sottostanti, corr_rows)
details_ctf_model = fs_db.get_details_ctf(isin)
details_event_model = fs_db.get_details_event(isin)
details_event_exdate_model = fs_db.get_details_event_exdate(isin)
ctf = details_ctf_model[0]
tasso_interesse = ctf.tasso_interesse
days_to_maturity = ctf.days_to_maturity
pdi_style = ctf.pdi_style
pdi_strike = ctf.pdi_strike
pdi_barrier = round(ctf.pdi_barrier, 4)
capital_value = ctf.capital_value
nominal_amount = ctf.nominal_amount
bid = ctf.bid
ask = ctf.ask
last_date_price = ctf.last_date_price
coupon_in_memory = ctf.coupon_in_memory
prot_min_val = ctf.prot_min_val
airbag = ctf.air_bag
fattore_airbag = ctf.fattore_airbag
one_star = ctf.one_star
trigger_onestar = round(ctf.trigger_onestar, 4)
twin_win = ctf.twin_win
sigma = ctf.sigma
relief = ctf.relief
domino = ctf.domino
category = ctf.category
cap = ctf.cap
leva = ctf.leva
prices_ul = [r.spot_price_normalized for r in details_ul_model]
dividends = [r.dividend for r in details_ul_model]
if is_dividend != "s":
dividends = [0.0 for _ in dividends]
num_sottostanti = len(details_ul_model)
days_to_obs = [r.days_to_obs for r in details_event_model]
days_to_ex_date = [r.days_to_ex_date for r in details_event_exdate_model]
days_to_obs_y_fract = [r.days_to_obs_y_fract for r in details_event_model]
coupon_values = [r.coupon_value for r in details_event_model]
coupon_triggers = [r.coupon_trigger for r in details_event_model]
autocall_values = [r.autocall_value for r in details_event_model]
autocall_triggers = [r.autocall_trigger for r in details_event_model]
memory_flags = [r.memory for r in details_event_model]
num_eventi = len(details_event_model)
input_ul_rows = []
for i in range(num_sottostanti):
input_ul_rows.append(
[
nomi_sottostanti[i],
round(prices_ul[i], 4),
round(dividends[i], 4),
round(volatility[i], 4),
]
)
_print_table(
f"Dati Input Sottostanti {isin}",
["Sottostante", "Price", "Dividend", "Volatility"],
input_ul_rows,
)
input_ctf_rows = [
[
round(tasso_interesse, 4),
days_to_maturity,
pdi_style,
pdi_barrier,
round(capital_value * nominal_amount, 5),
round(coupon_in_memory, 5),
round(prot_min_val, 3),
]
]
_print_table(
f"Dati Input Certificato {isin}",
[
"TassoInteresse",
"DaysToMaturity",
"PDI Style",
"PDI Barrier",
"Capital Value",
"Coupon In Memoria",
"Prot Min Val %",
],
input_ctf_rows,
)
input_flag_rows = [
[
airbag,
round(fattore_airbag, 3),
one_star,
trigger_onestar,
twin_win,
sigma,
relief,
]
]
_print_table(
f"Dati Input Flags {isin}",
[
"AirBag",
"Fattore Airbag",
"OneStar",
"TriggerOnestar",
"TwinWin",
"Sigma",
"Relief",
],
input_flag_rows,
)
input_event_rows = []
for i in range(num_eventi):
input_event_rows.append(
[
days_to_obs[i],
round(days_to_obs_y_fract[i], 4),
round(coupon_values[i] * nominal_amount, 6),
round(coupon_triggers[i], 6),
round(autocall_values[i] * nominal_amount, 6),
round(autocall_triggers[i], 6),
memory_flags[i],
]
)
_print_table(
f"Dati Input Eventi {isin}",
[
"DaysToObs.",
"DaysToObsYFract",
"Cpn. Value",
"Cpn. Trigger",
"Autoc. Value",
"Autoc. Trigger",
"Memory",
],
input_event_rows,
)
print("Elaborazione Fair value in corso...")
context_original = PayoffContext(
days_to_maturity=days_to_maturity,
r=tasso_interesse,
capital_value=capital_value,
prot_min_val=prot_min_val,
pdi_barrier=pdi_barrier,
pdi_style=pdi_style,
coupon_in_memory=coupon_in_memory,
days_to_obs_y_fract=days_to_obs_y_fract,
coupon_triggers=coupon_triggers,
coupon_values=coupon_values,
autocall_triggers=autocall_triggers,
autocall_values=autocall_values,
memory_flags=memory_flags,
caso=get_caso_string(airbag, sigma, relief, twin_win, one_star),
pdi_strike=pdi_strike,
fattore_airbag=fattore_airbag,
trigger_one_star=trigger_onestar,
cap=cap,
days_to_obs=days_to_obs,
airbag=airbag,
sigma=sigma,
relief=relief,
twin_win=twin_win,
one_star=one_star,
leva=leva,
volatility=volatility,
prices_ul=prices_ul,
nominal_amount=nominal_amount,
)
context_for_compare = clone_context(context_original)
fvalues = calc.fair_value_array(
prices_ul,
corr_matrix,
num_sottostanti,
num_sims,
tasso_interesse,
days_to_maturity,
dividends,
volatility,
days_to_obs,
days_to_obs_y_fract,
coupon_values,
coupon_triggers,
autocall_values,
autocall_triggers,
memory_flags,
coupon_in_memory,
pdi_style,
pdi_strike,
pdi_barrier,
capital_value,
prot_min_val,
airbag,
sigma,
twin_win,
relief,
fattore_airbag,
one_star,
trigger_onestar,
cap,
leva,
).fair_value_array
fv = [int(value * nominal_amount / 100) for value in fvalues]
t_engine_choice = time.perf_counter()
print(f"Tempo fino alla scelta del motore: {t_engine_choice - t_montecarlo_choice:.2f} sec")
compare_fair_values(
num_sims,
prices_ul,
corr_matrix,
num_sottostanti,
days_to_maturity,
tasso_interesse,
dividends,
context_for_compare,
nominal_amount,
isin,
ask,
bid,
last_date_price,
category,
)
t_expected_done = time.perf_counter()
print(f"Tempo fino al valore atteso: {t_expected_done - t_engine_choice:.2f} sec")
print("----------------------------------------")
if len(days_to_ex_date) > len(days_to_obs):
last_obs = days_to_obs[-1]
last_ex = days_to_ex_date[-1]
if last_obs < last_ex:
print("ATTENZIONE: POSSIBILE SOTTOSTIMA DEL FAIR VALUE")
print("\n Il calcolo del fair value presume che il coupon sia gia stato pagato,")
print(" ma in realta non e ancora maturato (la Ex-Date non e ancora stata raggiunta).")
print(" Il titolo incorpora ancora quel coupon nel suo prezzo, ma il pricer lo ha gia scontato.")
print("\n Inoltre, se erano presenti coupon in memoria, questi sono stati azzerati nel calcolo,")
print(" come se il pagamento fosse gia avvenuto.")
print(" In realta il diritto al pagamento non e ancora stato acquisito.")
print(" Questo comporta una POSSIBILE SOTTOSTIMA SIGNIFICATIVA del FAIR VALUE.")
print("\n SUGGERIMENTO: verificare manualmente l'ultimo evento osservato")
print(" e valutare l'impatto potenziale sul fair value atteso.")
restart_or_exit()