########################################################################
# Copyright (C)  Shuaib Osman (sosman@investec.co.za)
# This file is part of RiskFlow.
#
# RiskFlow is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# any later version.
#
# RiskFlow is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with RiskFlow.  If not, see <http://www.gnu.org/licenses/>.
########################################################################


# standard imports
import os
import inspect
import operator

from collections import OrderedDict
from functools import reduce


def fetch_module_documentation(module_name, attribute='documentation'):
    document_mapping = OrderedDict()
    for class_name, doc in [(x[0], getattr(x[1], attribute))
                            for x in inspect.getmembers(__import__(module_name),
                                                        lambda x: inspect.isclass(x)
                                                                  and hasattr(x, attribute)
                                                                  and getattr(x, attribute))]:
        document_mapping.setdefault(doc[0], []).append((class_name, doc[1]))
    return document_mapping


class ConstructMarkdown(object):
    """
    Constructs the markdown (.md) files as well as the index and config files for mkdocs. Also inspects the other
    classes in riskflow and pulls through relevant documentation.
    """

    mkdown = {'Theory':
        OrderedDict([
            ('Definitions',
             ['## Price Factors',
              '',
              'A financial instrument derives its value from several inherently random market variables (e.g. Equity,',
              'commodity, FX, interest rates, etc.). These variables (referred to as *price factors*) will either have',
              'a single value at time $t$ (i.e. $P(t)$,  e.g. Spot Equity or FX rates), or multiple values $P(t;p)$',
              'parametrized by $p$ which represents term, moneyness etc. (e.g. interest rate curves and volatility',
              ' surfaces).',
              '',
              'Interest rates have values $D(t,T)$ representing discount factors parametrized by maturity $T$. ',
              'Equity/FX volatility price factors has values $v(t,T,S,K)$ representing implied volatilities for expiry',
              '$T$, spot price $S$ and strike $K$. Valuing a deal at time $t$ involves requesting the set of',
              'corresponding price factor values $\\{P(s;p)\\}$ for times $s$, where $s \\le t$ (in the general case),',
              'and parameters $p$. Note that if there is no path dependency then $s=t$.',
              '',
              '## Factor models',
              '',
              'A *factor model* calculates future values of a price factor under monte carlo simulation. The factor',
              'model attached to a price factor $P$ has a vector of random processes $R_1(t),R_2(t),...,R_l(t)$, which',
              'generates the underlying ($l$-factor) source of randomness. All generated random numbers are gaussian',
              'and then transformed to simulate other (potentially correlated) stochastic processes as necessary.',
              '',
              'Under a particular factor model, the corresponding price factor value $P(t;p)$ at time $t$ may depend',
              'on other price factor values, $Q(t;q)$. Typically, an FX rate at time $t$ would depend on the foreign',
              'and domestic interest rates at time $t$.',
              '',
              '## Simulation of price factors with no model',
              '',
              'At $t=0$, all price factors are read directly from their marketdata file. If no factor model is',
              'attached and a value is requested at time $t$, then the price factor at time $t=0$ is used (i.e. it',
              'is assumed **Constant**). This can be extended for some risk factors to make it more **Risk Neutral**',
              'but is not implemented yet.']),

            ('Asset Pricing',
             ['## Spot',
              '',
              'The spot price of an asset $S(t)$ (assuming immediate delivery) is expressed in the *asset currency*.',
              'The asset currency is specified by the corresponding property:',
              '',
              '- **Currency** for equity and commodity prices',
              '- **Domestic Currency** for FX rates',
              '',
              'The initial price $S(0)$ is given by its **Spot** property.',
              '',
              '### FX Rates',
              '',
              'There is just one FX rate price factor for each currency pair (including the base currency). FX rate',
              'price factors always have a currency $C$ and a parent currency $p(C)$ which, currently, will always be',
              'the base currency. If $f(C)$ is the *foreign* currency, and $d(C)$ is the domestic currency, then let',
              '$X_{C/A}(t)$ be the spot price of currency $C$ in currency $A$ at time $t$. The asset factor models',
              'evolve the FX rate $S(t)=X_{f(C)/d(C)}(t)$, effectively making the domestic currency of all FX rates',
              'the same as the base currency',
              '',
              '## Forward rates',
              '',
              'For equity and commodity prices, the forward price at time $t$ for delivery at $T$ is the usual',
              'no-arbitrage formula:',
              '$$F(t,T)=S(t)\\frac{Q(t,T)}{D(t,T)}$$',
              '',
              'Here $D(t,T)$ is the discount rate from the asset\'s interest rate price factor (i.e. its repo rate',
              'specified by the **Interest Rate** price factor) and $Q(t,T)$ is the discount rate from the dividend',
              'rate (for equities) or convenience yield (for commodities).',
              '',
              '### FX Rates',
              '',
              'Forward FX rates for currency $C$ in currency $A$ is given by:',
              '',
              '$$F_{C/A}(t,T)=X_{C/A}\\frac{D_C(t,T)}{D_A(t,T)}$$',
              '',
              'where $D_C(t;T)$ is the discount rate from the interest rate price factor specified by the',
              '**Interest Rate** property on the FX rate price factor for currency $C$. This can be extended to handle',
              'the case where a given equity/commodity price $S(t)$ with asset currency $C$ is required in another',
              'currency $A$ as follows',
              '',
              '$$F_{S/A}(t,T)=S(t)X_{C/A}\\frac{Q(t,T)}{D_A(t,T)}$$',
              '',
              '### Dividend rate interpolation',
              '',
              'A initial dividend rate curve $q(t)$ can be derived from discrete dividends using the no-arbitrage',
              'relationship between spot and forward prices. The spot price is the present-value forward price plus',
              'the dividends the forward purchaser does not get (but the spot purchaser does):',
              '',
              '$$S(0)=F(0,t)D(0,t)+\\sum_{0 \\lt s_i \\le t} H_i D(0,t_i),$$',
              '',
              'where $H_i$ is the projected/known dividend paid at time $t_i$ with ex-dividend date $s_i$',
              '(with $s_i \\le t_i$). With $Q(0,t)=e^{-q(t)t}$,',
              'the implied dividend rate is:',
              '',
              '$$q(t)=\\frac{1}{t} \\log \\Biggl( \\frac{S(0)}{S(0)-\\sum_{0 \\lt s_i \\le t} H_i D(0,t_i)} \\Biggl)$$.',
              '',
              'Since the curve $q(t)t$ is constant on each interval $[s_i,s_{i+1}]$, and is a piecewise linear',
              'function of $1/t$, interpolation should also be linear in $1/t$ with flat extrapolation. If $t_1$ and',
              '$t_2$ are points on the curve with $t_1 \\le t \\le t_2$, then',
              '',
              '$$q(t)=q(t_1)+\\Biggl(\\frac{1/t_1 - 1/t}{1/t_1 - 1/t_2}\\Biggl)(q(t_2)-q(t_1))$$',
              ]),

            ('Energy Pricing',
             ['## Forward Curve',
              '',
              'Energy prices do not necessarily follow the same behaviour as other financial assets. Let $F(t,T)$',
              ' denote the forward price at time t for settlement at time $T$. The (initial) forward price curve',
              '$F(0,T)$ is specified at discrete settlement dates $T_1,...,T_m$. Linear interpolation is used for',
              'other settlement dates T and:',
              '',
              '$$F(t,T)=F(t,T_i)$$,',
              '',
              'where $i$ is either the least index for which $T_i \\ge T$, or $i=m$ if $T \\gt T_m$.']),

            ('Interest Rates',
             ['## Discount and zero rates',
              '',
              'The discount rate $D(t,T)$ is the price at time $t$ of a unit cashflow paid at $T (T \\ge t)$. The zero',
              'rate $r(t,T)$ at time $t$ for maturity $T$ is the continuously compounded interest rate between $t$ and',
              '$T$ where:',
              '',
              '$$D(t,T)=exp(-r(t,T)(T-t))$$',
              '',
              'Let $r_\\tau (t)$ denote the $\\tau$-tenor zero rate $r(t,t+\\tau)$',
              '',
              '## Spread Rates',
              '',
              'A *spread rate* is an interest rate price factor that is defined relative to a *parent rate*. A',
              '*base rate* is an interest rate price factor without a parent. The parent of a spread rate can be',
              'another spread rate or a base rate.',
              '',
              'A spread rate\'s ID has the form $R.S$, where $S$ is the spread name and $R$ is the ID of the parent rate.',
              'The discount rate of $R.S$ is given by',
              '',
              '$$D_{R.S}(t,T)=D_R(t,T)D_S(t,T)$$',
              '',
              'where $D_R$ is the discount rate of the parent and $D_S$ is the spread. Examples of spreads are',
              'ZAR-SWAP.ZAR-USD-BASIS (ZAR-SWAP is the parent and ZAR-USD-BASIS is the spread).']),

            ('Survival Rates',
             ['## Hazard Rates',
              '',
              'The relationship between the hazard rate $h(t)$, survival probability $S(t,T)$ and the',
              'forward hazard rate $h(t,T)$ is',
              '$$exp\\Big(-\\int_t^T h(t,u)du\\Big)=S(t,T)=\\Bbb{E}_t\\Bigl(exp\\bigl(-\\int_t^T h(s)ds\\bigr)\\Bigr) $$',
              '',
              'Where $\\Bbb{E}_t$ represents the risk-neutral expectation conditional on information at time $t$ and',
              '$h(t)=h(t,t)$.',
              '',
              'Initial survival probabilities are represented as a log survival probability curve $I(t)$ defined as',
              '$$I(t)=\\int_0^t h(0,s)ds=-\\log S(0,t)$$',
              'where $I(0)=0$ and $I(u)\\ge I(t)$ for $u \\ge t$.']),

            ('Inflation',
             ['## Price Index',
              '',
              'The Price Index can be monthly or quarterly. It is a flat-right interpolated curve $I(t)$ that contains',
              'historical values. The curve is defined on a discrete set of dates $\\mathcal T$ where for',
              '$\\tau\\in\\mathcal T, I(\\tau)$ is the published price index for period start date $\\tau$. If',
              '$\\tau_0=$max$\\mathcal T$ is the latest historical start period, then for $\\tau>\\tau_0$,',
              '',
              '$$I(\\tau)=I(\\tau_0)F(\\tau-\\tau_0)$$',
              '',
              'Note that no seasonal factor adjustments are made (but can be included here). Also note that',
              '**Last Period Start** should be set to $\\tau_0$.',
              '',
              'If $p(\\tau)$ is the publication date for period starting $\\tau$ (typically $p(\\tau)\\gt\\tau$) and',
              '$s(t)$ is the greatest $\\tau$ for a given date $t$ for which $p(\\tau) \\le t$, then $p(s(t))\\le t$',
              'and $s(p(\\tau))=\\tau$. The value of the Index at $t$ is $I(t)=I(s(t))$.',
              '',
              '## Price Index References',
              '',
              'If an inflation contract needs the value of a price index sampled at time $T$, the sampled value is',
              'called a **reference** value $I_R(T)$. Generally, $I_R(T)$ will be a function of several previously',
              'published price index values.',
              '',
              'For deal valuation, the price index reference convention needs to be known. The following conventions',
              'have been implemented:',
              '',
              '- **IndexReference$\\mathscr l$M** (for $\\mathscr l$=2,3) gives the published price index on the first',
              'day of the month that is $\\mathscr l$ calendar months prior to the month of $T$:',
              '',
              '$$I_R(T)=I((T-\\mathscr {l} m)^{(1)})$$',
              '',
              'where $T^{(i)}$ denotes the $i^{th}$ day in month $T$ and $T-\\mathscr {l} m$ is result of subtracting',
              '$\\mathscr l$ calendar months from T.',
              '',
              '- **IndexReferenceInterpolated$\\mathscr l$M** (for $\\mathscr l$=3 or 4) gives the following',
              'interpolation of $I((T-\\mathscr {l} m)^{(1)})$ and $I((T-(\\mathscr {l}-1) m)^{(1)})$:',
              '',
              '$$ I_R(T)=I((T-\\mathscr {l} m)^{(1)})+\\Biggl( \\frac{T-T^{(1)}}{(T^{(1)}+1m)-T^{(1)}} \\Biggl)\\Big(',
              'I((T-(\\mathscr {l}-1) m)^{(1)})-I((T-\\mathscr {l}m)^{(1)})\\Big)$$.',
              '',
              '## Inflation Rates',
              '',
              'Inflation rate price factors are similar to interest rate price factors but have an associated price',
              'index factor.'])
        ]),
        'Valuation': OrderedDict([
            ('Definitions',
             ['For a given valuation date $t$, expiry date $T$, and time remaining to expiry $\\tau$ (i.e. $(T-t)$),',
              'the interest rate and carry are defined as',
              '',
              '$$r=\\frac{1}{\\tau}\\log(D(t,T))$$',
              '$$b=\\frac{1}{\\tau}\\log\\Big(\\frac{F(t,T)}{S(t)}\\Big)$$',
              '',
              'Asset prices are assumed to be log-normally distributed with interest rates and asset yields assumed',
              'deterministic. Under these assumptions, forwards and european options are given by closed-form formulas.',
              '',
              '## Forwards',
              '',
              'A forward deal pays $S(T)-K$ at the maturity date $T$. where $K$ is the forward price. The value of the',
              'forward contract at time $t$ is',
              '',
              '$$(F(t,T)-K)D(t,T)$$',
              '',
              '## European Options',
              '',
              'A European option pays $max(\\delta(S(T)-K),0)$ at the expiry date $T$, where either $\\delta=+1$ for a',
              'call option or $\\delta=-1$ for a put option. The value of the European option for annualized implied',
              'volatility $\\sigma$ is given by Black\'s formula:',
              '',
              '$$\\mathcal B_\\delta(F(t,T),K,\\sigma\\sqrt\\tau)D(t,T),$$',
              '',
              'where $\\mathcal B_\\delta$ is given by:',
              '',
              '$$\\mathcal B_\\delta(F,K,v)=\\delta(F\\Phi(\\delta d_1)-K\\Phi(\\delta d_2)), $$',
              '',
              'and (for $F>0, K>0, v>0$):',
              '',
              '- $d_1=\\frac{\\log(F/K)}{v}+\\frac{v}{2}$',
              '- $d_2=d_1-v$',
              '- $\\Phi$ is the standard normal cumulative function']),

            ('FX and Equity',
             ['## Single Barrier Options',
              '',
              'A single barrier option has an underlying European option that is either knocked in ot knocked out when',
              'the underlying asset price touches the barrier level $H$. At the expiry date, if the option has not',
              'been knocked in then a rebate is paid.',
              '',
              'Consider a generalized European option that pays',
              '',
              '$$(AS(T)+B)[\\delta(S-K)>0],$$',
              '',
              'where $A$ and $B$ are constants, $K$ is the strike and $\\delta=+1$ for call options ($\\delta=-1$ for',
              'put options). Standard options have $A=\\delta$ and $B=-\\delta K$ with binary options having $A=0$',
              'and $B$ the payoff amount.',
              '',
              'Single barrier options are priced with the formulas from Merton, Reiner and Rubinstein. They are a',
              'combination of the following formulas:',
              '',
              '$$ V_1(t)=AS(t)e^{(b-r)\\tau}\\Phi(\\delta x_1)+Be^{-rt}\\Phi(\\delta x_1-\\delta\\sigma\\sqrt\\tau)$$',
              '$$ V_2(t)=AS(T)e^{(b-r)\\tau}\\Phi(\\delta x_2)+Be^{-rt}\\Phi(\\delta x_2-\\delta\sigma\\sqrt\\tau)$$',
              '$$ V_3(t)=AS(T)e^{(b-r)\\tau}\\Big(\\frac{H}{S(t)}\\Big)^{2(\\mu+1)} \\Phi(\\eta y_1)+Be^{-r\\tau}',
              '\\Big(\\frac{H}{S(t)}\\Big)^{2\\mu}\\Phi(\\eta y_1 - \\eta\\sigma\\sqrt\\tau)$$',
              '$$ V_4(t)=AS(T)e^{(b-r)\\tau}\\Big(\\frac{H}{S(t)}\\Big)^{2(\\mu+1)} \\Phi(\\eta y_2)+Be^{-r\\tau}',
              '\\Big(\\frac{H}{S(t)}\\Big)^{2\\mu}\\Phi(\\eta y_2 - \\eta\\sigma\\sqrt\\tau)$$',
              '',
              '| Barrier Type      | Condition     | Parameters          | Option Value                 |',
              '| -----------------:|:-------------:| -------------------:| ---------------------------: |',
              '| Down-and-Out Call | $K \\gt H$     | $\\eta=1,\\delta =1$  |$V_1 - V_3$                |',
              '| Down-and-Out Call | $K \\le H$     | $\\eta=1,\\delta=1$   |$V_2 - V_4$                |',
              '| Up-and-Out Call   | $K \\gt H$     | $\\eta=-1,\\delta=1$  |$0$                        |',
              '| Up-and-Out Call   | $K \\le H$     | $\\eta=-1,\\delta=1$  |$V_1 - V_2 + V_3 - V_4$    |',
              '| Down-and-Out Put  | $K \\gt H$     | $\\eta=1,\\delta=-1$  |$V_1 - V_2 + V_3 - V_4$    |',
              '| Down-and-Out Put  | $K \\le H$     | $\\eta=1,\\delta=-1$  |$0$                        |',
              '| Up-and-Out Put    | $K \\gt H$     | $\\eta=-1,\\delta=-1$ |$V_2 - V_4$                |',
              '| Up-and-Out Put    | $K \\le H$     | $\\eta=-1,\\delta=-1$ |$V_1 - V_3$                |',
              '',
              'Where $\\mu= {(b-\\sigma}^2/2)/\\sigma^2, \\eta=+1$ for down options or $\\eta=-1$ for up options, and',
              '',
              '$$ x_1=\\frac{1}{\\sigma\\sqrt\\tau}\\log\\Big(\\frac{S(t)}{K}\\Big)+(1+\\mu)\\sigma\\sqrt\\tau$$',
              '$$ x_2=\\frac{1}{\\sigma\\sqrt\\tau}\\log\\Big(\\frac{S(t)}{H}\\Big)+(1+\\mu)\\sigma\\sqrt\\tau$$',
              '$$ y_1=\\frac{1}{\\sigma\\sqrt\\tau}\\log\\Big(\\frac{H^2}{S(t)K}\\Big)+(1+\\mu)\\sigma\sqrt\\tau$$',
              '$$ y_2=\\frac{1}{\\sigma\\sqrt\\tau}\\log\\Big(\\frac{H}{S(t)}\\Big)+(1+\\mu)\\sigma\\sqrt\\tau$$',
              '',
              '### One touch and No touch Binary Options and Rebates',
              '',
              'A one touch binary option pays a fixed amount if the barrier is touched during the life of the option,',
              'otherwise nothing. The two types are:',
              '',
              '- Pay the fixed amount when the barrier is touched',
              '- Pay the fixed amount at expiry',
              '',
              'A no-touch binary option pays a fixed amount if the barrier is not touched during its life (equivalent',
              'to a fixed amount less a one touch binary option with payment at expiry).',
              '',
              'The value of a no touch option is',
              '',
              '$$e^{-r\\tau}\\Big[ \\Phi(\\eta x_2-\\eta\\sigma\\sqrt\\tau)-\\Big(\\frac{H}{S(t)}\\Big)^{2\\mu}',
              '\\Phi(\\eta y_2-\\eta\\sigma\\sqrt\\tau) \\Big] $$',
              '',
              'where $\\eta=+1$ for down options or $\\eta=-1$ for up options',
              '',
              'The value of the one touch option that pays 1 at expiry if S touches the barrier is $e^{-r\\tau}$',
              'minus the value of the no-touch option. If it pays 1 when $S$ touches the barrier, then its value is',
              '',
              '$$\\Big(\\frac{H}{S(t)}\\Big)^{\\mu+\\lambda}\\Phi(\\eta z)+\\Big(\\frac{H}{S(t)}\\Big)^{\\mu-\\lambda}',
              '\\Phi(\\eta z-2\\eta\\lambda\\sigma\\sqrt\\tau))$$',
              '\\Phi(\\eta z-2\\eta\\lambda\\sigma\\sqrt\\tau))$$',
              '',
              'with',
              '',
              '$$z=\\frac{1}{\\sigma\\sqrt\\tau}\\log\\Big(\\frac{H}{S(t)}\\Big)+\\lambda\\sigma\\sqrt\\tau$$',
              '$$\\lambda=\\sqrt{\\mu^2+\\frac{2r}{\\sigma^2}}$$',
              '',
              'Note that $r$ should be floored at $\\frac{-(b/\\sigma-\\sigma/2)^2}{2}$ for $\\lambda$ to be defined.',
              'One touch and no touch options have strike $H$.',
              '',
              '### Discontinuous Barrier Sampling',
              '',
              'Assuming that barriers are not monitored continuously, an adjustment needs to be made to compensate',
              'for discrete sampling. The adjustment is that of Broadie, Glasserman and Kou.',
              '',
              'If the barrier is above the asset, the adjusted barrier rate is $He^{\\beta\\sigma\\sqrt\\delta}$',
              'where $\\delta$ is the period between observations and $\\beta$ is the constant defined by:',
              '',
              '$$\\beta=\\frac{\\xi(1/2)}{\\sqrt{2\\pi}}\\approx 0.5826$$',
              '',
              'where $\\xi$ is the Riemann zeta function. If the barrier is below the asset, the adjusted barrier is',
              '$He^{-\\beta\\sigma\\sqrt\\delta}$',
              '',
              '## Discrete Asian Options',
              '',
              'The payoff of a discrete asian option is max$(\\delta(\\bar S-K),0)$ at expiry $T$ with:',
              '',
              '$$\\bar S=\\frac{1}{D}\\sum_{i=1}^n d_iS(t_i),$$',
              '',
              '$t_1,...,t_n$ are the dates defined **Sampling Data**, $d_i$ is the weight assigned to $t_i$,',
              '$D=\\sum_{i=1}^n d_i$, $K$ is the strike, and $\\delta$ is either $+1$ for a call or $-1$ for a put.',
              '',
              'If $t_i \\le 0$, then $S(t_i)$ is the known price assigned to $t_i$ in the sampling data list otherwise',
              'it\'s the initial price factor value.',
              '',
              'For valuation date $t$, let $m$ be the smallest index for which $t_{m+1} \\gt t$ ($t_{n+1}=\\infty$).',
              'Then $\\bar S-K=A-\\bar K$, with',
              '',
              '$$A=\\sum_{i=m+1}^n \\omega_i S(t_i),$$',
              '',
              '$\\omega_i=d_i/D$, and $\\bar K$ is the adjusted strike:',
              '',
              '$$\\bar K=K-\\sum_{i=1}^m \\omega_i S(t_i).$$',
              '',
              'The expectation of $S(t_i)$ under the risk-neutral measure is the forward price $F(t,t_i)$ with the',
              'expectation of $A$ given by:',
              '',
              '$$F=\\Bbb{E}_t(A)=\\sum_{i=m+1}^n \\omega_i F(t,t_i).$$',
              '',
              'Define:',
              '',
              '- $\\tau_i=t_i-t$',
              '- $i\\wedge j$ to mean $\\min(i,j)$',
              '- $cov_t(\\log S(t_i),\\log S(t_j))=\\sigma_{i\\wedge j}^2 \\tau_{i\\wedge j}$',
              '- $var_t(\\log S(t_i))=\\sigma_i^2 \\tau_i$',
              '',
              'Assuming the moment matching approach (the idea that a sum of lognormal variables may be represented by',
              'another lognormal variable with the same first and second moments as the sum), $A$ is lognormal and',
              '$var_t(\\log A)=v^2$ where $v$ is given by:',
              '',
              '$$ F^2 e^{v^2} = \\sum_{i,j=m+1}^n \\omega_i\\omega_j F(t,t_i)F(t,t_j)e^{\\sigma^2_{i\\wedge j}',
              '\\tau_{i\\wedge j}},$$',
              '',
              'and the option value is',
              '',
              '$$\\mathcal B_\\delta(F,\\bar K,v)D(t,T).$$',
              '',
              'Assuming a constant carry rate and constant volatility, we can approximate $F(t,t_i)=S(t)e^{b\\tau_i}$',
              'and $\\sigma_i=\\sigma$ where',
              '$\\sigma$ is the implied volatility at time $t$ for expiry $T$ and strike $K\'$ and,',
              '',
              '$$K\'=\\frac{\\bar K}{\\sum_{i=m+1}^n \\omega_i}$$',
              '',
              '## Equity Swaps',
              '',
              'Equity swap legs consist of a series of equity swaplets.',
              '',
              '### Equity Swaplet',
              '',
              'An equity swaplet has:',
              '',
              '- a cashflow $A$',
              '- start date $t_0$',
              '- end date $t_1$',
              '- payment date $T$',
              '- a start multiplier $a_0$',
              '- an end multiplier $a_1$',
              '- a dividend multiplier $b$',
              '',
              'For cashflow dates $t_0\\le t_1\\le T$, the equity swaplet pays:',
              '',
              '$$A\\Big( \\frac{a_1 S(t_1)-a_0 S(t_0)+bH(t_0,t_1)}{S(t_0)^a}\\Big)$$',
              '',
              'at time $T$. where',
              '',
              '- $S(t)$ is the equity price',
              '- $H(t_0,t_1)$ is the time-$t_1$ value of dividends per share with ex-dividend date after $t_0$ but on',
              'or before $t_1$',
              '- $a=1$ if the amount type is **Principle** and $a=0$ if the amount type is **Shares**.',
              '',
              'The swaplets have $a_0=a_1=1$ and either $b=1$ if **Include Dividends** is **Yes** or $b=0$ otherwise.',
              '',
              'The formula used to value the swaplet at $t\\le t_0$ is',
              '',
              '$$A\\Big((a_1-b)\\frac{F(t,t_1)}{F(t,t_0)^a}+ \\Big( b\\frac{D_r(t,t_0)}{D_r(t,t_1)}-a_0\\Big)',
              'F(t,t_0)^{1-a}\\Big)D(t,T)$$',
              '',
              'where:',
              '',
              '- $F$ is the forward equity price',
              '- $D$ is the usual discount factor',
              '- $D_r$ is the discount factor from the equity\'s repo rate',
              '',
              'The value of the swaplet at $t_0\\le t\\lt t_1$ is',
              '',
              '$$A\\Big(\\frac{(a_1-b)F(t,t_1)+ \\frac{b(S(t)+H(t_0,t))}{D_r(t,t_1)}-a_0S(t_0)}{S(t_0)^a}\\Big)',
              'D(t,T)$$',
              '',
              'The value of the swaplet for $t_1\\le t\\le T$ is the payoff multiplied by $D(t,T)$',
              '',
              'When $t\\ge t_0$, the dividend payoff $H(t_0,t\\wedge t_1)$ is calculated from **Known Dividends**',
              'and/or the simulated spot and forward prices along the current scenario path',
              '',
              '**Dividend Timing** is assumed to be **Terminal** i.e. the swaplet pays $\\frac{AbH(t_0,t_1)}{S(t_0)^a}$',
              'at time $T$. Dividend timing could also be continuous (i.e. the dividends are settled on their dividend',
              'dates) but that is not currently implemented.',
              ]),
            ('Energy',
             ['## Forward Prices',
              '',
              'Physical commodities that encumber difficulties in storage or a lack of speculators that make the',
              'arbitrage relationship between spot and forward prices at different tenors weak are (unlike equities',
              'or FX) not suited to having the forward price treated as a deterministic function of the spot and',
              'carry. Instead, the underlying forward prices themselves must be simulated.',
              '',
              'Forward prices are stored as curves (the forward price at time $t$ for delivery at time $T$ is',
              'denoted $F(t,T)$) with the initial forward price curve $F(0,T)$ entered in the market data file.',
              '',
              '## Reference Prices',
              '',
              'Most derivatives contracts are not written directly on daily energy prices but usually on averages of',
              'future prices. Reference prices allow this by being a deterministic function of a Forward price curve,',
              'a sampling period delimited by start and end dates ($t_s^s$ and $t_e^s$) and a set of sampling dates',
              '$\\mathcal S$. It is assumed that sampling periods are contiguous. Reference prices are simulated',
              'indirectly via their forward prices and are denoted $S^R(t,t_s^s,t_e^s,\\mathcal S)$.',
              '',
              '### Fixings',
              '',
              'Reference prices are represented by a fixing curve i.e. a mapping of reference dates to the underlying',
              'forward price dates. In general, it is possible to contruct reference prices that sample the forward',
              'price curve more than once by simply averaging all prices within a reference price window - this is',
              'not implemented. Currently, each reference price simply looks up a single forward price using the',
              'fixing curve mapping.',
              '',
              '#### Expectations',
              '',
              'The risk-neutral expectation of a sampled price at time $t$ when the sampling date is before the',
              'forward price date is simply:',
              '',
              '$$\\Bbb{E}_t (F(t^s,T^f))=F(t,T^f)$$.',
              '',
              'After the sampling date, we need to take the sample value into account and the expectation of a fixing',
              'price with $K$ samples in the past at time $t$ but with $M$ samples still in the future is:',
              '',
              '$$F^f(t,T^f)=\\frac{1}{K+M}\\Big(M F(t,T^f)+ \\sum_{i=1}^K F(t_i^s,T^f)\\Big)$$',
              '',
              'A reference price with $N$ samples is a weighted sum:',
              '',
              '$$ S^R(t,t_s^s,t_e^s,\\mathcal S)=\\frac{1}{K}\\sum_{i=1}^K K_i F_i^f(t,T_i^f), $$',
              '',
              'where the weight $K_i$ of the $i^{th}$ fixing is given by the number of samples within the fixing',
              'period and $K$ is the normalization term $\\sum_{i=1}^N K_i$.',
              '',
              '#### Sample Dates',
              '',
              'The set of dates $\\mathcal S$ used to compute the reference price is defined by the deal by using a',
              '**forward price sample** which can then specify business days according to a given calendar.',
              '',
              '#### Realized Averages',
              '',
              'The realized average price is prorated according to the number of sample dates within the realized',
              'period (exactly as with unrealized samples). The currency depends on whether **FX Averaging** is',
              'selected or if the deal is a compo. If the deal is a compo, the realized average is in the',
              ' **payoff currency**, otherwise, it\'s in the currency of the forward price.',
              '',
              '#### FX Averaging',
              '',
              'When an energy deal is specified in a currency other than the price factor currency, each price',
              'sample must be converted to the native (deal) currency',
              '',
              'Currently, **Average FX** can only be set to **No**, meaning that each price sample is converted to',
              'deal currency at the prevailing spot FX rate. A fixing price with $N$ samples is given in deal',
              'currency as:',
              '',
              '$$F^f(t,T^f)=\\frac{1}{N}\\sum_{i=1}^N F(t_i^s,T^f)X(t_i^s) $$',
              '',
              'Where $F(t,T)$ is the forward price in price factor currency and $X(t)$ is the price of one unit of',
              'price factor currency in deal currency. Here, the realized average of any historical price samples must',
              'be in deal currency.',
              '',
              'Note that forward FX rates $X(t,T)$ are calculated under the usual risk-neutral measure.',
              '',
              '$$X(t,T)=X(t)\\frac{D_p(t,T)}{D_d(t,T)}$$',
              '',
              'where $D_p,D_d$ are the price factor and deal currency discount factors respectively.',
              '',
              '### Reference volatility',
              '',
              'The volatility of a reference price $S^R(t,t_s^s,t_e^s,\\mathcal S)$ with strike price $K$ can be',
              'estimated using the moment matching technique mentioned earlier (assuming that future reference prices',
              'are log-normally distributed).',
              '',
              'For valuation date $t$, define $n$ to be the least index for which $t_{n+1}^s\\gt t$ (here',
              '$t_{N+1}^s=\\infty$). Then $S^R(t,t_s^s,t_e^s,\\mathcal S)-K=A-\\bar K$, where',
              '',
              '$$A=\\frac{1}{N}\\sum_{i=n+1}^N F(t_i^s,T^f)$$',
              '$$\\bar K=K-\\frac{1}{N}\\sum_{i=1}^n F(t_i^s,T^f)$$',
              '',
              'If $F_i$ denotes $F(t_i^s,T_i^f)$ ($t_i^s$ is the $i^{th}$ sampling date in the reference period and',
              '$T_i^f$ is the price date of fixing in which $t_i^s$ falls), then the correlation between $\\log F_i$',
              'and $\\log F_j$ (for $t_i^s \\le t_j^s$) is assumed to be',
              '',
              '$$\\rho_{ij}=\\frac{\\sigma_i\\sqrt{t_i^s-t}}{\\sigma_j\\sqrt{t_j^s-t}}$$',
              '',
              'and $\\sigma_i^2 (t_i^s-t)$ is the standard deviation of $\\log F_i$.',
              '',
              'The standard deviation of $A$ at time $t$ (with $t\\le T$) is then given by',
              '',
              '$$w(t,T,t_s^s,t_e^s,\\mathcal S)^2=\\log\\Big(\\frac{M_2}{M_1^2}\\Big) $$',
              '',
              'with $M_1$ and $M_2$ being the first and second moments given by:',
              '',
              '$$M_1=\\Bbb E_t(A)=\\frac{1}{N}\\sum_{i=n+1}^N F(t,T_i^f)$$',
              '$$M_2=\\frac{1}{N^2}\\sum_{i,j=n+1}^N F(t,T_i^f)F(t,T_j^f)\\exp\\Big(v(t,T_{i\\wedge j}^f,',
              'u_{i\\wedge j},m)^2(u_{i\\wedge j}-t)\\Big)$$',
              '',
              'where',
              '',
              '- $t_1^s,...,t_N^s$ are the sample dates in $\\mathcal S$ between $t_s^s$ and $t_e^s$',
              '- $u_i=\\min(T,t_i^s)$',
              '- $i\\wedge j$ denotes $\\min(i,j)$',
              '- $m=\\frac{M_1}{\\bar K}$ is the moneyness',
              '- $v(t,T,u,m)$ is the forward price volatility at time $t$ for delivery at date $T$ with expiry $u$ and',
              'moneyness $m$ (and $v=0$ for $u\\lt t$).',
              '',
              'Spreads on top of reference prices and volatilities are not currently implemented.',
              '',
              '#### Composite Deals',
              '',
              'Pricing energy composite (compo) deals requires the forward price in payoff currency $F(t,T)X(t,T)$ ',
              'with the compo-adjusted volatility $\\sqrt{\\sigma_S^2+\\sigma_X^2+2\\rho\\sigma_S\\sigma_x}$ used at',
              'each sampling date for both the reference price and reference price volatility (during moment matching)',
              'respectively. The deal currency and the payoff currency must be the same with the **Realized Average**',
              'expressed in payoff currency.',
              ]),
            ('Interest Rates',
             ['Let $D(t,T)$ denote the discount factor for the discount rate and $D_f(t,T)$ the discount factor for',
              'the forecast rate. The currency of the discount rate must be the same as the settlement currency',
              '(**Currency**). Note that the currency of the forecast rate may in future be different to the',
              'settelment currency but is currently not implemented.',
              '',
              'The **Distrubution Type** on the volatility price factor can only be set to **Lognormal** currently.',
              'This assumes that the price factors are log-normally distributed (hence have implied *Black*',
              'volatilities). Note that this can be extended to **Normal** resulting in the price factor having',
              'implied *Bachelier* volatilities.',
              '',
              '## Cashflows',
              '',
              '### Fixed Interest Cashflows',
              '',
              'A cashflow with',
              '',
              '- principal $P$',
              '- fixed interest rate $r$',
              '- accrual start date $T_1$',
              '- accrual end date $T_2$',
              '- accrual day count convention with $\\alpha$ the accrual year fraction from $T_1$ to $T_2$',
              '- payment date $T$',
              '- **Fixed Amount** $C$',
              '',
              'has a standard payoff:',
              '',
              '$$G(r)=Pr\\alpha+C$$',
              '',
              'with value at time $t$ of $G(r)D(t,T)$.',
              '',
              '### Floating Interest Cashflows',
              '',
              'In addtion to the Fixed Interest Cashflow, a Floating Interest Cashflow also has',
              '',
              '- reset date $t_0$',
              '- reset start $t_1$',
              '- reset end $t_2$',
              '- margin rate $m$',
              '',
              'The cashflow dates must satisfy $T_1\\le T_2, t_0\\le t_1\\lt t_2$ and $t_0\\le T$ and the payoff is',
              '$P(L(t_0)+m)\\alpha$ with $L(t)$ is the simply-compounded forward rate at time $t$ given by',
              '',
              '$$L(t)=\\frac{1}{\\alpha_2}\\Big(\\frac{D_f(t,t_1)}{D_f(t,t_2)}-1\\Big),$$',
              '',
              'where $\\alpha_2$ is the accrual year fraction from $t_1$ to $t_2$ using the rate day count convention.',
              '',
              'The value of a standard floating interest rate cashflow at time $t\\lt t_0$ is,',
              '',
              '$$P(L(t)+m)\\alpha D(t,T_2)$$',
              '',
              'If $T=t_2, \\alpha=\\alpha_2$ and the discount and forecast rate are the same, then the value is',
              '',
              '$$P(D(t,t_1)-D(t,t_2))+Pm\\alpha D(t,t_2)$$',
              '',
              'For $T\\neq t_2$, the valuation needs a *convexity correction* but this is yet to be implemented. The',
              'standard payoff is:',
              '',
              '$$G(r)=P(\\eta r+\\kappa\\max((r-K_c),0)+\\lambda\\max((K_f-r),0)+m)\\alpha+C$$',
              '',
              'where',
              '',
              '- $r$ is a simply-compounded forward rate',
              '- $\\eta$ is the swaplet multiplier',
              '- $\\kappa$ is a caplet multiplier, with $K_c$ the caplet strike',
              '- $\\lambda$ is a floorlet multiplier, with $K_f$ the floorlet strike',
              '',
              '### Caplets/Floorlets',
              '',
              'A caplet/floorlet is a call/put option on a simply compounded rate. The option payoff at time $T$ is:',
              '',
              '$$P\\max(\\delta(L(t_0)-K),0)\\alpha$$',
              '',
              'where $K$ is the strike and $\\delta$ is either $+1$ for caplets and $-1$ for floorlets. If $T=t_2$ then',
              'the option value at time $t\\lt t_0$ is',
              '',
              '$$P\\mathcal B_\\delta(L(t),K,\\sigma\\sqrt{t_0-t})\\alpha D(t,T)$$',
              '',
              'where $\\mathcal B_\\delta(F,K,v)$ is the Black function and $\\sigma$ is the volatility of the forecast',
              'rate at time $t$ for expiry $t_0$, tenor $t_2-t_1$ and strike $K$. Note that if $T\\neq t_2$ then the',
              'above formula is still used as no covexity correction has been applied.',
              '',
              '#### Averaging',
              '',
              'A cashflow with averaging depends on a sequence of simply compounded rates $r_1,...,r_m$ with the same',
              'nominal tenor $\\tau$. Each rate $r_k$ jas a positive weight $\\omega_k$. Let $t_{0,k}$ be the reset',
              'date of $r_k$. The average rate $R$ at time $T$ is',
              '',
              '$$R=\\frac{\\sum_{k=1}^m \\omega_k r_k(t_{0,k})}{\\sum_{k=1}^m \\omega_k}$$',
              '',
              '### Cashflow Lists',
              '',
              'Consider a fixed or floating cashflow list with payment dates $t_1\\le ... \\le t_n$ and notional',
              'principal amounts $P_1,...,P_n$. If $U_i(t)$ denotes the value of the $i^{th}$ cashflow at time $t$,',
              'then the value of the cashflow list is $U(t)=\\sum_{i=1}^n [t_i\\ge t]U_i(t)$',
              '',
              'There may also be an optional **Settlement Date** $T$ and **Settlement Amount** $C$. If not specified,',
              'then $T=-\\infty$. Cashflow payment dates must be after the settlement date ($T\\lt t_1$).',
              '',
              'The time $t(>T)$ value of the deal is',
              '',
              '$$V(t)=U(t)\\delta$$,',
              '',
              'where either $\\delta=1$ for a **Buy**, else $\\delta=-1$ for a **Sell**. If $t\\le T$, the deal is',
              'treated as a forward contract on the underling cashflow list. If $A$ is the accrued interest up to ',
              '$T$, then $K=C+A$ if **Settlement Amount Is Clean** else $K=A$. The value at time $t\\le T$ is',
              '',
              '$$V(t)=\\Big(\\frac{U(t)}{D(t,T)}-K\\Big)D_r(t,T)\\delta,$$',
              '',
              'For cash settled deals, the valuation profile terminates at $T$ with a corresponding cashflow',
              '$V(T)=(U(t)-K)\\delta$. If physically settled, then the cashflow is $-K\\delta$ at $T$ and the profile',
              'continues until $t_n$.',
              '',
              '#### Fixed Compounding Cashflow Lists',
              '',
              'For cashflow lists with the interest frequency greater than its payment frequency with payment dates',
              '$T_1\\lt ...\\lt T_c$,let $n(k)$ be the index of the last cashflow with payment date $T_k$ (with',
              '$n(0)=0$). For groups of cashflows with the same payment date, interest is compounded as follows: the',
              '$i^{th}$ cashflow at time $T_k$ pays $K_i+C_i$ with',
              '',
              '$$K_i=P_i I_i(1+I_{i+1})...(1+I_{n(k)})$$',
              '',
              'where',
              '',
              '- $I_i=r_i\\alpha_i$',
              '- $P_i$ is the principal amount$',
              '- $r_i$ is the fixed rate',
              '- $\\alpha_i$ is the accrual year fraction',
              '- $C_i$ is the **Fixed Amount** of the $i^{th}$ cashflow.',
              '',
              'The final value of the cashflows with payment date $T_k$ is',
              '',
              '$$ \\Big(\\sum_{i=n(k-1)+1}^{n(k)}K_i+C_i\\Big)D(t,T_k)$$',
              '',
              '#### Floating Compounding Cashflow Lists',
              '',
              'Similar to the Fixed Compounding Cashflow Lists, $I_i=G_i(r_i(u_i))\\alpha_i+m_i\\alpha_i$ where $u_i$',
              'being the reset date. Let $V_i(t)$ be the value at time $t$ of an amount $I_i$ paid at the accrual end',
              'date $t_i$ (as opposed to the actual payment date $T_k$). The *estimated interest* is',
              '$I_i=\\frac{V_i(t)}{D(t,t_i)}$ when $t<u_i$ otherwise $I_i(t)=I_i$ .',
              '',
              'The compounding method can be:',
              '',
              '**Include Margin** where the $i^{th}$ cashflow pays $P_i I_i(1+I_{i+1})...(1+I_{n(k)})+C_i$ at time',
              '$T_k$ with a value at $t\\le T_k$ of',
              '',
              '$$ (P_i I_i(t)(1+I_{i+1}(t))...(1+I_{n(k)}(t))+C_i)D(t,T_k) $$',
              '',
              '**Flat** where the $i^{th}$ cashflow pays $P_i I_i(1+J_{i+1})...(1+J_{n(k)})+C_i$ at time $T_k$ with',
              '$J_i=I_i-m_i\\alpha_i$. Its value at $t\\le T_k$ is',
              '',
              '$$ (P_i I_i(t)(1+J_{i+1}(t))...(1+J_{n(k)}(t))+C_i)D(t,T_k) $$',
              '',
              '**None** in which case the $i^{th}$ cashflow pays $P_i I_i+C_i$ at time $T_k$.',
              ''
              ]),
            ('Credit',
             ['## Hazard Rates',
              '',
              'A discrete forward hazard rate $H$ in some time interval $\\delta$ given survival at the start of the',
              'interval is:',
              '',
              '$$H(t,T,T+\\delta)=\\frac{1}{\\delta}\\Big(\\frac{S(t,T)-S(t,T+\\delta)}{S(t,T)}\\Big).$$',
              '',
              'The instantaneous hazard rate (the limit as $\\delta\\to 0$) is:',
              '',
              '$$h(t,T)=-\\frac{1}{S(t,T)}\\frac{\\partial S(t,T)}{\\partial T}$$',
              '',
              'Which allows us to write:',
              '',
              '$$S(t,T)=\\exp\\Big(-\\int_t^T h(t,u)du\\Big)$$',
              '',
              '### Value of payments on default',
              '',
              'Consider a cashflow paying $g(u)$ at time $u$. If default occurs at time $u$, and $t_1\\le t\\le t_2$,',
              'then the value at $t\\le t_1$ is:',
              '',
              '$$V(t)=\\int_{t_1}^{t_2} D(t,u)S(t,u)h(t,u)g(u)du.$$',
              '',
              'This is approximated by assuming a constant forward hazard rate $\\bar h$ and forward rate $f$ between',
              '$t_1$ and $t_2$ so that',
              '',
              '$$S(t,u)=S(t,t_1)e^{\\bar h(u-t_1)}$$',
              '$$D(t,u)=D(t,t_1)e^{f(u-t_1)}$$',
              '',
              'where',
              '',
              '$$\\bar h=\\frac{1}{t_2-t_1}\\log\\Big(\\frac{S(t,t_1)}{S(t,t_2)}\\Big)$$',
              '$$f=\\frac{1}{t_2-t_1}\\log\\Big(\\frac{D(t,t_1)}{D(t,t_2)}\\Big)$$',
              '',
              'For a unit cashflow paid on default, $g(u)=1$ and',
              '',
              '$$\\begin{align}V(t) & = D(t,t_1)S(t,t_1)\\bar h\\Big(\\frac{1-e^{(f+\\bar h)(t_2-t_1)}}{f+\\bar h}\\Big)\\\\',
              ' & = \\frac{\\bar h}{f+\\bar h}\\Big((D(t,t_1)S(t,t_1)-D(t,t_2)S(t,t_2)\\Big).\\end{align}$$',
              '',
              'For credit derivatives, define the following:',
              '',
              '- $t_0$ is the deal effective date',
              '- $t_1<...<t_n$ are the accrual period end dates',
              '- $T_1<...<T_n$ are the coupon payment dates',
              '- $P_i$ is the principal for the period $t_{i-1}$ to $t_i$',
              '- $\\alpha_i$ is the accrual year fraction for the period $t_{i-1}$ to $t_i$',
              '- $C_i$ is coupon paid at time $T_i$',
              '- $\\tilde t=\\max(t_i,t)$ and $t_i^\\prime=(\\tilde t_{i-1}+\\tilde t_i)/2$, $t$ is the valuation date',
              '- $R$ is the recovery rate value on the survival probability price factor and $D(t,T)$ is $0$ for $t>T$',
              ]),
            ('Inflation',
             [
                 'The payoff of inflation linked cashflows involves the ratio of reference values $I_R(T_2)$ and $I_R(T_1)$',
                 'with $T_1<T_2$. The following approximation is used:',
                 '',
                 '$$\\Bbb E_t^T\\Big(\\phi\\Big(\\frac{I_R(T_2)}{I_R(T_1)}\\Big)\\Big)\\approx \\phi\\Big(\\frac{I_R(T_2)}{I_R(T_1)}\\Big) $$',
                 '',
                 'where $\\phi$ is an approximately linear function, $T$ is the cashflow payment date and $\\Bbb E_t^T$ is',
                 'a $T$ forward measure conditional at time $t$. This approximation ignores the convexity correction which',
                 'is dependent on the underlying inflation model.',
             ]),
            ('Collateral',
             ['Collateral agreements (CSA\'s) are represented using a container instrument called a netting collateral',
              'set. The idea is to first model the effect of an uncollateralized net portfolio $V(t)$ and then, per',
              'scenario, transform this to a collateralized portfolio $\\hat V(t)$.',
              '',
              'In addition to posting and recieving collateral there are still two residual risks viz.',
              '',
              '### Settlement Risk',
              '',
              'This arises when counterparty default occurs unexpectantly. Potentially, a party may make payment (or ',
              'post collateral) to the counterparty without receiving the corresponding collateral (or payment) in',
              'return.',
              '',
              '### Liquidity risk',
              '',
              'This refers to the basis risk between the market cost of closing out or replacing the counterparty',
              'portfolio against the realized market value of the collateral held.',
              ])
        ]),
        'Boostrapping': OrderedDict([
            ('General',
             ['Market Data needs to be calibrated to their corresponding price models in order to construct',
              'a risk neutral calibration. Bootstrapping is the general term used to fit models to data via',
              '*optimizers*. It is a form of calibration that typically only looks at current market data with no',
              'reference to any historical data.',
              '',
              'Generally, if $S$ is the price factor that needs to be calculated from $n$ benchmark deals, then the',
              '$i^{th}$ deal has:',
              '',
              ' - an observed quoted market value $Q_i$',
              ' - a net value $V_i(S,Q_i)$',
              ' - a surface point $p_i$',
              '',
              'The points should satisfy $p_1<p_2<...<p_n$ and the process of bootstrapping results in a price',
              'factor $S$ such that $V_i(S, Q_i)=0$ for all $i=1,..,n$.',
              ''
              ]),
            ('FX and Equity', ['']),
            ('Interest Rates', [''])
        ]),
        'JSON': OrderedDict([
            ('General',
             [
                 'All data types used in RiskFlow are the standard JSON types (string, float, integers) with the exception',
                 'of the following:',
                 '',
                 '- ModelParams. An object with the following fields:',
                 '    - modeldefaults: a JSON object with price factor type as the fieldname and the factor model as the value.',
                 '    - modelfilters: a JSON object with price factor type as the fieldname and an array of fieldname, ',
                 'value pairs followed by a factor model.',
                 '- Curve. An object with two fields:',
                 '    - meta: set to []. Reserved for future use.',
                 '    - data: an array with floats or integers. Can be a list of pairs, triples or quads.',
                 '- Percent. Float value interpreted as being entered in percentage points.',
                 '- Basis. Float value interpreted as being entered in basis points.',
                 '- DateOffset. An object that must have at least one or several of the following distinct fields:',
                 '    - days: integer',
                 '    - weeks: integer',
                 '    - months: integer',
                 '    - years: integer',
                 '- Timestamp: String value interpreted as a date in YYYY-MM-DD date format',
                 '',
                 'Note that all objects must be preceded with a \'.\'(period) as the fieldname in the JSON.',
                 '',
                 '### Correlation names',
                 '',
                 'Each factor model has its own correlation name. They are as follows:',
                 '',
                 '| Factor Model      | Correlation Name     | Number of factors  | Sub Components  |',
                 '| -----------------:|:--------------------:| ------------------:| ---------------:|',
                 '| GBMAssetPriceModel  | LognormalDiffusionProcess | 1 | <NA> |',
                 '| GBMPriceIndexModel  | LognormalDiffusionProcess | 1 | <NA> |',
                 '| HullWhite1FactorInterestRateModel  | HWInterestRate | 1 | F1|',
                 '| HullWhite2FactorImpliedInterestRateModel  | HWImpliedInterestRate | 2 | F1, F2 |',
                 '| HWHazardRateModel | HullWhiteProcess | 1 | <NA> |',
                 '| CSForwardPriceModel | ClewlowStricklandProcess | 1 | <NA> |',
                 '| PCAInterestRateModel | InterestRateOUProcess | 3 | PC1,PC2,PC3 |',
                 '',
                 'The sections that follow refer to the *Price Factor* section of the market data file.',
             ]),
            ('FX and Equity', ['']),
            ('Energy', ['']),
            ('Interest Rates', ['']),
            ('Inflation', ['']),
            ('Credit', [''])
        ]),
        'API': OrderedDict([
            ('Data',
             ['There are two fundemental data files that need to be setup prior to performing any calculations viz.',
              'Market Data and Trade Data files:',
              '',
              '## Market Data',
              '',
              'A market data file is a JSON object that contains the following sections:',
              '',
              '### System Parameters',
              '',
              'Here the **Base Currency** and the **Correlations Healing Method** is specified. All FX rates are',
              'expressed relative to the base currency. Since the correlations between risk factors may not always',
              'form a positive-definite matrix, a technique called *Eigenvalue Raising* is used to ensure that all',
              'eigenvalues of the correlation matrix are positive. The matrix is then rescaled to ensure that there',
              'are one\'s along the diagonal.',
              '',
              '###  Model Configuration',
              '',
              'This specifies a assignment of Risk Factor to Process Model. There are two subsections:',
              '',
              '**modeldefaults** contain mappings of price factors to models e.g. FxRate:GBMAssetPriceModel defaults',
              'all FX rates to use the GBMAssetPriceModel.',
              '',
              '**modelfilters** allow exceptions to the default model. Filters are allowed based on attributes of the',
              'price factor (or its *ID*) e.g.',
              '',
              '```json',
              '"InterestRateBasisSpread": [',
              '  [',
              '	  [',
              '		"Currency",',
              '		"ZAR"',
              '	  ],',
              '	  "HullWhite1FactorInterestRateModel"',
              '	]',
              ']',
              '```',
              '',
              'is interpreted as using the HullWhite1FactorInterestRateModel for all InterestRateBasisSpreads where',
              'the Currency is ZAR.',
              '',
              '###  Price Factors',
              '',
              'Prices factors representing a snapshot of a market (and hence taken at the same time) are to be provided',
              'here. e.g. for the ZAR FxRate with USD as the **Base Currency**',
              '',
              '```json',
              '"Price Factors": {',
              '  "FxRate.USD": {',
              '    "Domestic_Currency": null,',
              '    "Interest_Rate": "USD-MASTER",',
              '    "Spot": 1',
              '   },',
              '  "FxRate.ZAR": {',
              '    "Domestic_Currency": USD,',
              '    "Interest_Rate": "ZAR-SWAP.ZAR-USD-BASIS",',
              '    "Spot": 0.075475',
              '   }',
              '}',
              '```',
              'Note that the corresponding USD-MASTER and both the ZAR-SWAP and ZAR-USD-BASIS interest rate curves',
              'need to be defined.',
              '',
              '###  Price Models',
              '',
              'Parameters for the stochastic processes used to simulate it\'s corresponding price factor is to be',
              'provided here e.g. for ZAR,',
              '',
              '```json',
              '"Price Models": {',
              '  "GBMAssetPriceModel.ZAR": {',
              '    "Vol": 0.171569979672,',
              '    "Drift": -0.0436796256753',
              '   }',
              '}',
              '```',
              '',
              'Note that the name of the model needs to match the price factor.',
              '',
              '###  Correlations',
              '',
              'Correlations between Price Models is to be provided here. e.g.',
              '```json',
              '"Correlations": {',
              '      "HWInterestRate.ZAR-SWAP.F1": {',
              '        "HWInterestRate.USD-MASTER.F1": 0.2,',
              '        "LognormalDiffusionProcess.ZAR": 0.5',
              '      },',
              '      "HWInterestRate.USD-MASTER.F1": {',
              '        "LognormalDiffusionProcess.ZAR": -0.1',
              '      }',
              '    }',
              '```',
              'specifies that the correlation between the one factor hull white model for ZAR-SWAP and the lognormal',
              'process for ZAR is 0.5 while the correlation between ZAR-SWAP and',
              'the one factor hull white model for the USD-MASTER is 0.2.',
              '',
              '### Market Prices',
              '',
              'All risk neutral models need to derived from observable market prices. This section specifies both the',
              'model used and the necessary data required to correctly simulate a risk-neutral model.',
              '',
              'Currently only FX and IR rates may be risk neutral:',
              '',
              '- FX may be simulated via *GBMTSModelPrices*  and requires only a corresponding FX vol surface to',
              '  establish average ATM vols used by the corresponding *GBMAssetPriceTSModelImplied* model. It is',
              '  specified as follows:',
              '',
              '```json',
              '"GBMTSModelPrices.AUD",',
              '  {',
              '    "instrument": {',
              '      "Asset_Price_Volatility": "AUD.USD"',
              '    },',
              '    "Children": []',
              '  }',
              '```',
              '',
              '- The only risk neutral IR currently available may be simulated via ',
              '  *HullWhite2FactorInterestRateModelPrices* and requires both a corresponding swaption volatility',
              '   surface as well as a set of **instrument definitions** that define the forward starting swaps that',
              '   reference the swaption vol surface. Note that again, only ATM vols are used. They are specified as:',
              '',
              '```json',
              '"HullWhite2FactorInterestRateModelPrices.ZAR-JIBAR-3M",',
              '{',
              '	"instrument": {',
              '		"Swaption_Volatility": "ZAR_SMILE_ICE",',
              '		"Property_Aliases": null,',
              '		"Generation_Parameters": {',
              '			"Last_Tenor": {',
              '				".DateOffset": {',
              '					"years": 9',
              '				}',
              '			},',
              '			"Floating_Frequency": {',
              '				".DateOffset": {',
              '					"months": 6',
              '				}',
              '			},',
              '			"First_Tenor": {',
              '				".DateOffset": {',
              '					"years": 1',
              '				}',
              '			},',
              '			"Day_Count": "ACT_365",',
              '			"Last_Maturity": {',
              '				".DateOffset": {',
              '					"years": 10',
              '				}',
              '			},',
              '			"First_Start": {',
              '				".DateOffset": {',
              '					"years": 1',
              '				}',
              '			},',
              '			"Fixed_Frequency": {',
              '				".DateOffset": {',
              '					"months": 6',
              '				}',
              '			},',
              '			"Index_Offset": 0.0,',
              '			"Last_Start": {',
              '				".DateOffset": {',
              '					"years": 9',
              '				}',
              '			},',
              '			"First_Maturity": {',
              '				".DateOffset": {',
              '					"years": 10',
              '				}',
              '			}',
              '		},',
              '		"Generate_Instruments": "No",',
              '		"Instrument_Definitions": [',
              '			{',
              '				"Floating_Frequency": {',
              '					".DateOffset": {',
              '						"months": 3',
              '					}',
              '				},',
              '				"Weight": 1.0,',
              '				"Holiday_Calendar": null,',
              '				"Day_Count": "ACT_365",',
              '				"Start": {',
              '					".DateOffset": {',
              '						"months": 3',
              '					}',
              '				},',
              '				"Fixed_Frequency": {',
              '					".DateOffset": {',
              '						"months": 3',
              '					}',
              '				},',
              '				"Tenor": {',
              '					".DateOffset": {',
              '						"years": 1',
              '					}',
              '				},',
              '				"Market_Volatility_Type": "Lognormal",',
              '				"Index_Offset": 0.0,',
              '				"Market_Volatility": {',
              '					".Percent": 0.0',
              '				}',
              '			},',
              '			{',
              '				"Floating_Frequency": {',
              '					".DateOffset": {',
              '						"months": 3',
              '					}',
              '				},',
              '				"Weight": 1.0,',
              '				"Holiday_Calendar": null,',
              '				"Day_Count": "ACT_365",',
              '				"Start": {',
              '					".DateOffset": {',
              '						"months": 3',
              '					}',
              '				},',
              '				"Fixed_Frequency": {',
              '					".DateOffset": {',
              '						"months": 3',
              '					}',
              '				},',
              '				"Tenor": {',
              '					".DateOffset": {',
              '						"years": 2',
              '					}',
              '				},',
              '				"Market_Volatility_Type": "Lognormal",',
              '				"Index_Offset": 0.0,',
              '				"Market_Volatility": {',
              '					".Percent": 0.0',
              '				}',
              '			},',
              '			{',
              '				"Floating_Frequency": {',
              '					".DateOffset": {',
              '						"months": 3',
              '					}',
              '				},',
              '				"Weight": 1.0,',
              '				"Holiday_Calendar": null,',
              '				"Day_Count": "ACT_365",',
              '				"Start": {',
              '					".DateOffset": {',
              '						"months": 3',
              '					}',
              '				},',
              '				"Fixed_Frequency": {',
              '					".DateOffset": {',
              '						"months": 3',
              '					}',
              '				},',
              '				"Tenor": {',
              '					".DateOffset": {',
              '						"years": 5',
              '					}',
              '				},',
              '				"Market_Volatility_Type": "Lognormal",',
              '				"Index_Offset": 0.0,',
              '				"Market_Volatility": {',
              '					".Percent": 0.0',
              '				}',
              '			},',
              '			{',
              '				"Floating_Frequency": {',
              '					".DateOffset": {',
              '						"months": 3',
              '					}',
              '				},',
              '				"Weight": 1.0,',
              '				"Holiday_Calendar": null,',
              '				"Day_Count": "ACT_365",',
              '				"Start": {',
              '					".DateOffset": {',
              '						"months": 3',
              '					}',
              '				},',
              '				"Fixed_Frequency": {',
              '					".DateOffset": {',
              '						"months": 3',
              '					}',
              '				},',
              '				"Tenor": {',
              '					".DateOffset": {',
              '						"years": 10',
              '					}',
              '				},',
              '				"Market_Volatility_Type": "Lognormal",',
              '				"Index_Offset": 0.0,',
              '				"Market_Volatility": {',
              '					".Percent": 0.0',
              '				}',
              '			},',
              '			{',
              '				"Floating_Frequency": {',
              '					".DateOffset": {',
              '						"months": 3',
              '					}',
              '				},',
              '				"Weight": 1.0,',
              '				"Holiday_Calendar": null,',
              '				"Day_Count": "ACT_365",',
              '				"Start": {',
              '					".DateOffset": {',
              '						"months": 6',
              '					}',
              '				},',
              '				"Fixed_Frequency": {',
              '					".DateOffset": {',
              '						"months": 3',
              '					}',
              '				},',
              '				"Tenor": {',
              '					".DateOffset": {',
              '						"years": 1',
              '					}',
              '				},',
              '				"Market_Volatility_Type": "Lognormal",',
              '				"Index_Offset": 0.0,',
              '				"Market_Volatility": {',
              '					".Percent": 0.0',
              '				}',
              '			},',
              '			...',
              '			{',
              '				"Floating_Frequency": {',
              '					".DateOffset": {',
              '						"months": 3',
              '					}',
              '				},',
              '				"Weight": 1.0,',
              '				"Holiday_Calendar": null,',
              '				"Day_Count": "ACT_365",',
              '				"Start": {',
              '					".DateOffset": {',
              '						"years": 10',
              '					}',
              '				},',
              '				"Fixed_Frequency": {',
              '					".DateOffset": {',
              '						"months": 3',
              '					}',
              '				},',
              '				"Tenor": {',
              '					".DateOffset": {',
              '						"years": 2',
              '					}',
              '				},',
              '				"Market_Volatility_Type": "Lognormal",',
              '				"Index_Offset": 0.0,',
              '				"Market_Volatility": {',
              '					".Percent": 0.0',
              '				}',
              '			},',
              '			{',
              '				"Floating_Frequency": {',
              '					".DateOffset": {',
              '						"months": 3',
              '					}',
              '				},',
              '				"Weight": 1.0,',
              '				"Holiday_Calendar": null,',
              '				"Day_Count": "ACT_365",',
              '				"Start": {',
              '					".DateOffset": {',
              '						"years": 10',
              '					}',
              '				},',
              '				"Fixed_Frequency": {',
              '					".DateOffset": {',
              '						"months": 3',
              '					}',
              '				},',
              '				"Tenor": {',
              '					".DateOffset": {',
              '						"years": 5',
              '					}',
              '				},',
              '				"Market_Volatility_Type": "Lognormal",',
              '				"Index_Offset": 0.0,',
              '				"Market_Volatility": {',
              '					".Percent": 0.0',
              '				}',
              '			},',
              '			{',
              '				"Floating_Frequency": {',
              '					".DateOffset": {',
              '						"months": 3',
              '					}',
              '				},',
              '				"Weight": 1.0,',
              '				"Holiday_Calendar": null,',
              '				"Day_Count": "ACT_365",',
              '				"Start": {',
              '					".DateOffset": {',
              '						"years": 10',
              '					}',
              '				},',
              '				"Fixed_Frequency": {',
              '					".DateOffset": {',
              '						"months": 3',
              '					}',
              '				},',
              '				"Tenor": {',
              '					".DateOffset": {',
              '						"years": 10',
              '					}',
              '				},',
              '				"Market_Volatility_Type": "Lognormal",',
              '				"Index_Offset": 0.0,',
              '				"Market_Volatility": {',
              '					".Percent": 0.0',
              '				}',
              '			}',
              '		]',
              '	},',
              '	"Children": []',
              '}',
              '```',
              'Note that although *Generation paramaters* can be specified, instrument definitions are preferred.',
              '',
              '### Bootstrapper Configuration',
              '',
              'This section links the price factors to the market prices from the previous section as well as',
              'adding any extra parameters required for calibration',
              '',
              'The 2 bootstrapper configurations so far supported are:',
              '',
              '```json',
              '"GBMAssetPriceTSModelParameters": "GBMAssetPriceTSModelPrices"',
              '"HullWhite2FactorModelParameters": "HullWhite2FactorInterestRateModelPrices"',
              '```',
              '',
              '## Trade Data',
              '',
              'This is a JSON object representing the portfolio of trades belonging to a single netting set. As as',
              'example, consider booking a **FXNonDeliverableForward** inside',
              'an uncollateralized netting set. ',
              '```json',
              '{',
              '  "Deals": {',
              '    "Children": [',
              '      {',
              '        "instrument": {',
              '          ".Deal": {',
              '            "Object": "NettingCollateralSet",',
              '            "Reference": "Test",',
              '            "Tags": "",',
              '            "Collateralized": "False",',
              '            "Netted": "True",',
              '          }',
              '        },',
              '        "Children": [',
              '          {',
              '            "instrument": {',
              '              ".Deal": {',
              '                "Object": "FXNonDeliverableForward",',
              '                "Reference": "341",',
              '                "Tags": "",',
              '                "MtM": "",',
              '                "Sell_Currency": "USD",',
              '                "Sell_Amount": 1000,',
              '                "Settlement_Date": {',
              '                  ".Timestamp": "2017-08-31"',
              '                },',
              '                "Settlement_Currency": "ZAR",',
              '                "Buy_Amount": 14000,',
              '                "Discount_Rate": "ZAR-SWAP",',
              '                "Buy_Currency": "ZAR"',
              '              }',
              '            }',
              '          }',
              '        ]',
              '      }',
              '    ]',
              '  }',
              '}',
              '```',
              'The JSON is parsed into python dictionaries and lists. However, note that objects beginning with a',
              'period (e.g. .Deal, .Timestamp etc.) will convert the enclosed dictionary/list into the corresponding',
              'python object. When defining Deals, any number of key-value attributes may be specified as it\'s loaded',
              'directly as a python dictionary.',
              '',
              '## Calendars',
              '',
              'Optionally, an XML calendar file may be loaded defining one more set of business days i.e.',
              '',
              '```xml',
              '<Calendars>',
              '  <Calendar Location="Johannesburg" Weekends="Saturday and Sunday" Holidays="2016-01-01|New Year\'s Day,'
              '2016-03-21|Human Rights Day, ... ,2047-12-26|Day of Goodwill" />',
              '  <Calendar Location="Kabul" Weekends="Friday" Holidays="2016-02-15|Liberation Day, 2016-03-20|'
              'Noruz (New Year) 2, ... , 2047-10-30|Ashoora*" />',
              '</Calendars>',
              '```',
              '',
              ]),
            ('Calculations', [
                'To use the models and valuations in the previous sections, a **Calculation** object needs to be',
                'constructed and correctly setup. Note that all calculations need a **calc_name** field as a',
                'description.',
            ]),
            ('Examples',
             ['Assume we have the following market data file:',
              '```json',
              '{',
              '  "MarketData": {',
              '    "Market Prices": {},',
              '    "Price Factors": {',
              '      "FxRate.USD": {',
              '        "Spot": 1,',
              '        "Domestic_Currency": "",',
              '        "Interest_Rate": "USD-MASTER"',
              '      },',
              '      "InterestRate.ZAR-SWAP": {',
              '        "Curve": {',
              '          ".Curve": {',
              '            "meta": [],',
              '            "data": [[0.00274, 0.05], [10, 0.08]]',
              '          }',
              '        },',
              '        "Sub_Type": "",',
              '        "Day_Count": "ACT_365",',
              '        "Accrual_Calendar": "",',
              '        "Currency": ""',
              '      },',
              '      "InterestRate.ZAR-SWAP.ZAR-USD-BASIS": {',
              '        "Curve": {',
              '          ".Curve": {',
              '            "meta": [],',
              '            "data": [[0.00274,0.01], [10,-0.01]]',
              '          }',
              '        },',
              '        "Sub_Type": "",',
              '        "Day_Count": "ACT_365",',
              '        "Accrual_Calendar": "",',
              '        "Currency": ""',
              '      },',
              '      "InterestRate.USD-MASTER": {',
              '        "Curve": {',
              '          ".Curve": {',
              '            "meta": [],',
              '            "data": [[0.00274,0.01], [10,0.02]]',
              '          }',
              '        },',
              '        "Sub_Type": "",',
              '        "Day_Count": "ACT_365",',
              '        "Accrual_Calendar": "",',
              '        "Currency": "USD"',
              '      },',
              '      "FxRate.ZAR": {',
              '        "Domestic_Currency": "USD",',
              '        "Interest_Rate": "ZAR-SWAP.ZAR-USD-BASIS",',
              '        "Spot": 0.07',
              '      }',
              '    },',
              '    "System Parameters": {',
              '      "Base_Currency": "USD",',
              '      "Correlations_Healing_Method": "Eigenvalue_Raising"',
              '    },',
              '    "Correlations": {',
              '      "HWInterestRate.ZAR-SWAP.F1": {',
              '        "HWInterestRate.USD-MASTER.F1": 0.2,',
              '        "LognormalDiffusionProcess.ZAR": 0.5',
              '      },',
              '      "HWInterestRate.USD-MASTER.F1": {',
              '        "LognormalDiffusionProcess.ZAR": -0.1',
              '      }',
              '    },',
              '    "Price Models": {',
              '      "HullWhite1FactorInterestRateModel.USD-MASTER": {',
              '        "Alpha": 1,',
              '        "Lambda": 0,',
              '        "Sigma": {',
              '          ".Curve": {',
              '            "meta": [],',
              '            "data": [[0,0.004]]',
              '          }',
              '        },',
              '		"Quanto_FX_Volatility":null',
              '      },',
              '      "HullWhite1FactorInterestRateModel.ZAR-SWAP": {',
              '        "Alpha": 2,',
              '        "Lambda": 0,',
              '        "Sigma": {',
              '          ".Curve": {',
              '            "meta": [],',
              '            "data": [[0,0.005]]',
              '          }',
              '        },',
              '		"Quanto_FX_Volatility":null',
              '      },',
              '      "GBMAssetPriceModel.ZAR": {',
              '        "Drift": -0.03,',
              '        "Vol": 0.17',
              '      },',
              '      "HullWhite1FactorInterestRateModel.ZAR-SWAP.ZAR-USD-BASIS": {',
              '        "Alpha": 3.5,',
              '        "Lambda": 0,',
              '        "Sigma": {',
              '          ".Curve": {',
              '            "meta": [],',
              '            "data": [[0,0.01]]',
              '          }',
              '        },',
              '		"Quanto_FX_Volatility":null',
              '      }',
              '    },',
              '    "Model Configuration": {',
              '      ".ModelParams": {',
              '        "modeldefaults": {',
              '          "FxRate": "GBMAssetPriceModel",',
              '          "InterestRate": "HullWhite1FactorInterestRateModel"',
              '        },',
              '        "modelfilters": {}',
              '      }',
              '    }',
              '  },',
              '  "Version": null',
              '}',
              '```',
              'and the trade data file defined [earlier](Data#trade-data)',
              '',
              'Everything in RiskFlow is based off a *Context*. All calculations are constructed with reference to one.',
              'Note that the interest rate curves start one day from now i.e. $1/365\\approx 0.00274$. No interest rate',
              'curve can start at time 0 (although the rate at time 0 is flat extrapolated from the first timepoint).',
              '',
              'Assume the Market Data file is called *MarketData.json*, the trade data is called *fxfwd.json* and the',
              'calendar file is called *calendars.xml*. Here\'s how to perform a *Base Revaluation*:',
              '',
              '```python',
              'import riskflow',
              '',
              '',
              '#create a calculation context',
              'cx      = riskflow.Context()',
              '',
              '#load calendars',
              'cx.parse_calendar_file(\'calendars.xml\')',
              '',
              '#load marketdata',
              'cx.parse_json(\'MarketData.json\')',
              '',
              '#load tradedata',
              'cx.parse_json(\'fxfwd.json\')',
              '',
              '#all calculations take a context as an input',
              'calc 	 = riskflow.calculation.construct_calculation(\'Base_Revaluation\', cx)',
              '',
              '#execute the calculation with the following parameters',
              'out 		= calc.execute ( { \'calc_name\':(\'test1\',), \'Run_Date\':\'2017-08-01\',',
              '\'Currency\':\'ZAR\' } )',
              '```',
              '',
              '```out``` will now contain the stats for the computation in a dictionary with the field',
              '*Result* containing the results.',
              'To check the results, use the following code:',
              '```python',
              'out[\'Results\']',
              '```',
              'should return a pandas dataframe and look like:',
              '```',
              'Test	NettingCollateralSet	0.0',
              '	341	FXNonDeliverableForward	-343.123474121',
              '```',
              'So the market value at 1 August 2017 of the forward is -343 ZAR. If a credit simulation was',
              'needed, we could reuse the context and construct a new calculation',
              '```python',
              '#first define the parameters',
              'time_grid = \'0d 2d 1w(1w) 3m(1m) 2y(3m)\'',
              '',
              'params 	= { \'calc_name\':(\'test2\',), \'Time_grid\':time_grid,',
              '             \'Run_Date\':\'2017-08-01\', \'Currency\':\'ZAR\', \'Simulation_Batches\':10,',
              '             \'Batch_Size\':512, \'Random_Seed\':6126, \'Calc_Scenarios\':\'No\'',
              '             \'Generate_Cashflows\':\'Yes\', \'Dynamic_Scenario_Dates\': \'Yes\'',
              '           }',
              '',
              'cmc 	 = riskflow.Calculation.construct_calculation(\'Credit_Monte_Carlo\', cx)',
              '',
              '#execute the calculation with the previous parameters',
              'out 		= cmc.execute ( params )',
              '```',
              'To see the output, access the ```Results``` key i.e.',
              '```python',
              'out[\'Results\'])',
              '```',
              'should output',
              '```',
              '				EE         PFE',
              '2017-08-01    0.000000    0.000000',
              '2017-08-03    1.809047    0.000000',
              '2017-08-08   25.414378  201.102859',
              '2017-08-15   62.647971  414.040855',
              '2017-08-22   96.029947  574.368042',
              '2017-08-29  130.653986  737.920593',
              '2017-08-31  132.900141  745.158432',
              '2017-09-01    0.000000    0.000000',
              '```',
              'Where **EE** is the Expected Exposure and **PFE** is the Peak Exposure at 95% (the default). Note that',
              'this returns a pandas dataframe and as such, can be plotted by using the ```.plot()``` method',
              '(assuming *matplotlib* is installed).'
              ]),
        ])
    }

    def __init__(self, project_dir):
        self.project_dir = project_dir
        self.docdir = os.path.join(self.project_dir, 'docs')

    @staticmethod
    def config(generated_docs):
        return ['site_name: RiskFlow',
                '',
                'theme: readthedocs',
                '',
                'nav:',
                '    - Home: index.md',
                '    - Requirements: require.md'] + \
               reduce(operator.concat, [
                   ['    - {0}:'.format(section)] + [' ' * 8 + "- '{0}': '{1}'".format(k, v) for k, v in data.items()]
                   for section, data in generated_docs.items()]) + \
               ['',
                'extra_javascript:',
                '    - https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML',
                '',
                'markdown_extensions:',
                '    - mdx_math:',
                '        enable_dollar_delimiter: True']

    @staticmethod
    def requirements():
        return ['# Requirements',
                '',
                'In order to run RiskFlow, an nvidia video card with compute capability 6.1 or above (and ',
                'corresponding drivers) is strongly recommended. Most of the modules listed here can simply '
                'be installed via pip but may require a full build environment (with a C/C++ compiler). The',
                '[Anaconda](https://www.continuum.io/anaconda-overview) python distribution already comes with many',
                'of the below packages already installed. The required packages are:',
                '',
                '[Python](http://www.python.org/)>=3.6',
                '',
                '- Only python 3.6 and above is supported - this is mainly due to all dictionaries now being ordered',
                '',
                '[Numpy](http://numpy.scipy.org/)>=1.16.1',
                '',
                '- Earlier versions could work but have not been tested.',
                '',
                '[Scipy](http://scipy.org/)>=1.2.2',
                '',
                '- Currently only required for interpolation and numerical integration. Again, earlier versions could',
                'work but have not been tested.',
                '',
                '[Pandas](http://pandas.pydata.org/)>=1.0',
                '',
                '- Earlier versions could work but have not been tested.',
                '',
                '[Pytorch](https://pytorch.org/)>=1.11',
                '',
                '- This is the computational library that evaluates tensors either on CPU or GPU.',
                '',
                '[pyparsing](http://pyparsing.wikispaces.com)',
                '',
                '- Required for simple parsing of time grids.',
                '',
                '## Optional requirements',
                '',
                '[NVIDIA CUDA drivers and SDK](http://developer.nvidia.com/object/gpucomputing.html)',
                '',
                '- Needed for GPU code execution. This is needed by Pytorch if GPU computation is required',
                '',
                '[Matplotlib](https://matplotlib.org/)>=3.0.0',
                '',
                '- Needed for generating plots of risk factors and simualted paths',
                '',
                '[mkdocs](http://www.mkdocs.org/)>=0.16',
                '',
                '- Needed for building this documentation. Note that the math formatting is done via',
                '[python-markdown-math](https://github.com/mitya57/python-markdown-math/) and also needs to be',
                'installed.'
                ]

    @staticmethod
    def home():
        return ['# Welcome to RiskFlow',
                '',
                'RiskFlow is a python framework for performing derivatives pricing and related quantitative finance',
                'by utilizing Facebook\'s Pytorch library. Riskflow is designed to work either on CPU\'s or nvidia',
                'GPU\'s via [CUDA](https://developer.nvidia.com/cuda-zone).',
                '',
                '## Features',
                '',
                '* Fast prototyping and interactive scripting of new instruments in Python',
                '* Theoretical documentation for the pricing and simulation of financial derivatives',
                '* Monte Carlo simulation of a portfolio of trades through time allowing fast $XVA$ calculations',
                '* Automatic Derivatives for sensitivities calculation via pytorch',
                '',
                '## Motivation',
                '',
                'Similar to other open source quantitative finance libraries (like [quantlib](http://quantlib.org/)),',
                'the motivations for RiskFlow are:',
                '',
                '- Stop re-inventing the wheel. Robust implementations of standard pricing functions (like Black',
                'Scholes) have been written multiple times and as a result of regulation, have had to be independently',
                'validated as many times.',
                '- Encouraging open collaboration via the philosophy of open source software.',
                '',
                'Libraries like quantlib already do an excellent job of the above. RiskFlow attempts to also:',
                '',
                '- Make use of modern GPU\'s to perform full portfolio monte carlo simulation.',
                '- Provide theoretical documentation as part of the library thereby encouraging model validation (which',
                'can then be added to the library).',
                '- Standardize the way in which market and trade data is loaded and stored in the form of JSON files.',
                '- Offer a simpler alternative to quantlib by utilizing python as its main development language.',
                '',
                '## Roadmap',
                '',
                'Although most major asset classes have been implemented, there is still considerable room for',
                'refinement. In addition to adding more assets/pricing functions, there is also the following:',
                '',
                '- Bootstrapping yield curves from benchmark FRA\'s and swaps',
                '- Bootstrapping volatility surfaces for FX and interest rates',
                '- Incorporating Wrong way risk during the Monte Carlo simulation',
                '- Calibration of risk neutral price models from market data',
                '- Better handling of RFR\'s and OIS curves',
                ]

    def fetchdocumentation(self, section, module, attrib='documentation'):
        subdocdir = os.path.join(self.docdir, section)
        module_docs = fetch_module_documentation(module, attrib)
        if not os.path.isdir(subdocdir):
            os.mkdir(subdocdir)

        mdfiles = OrderedDict()
        for k, v in self.mkdown[section].items():
            doc = v[:] + ['', '---', '']
            md_file = k.replace(' ', '_') + '.md'

            if k in module_docs:
                for class_name, md_string in module_docs[k]:
                    doc.extend(['', '## {0}'.format(class_name), ''] + md_string)

            with open(os.path.join(subdocdir, md_file), 'wt') as f:
                f.write('\n'.join(doc))
            mdfiles[k] = '{0}/{1}'.format(section, md_file)

        return mdfiles

    def build(self):
        if not os.path.isdir(self.docdir):
            os.mkdir(self.docdir)

        # make the pages
        for page, method in [('index.md', self.home), ('require.md', self.requirements)]:
            with open(os.path.join(self.docdir, page), 'wt') as f:
                f.write('\n'.join(method()))

        # fetch the embedded documentation:
        docs = OrderedDict([('Theory', self.fetchdocumentation('Theory', 'stochasticprocess')),
                            ('Valuation', self.fetchdocumentation('Valuation', 'instruments')),
                            ('Boostrapping', self.fetchdocumentation('Boostrapping', 'bootstrappers')),
                            ('API', self.fetchdocumentation('API', 'calculation')),
                            ('JSON Structures', self.fetchdocumentation('JSON', 'riskfactors', 'field_desc'))
                            ])

        # finally the config file
        with open(os.path.join(self.project_dir, 'mkdocs.yml'), 'wt') as f:
            f.write('\n'.join(self.config(docs)))


if __name__ == '__main__':
    '''Documentation is generated for mkdocs (https://www.mkdocs.org/). Run mkdocs serv in the 
    correct folder to serve the documentation (or build it for static distribution). 
    Please note that python-markdown-math needs to be installed for this to work - can be obtained via PyPI
    (pip install python-markdown-math)'''

    md = ConstructMarkdown(r'..')
    md.build()
