import dx
import datetime as dt
import pandas as pd
from pylab import plt
plt.style.use('seaborn')

"""
Explanation: <img src="http://hilpisch.com/tpq_logo.png" alt="The Python Quants" width="45%" align="right" border="4">
Quickstart
This brief first part illustrates---without much explanation---the usage of the DX Analytics library. It models two risk factors, two derivatives instruments and values these in a portfolio context.
End of explanation
"""


r = dx.constant_short_rate('r', 0.01)

"""
Explanation: Risk Factor Models
The first step is to define a model for the risk-neutral discounting.
End of explanation
"""


me_1 = dx.market_environment('me', dt.datetime(2016, 1, 1))

me_1.add_constant('initial_value', 100.)
  # starting value of simulated processes
me_1.add_constant('volatility', 0.2)
  # volatiltiy factor
me_1.add_constant('final_date', dt.datetime(2017, 6, 30))
  # horizon for simulation
me_1.add_constant('currency', 'EUR')
  # currency of instrument
me_1.add_constant('frequency', 'W')
  # frequency for discretization
me_1.add_constant('paths', 10000)
  # number of paths
me_1.add_curve('discount_curve', r)
  # number of paths

"""
Explanation: We then define a market environment containing the major parameter specifications needed,
End of explanation
"""


gbm_1 = dx.geometric_brownian_motion('gbm_1', me_1)

"""
Explanation: Next, the model object for the first risk factor, based on the geometric Brownian motion (Black-Scholes-Merton (1973) model).
End of explanation
"""


pdf = pd.DataFrame(gbm_1.get_instrument_values(), index=gbm_1.time_grid)

%matplotlib inline
pdf.iloc[:, :10].plot(legend=False, figsize=(10, 6));

"""
Explanation: Some paths visualized.
End of explanation
"""


me_2 = dx.market_environment('me_2', me_1.pricing_date)
me_2.add_environment(me_1)  # add complete environment
me_2.add_constant('volatility', 0.5)  # overwrite value

gbm_2 = dx.geometric_brownian_motion('gbm_2', me_2)

pdf = pd.DataFrame(gbm_2.get_instrument_values(), index=gbm_2.time_grid)

pdf.iloc[:, :10].plot(legend=False, figsize=(10, 6));

"""
Explanation: Second risk factor with higher volatility. We overwrite the respective value in the market environment.
End of explanation
"""


me_opt = dx.market_environment('me_opt', me_1.pricing_date)
me_opt.add_environment(me_1)
me_opt.add_constant('maturity', dt.datetime(2017, 6, 30))
me_opt.add_constant('strike', 110.)

"""
Explanation: Valuation Models
Based on the risk factors, we can then define derivatives models for valuation. To this end, we need to add at least one (the maturity), in general two (maturity and strike), parameters to the market environments.
End of explanation
"""


am_put = dx.valuation_mcs_american_single(
            name='am_put',
            underlying=gbm_1,
            mar_env=me_opt,
            payoff_func='np.maximum(strike - instrument_values, 0)')

"""
Explanation: The first derivative is an American put option on the first risk factor gbm_1.
End of explanation
"""


am_put.present_value()

am_put.delta()

am_put.gamma()

am_put.vega()

am_put.theta()

am_put.rho()

"""
Explanation: Let us calculate a Monte Carlo present value estimate and estimates for the option Greeks.
End of explanation
"""


eur_call = dx.valuation_mcs_european_single(
            name='eur_call',
            underlying=gbm_2,
            mar_env=me_opt,
            payoff_func='np.maximum(maturity_value - strike, 0)')

"""
Explanation: The second derivative is a European call option on the second risk factor gbm_2.
End of explanation
"""


eur_call.present_value()

eur_call.delta()

eur_call.gamma()

eur_call.vega()

eur_call.theta()

eur_call.rho()

"""
Explanation: Valuation and Greek estimation for this option.
End of explanation
"""


me_3 = dx.market_environment('me_3', me_1.pricing_date)
me_3.add_environment(me_1)  # add complete environment

# interest rate like parmeters
me_3.add_constant('initial_value', 0.05)
  # initial value
me_3.add_constant('alpha', 0.1)
  # initial variance
me_3.add_constant('beta', 0.5)
  # exponent
me_3.add_constant('rho', 0.1)
  # correlation factor
me_3.add_constant('vol_vol', 0.5)
  # volatility of volatility/variance

"""
Explanation: Excursion: SABR Model
To illustrate how general the approach of DX Analytics is, let us quickly analyze an option based on a SABR stochastic volatility process. In what follows herafter, the SABR model does not play a role.
We need to define different parameters obviously.
End of explanation
"""


sabr = dx.sabr_stochastic_volatility('sabr', me_3)

"""
Explanation: The model object instantiation.
End of explanation
"""


me_opt.add_constant('strike', me_3.get_constant('initial_value'))

sabr_call = dx.valuation_mcs_european_single(
            name='sabr_call',
            underlying=sabr,
            mar_env=me_opt,
            payoff_func='np.maximum(maturity_value - strike, 0)')

"""
Explanation: The valuation object instantiation.
End of explanation
"""


sabr_call.present_value(fixed_seed=True)

sabr_call.delta()

sabr_call.rho()

# resetting the option strike
me_opt.add_constant('strike', 110.)

"""
Explanation: Some statistics --- same syntax/API even if the model is more complex.
End of explanation
"""


me_1.add_constant('model', 'gbm')
me_2.add_constant('model', 'gbm')

"""
Explanation: Options Portfolio
Modeling
In a portfolio context, we need to add information about the model class(es) to be used to the market environments of the risk factors.
End of explanation
"""


put = dx.derivatives_position(
            name='put',
            quantity=2,
            underlyings=['gbm_1'],
            mar_env=me_opt,
            otype='American single',
            payoff_func='np.maximum(strike - instrument_values, 0)')

call = dx.derivatives_position(
            name='call',
            quantity=3,
            underlyings=['gbm_2'],
            mar_env=me_opt,
            otype='European single',
            payoff_func='np.maximum(maturity_value - strike, 0)')

"""
Explanation: To compose a portfolio consisting of our just defined options, we need to define derivatives positions. Note that this step is independent from the risk factor model and option model definitions. We only use the market environment data and some additional information needed (e.g. payoff functions).
End of explanation
"""


risk_factors = {'gbm_1': me_1, 'gbm_2' : me_2}
correlations = [['gbm_1', 'gbm_2', -0.4]]
positions = {'put' : put, 'call' : call}

val_env = dx.market_environment('general', dt.datetime(2016, 1, 1))
val_env.add_constant('frequency', 'W')
val_env.add_constant('paths', 10000)
val_env.add_constant('starting_date', val_env.pricing_date)
val_env.add_constant('final_date', val_env.pricing_date)
val_env.add_curve('discount_curve', r)

"""
Explanation: Let us define the relevant market by 2 Python dictionaries, the correlation between the two risk factors and a valuation environment.
End of explanation
"""


port = dx.derivatives_portfolio(
            name='portfolio',  # name 
            positions=positions,  # derivatives positions
            val_env=val_env,  # valuation environment
            risk_factors=risk_factors, # relevant risk factors
            correlations=correlations, # correlation between risk factors
            parallel=False)  # parallel valuation

"""
Explanation: These are used to define the derivatives portfolio.
End of explanation
"""


port.get_values()

"""
Explanation: Simulation and Valuation
Now, we can get the position values for the portfolio via the get_values method.
End of explanation
"""


port.get_statistics()

"""
Explanation: Via the get_statistics methods delta and vega values are provided as well.
End of explanation
"""


deltas, benchvalue = port.get_port_risk(Greek='Delta')

deltas

deltas.loc(axis=0)[:, 'value'] - benchvalue

vegas, benchvalue = port.get_port_risk(Greek='Vega', step=0.05)

vegas

vegas.loc(axis=0)[:, 'value'] - benchvalue

"""
Explanation: Much more complex scenarios are possible with DX Analytics
Risk Reports
Having modeled the derivatives portfolio, risk reports are only two method calls away.
End of explanation
"""


