primo commit
This commit is contained in:
342
pricer/cli.py
Normal file
342
pricer/cli.py
Normal 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()
|
||||
Reference in New Issue
Block a user