<jupyter_start><jupyter_text>Financial Analysis Use this link to do the thing:https://ubc.syzygy.ca/jupyter/hub/user-redirect/git-pull?repo=https://github.com/gparadis/ubc-frst318&branch=master&subpath=frst318_lab2-part1.ipynb  IntroductionWelcome to FRST-318 Lab 2, part 1. From the lab last week, you know how to navigate and run code in Jupyter notebooks. Let get started.  OverviewThis notebook presents interactive models helping you explore financial analysis concepts like* discounting and compounding * cash flows* net present value Discounting and CompoundingThe notion of _interest_ is the _Compounding_ projects present value $V_0$, $n$ years forward, at discount rate $i$, yielding future value $V_n$.  _Discounting_ projects future value $V_n$, $n$ years back backward, at discount rate $i$, yielding present value $V_0$.  The compounding formula solves for future value $V_n$, given present value $V_0$.$$V_n = V_0(1 + i)^{n}$$The discounting formula solves for present value $V_0$, given future value $V_n$.$$V_0 = V_n(1 + i)^{-n}$$ First, we define some Python functions that implement discounting and compounding, and a function that plots compounding or discounting of a single sum to a single other time period.<jupyter_code>def discount(v, n, i):
    return v * ((1 + i)**-n)

def compound(v, n, i):
    return v * ((1 + i)**+n)

def plot_v(v=1., n=10, i=0.05, mode='c', figsize=(12, 6)):
    fig, ax = plt.subplots(figsize=figsize)
    #x = [0, n]
    #y = [v, compound(v, n, i)] if mode == 'c' else [discount(v, n, i), v]
    #ax.bar(x, y)
    if mode == 'c':
        _v = compound(v, n, i)
        ax.bar(0, v, label='reference value')
        ax.bar(n, _v, label='compounded value')
    else:
        _v = discount(v, n, i)
        ax.bar(n, v, label='reference value')
        ax.bar(0, _v, label='discounted value')
    plt.legend()
    ax.set_xlabel('n')
    ax.set_ylabel('V')
    plt.show()
    print('i', i)
    print('projected value', _v)<jupyter_output><empty_output><jupyter_text>Next, we interact with the simple model defined above. You can manipulate the reference value `v`, the number of years to project `n`, the interest rate `i`, and the function mode (`c` for compounding, `d` for discounting).<jupyter_code>interact(plot_v, 
         v=widgets.FloatSlider(value=1., min=0.01, max=10., step=0.01),
         n=widgets.IntSlider(value=10, min=0, max=100),
         i=widgets.FloatSlider(value=0.050, min=0.01, max=0.10, step=0.001),
         figsize=fixed((12, 6)))<jupyter_output><empty_output><jupyter_text>Question 1At what interest rate will \$5.00 in year 14 be worth 60\% of its original value in year 0?  Question 2How many years does it take for \$5.00 compounded at \%2.0 to double in value?   Cash flowsNext, we present a model of the Tracy Treefarmer problem from class.<jupyter_code>def npv(X, V, i):
    I = [i for x in X]
    return sum(np.vectorize(discount)(V, X, I))

def plot_cashflow(X, V, i=0.05, figsize=(12, 6), x_scale=1.):
    _npv = npv(X, V, i)
    _V = np.vectorize(discount)(V, X, [i for x in X])
    fig, ax = plt.subplots(figsize=figsize)
    ax.bar(X * x_scale, V, alpha=0.5, label='Cashflow')
    ax.bar(X * x_scale, _V, alpha=0.5, label='Cashflow')    
    ax.bar(0, _npv, alpha=0.5, label='NPV')
    plt.axhline(0.)
    ax.set_xlabel('Period')
    ax.set_ylabel('V')
    plt.xticks([i for i in range(int(X[-1]*x_scale+1))])
    plt.legend()
    plt.show()
    print('NPV at i=%0.3f: $%0.2f' % (i, _npv))
X = np.array([0, 1, 2, 3, 4, 5, 6])
V = np.array([-990, -590, -590, -590, -590, -590, +7200])
interact(plot_cashflow, X=fixed(X), V=fixed(V), figsize=fixed((12, 6)), x_scale=fixed(1.),
         i=widgets.FloatSlider(value=0.05, min=0.00, max=0.20, step=0.001))<jupyter_output><empty_output><jupyter_text>Internal Rate of ReturnThe _internal rate of return_ (IRR) is the discount rate which induces a null NPV. You can find IRR by trial and error using the interactive models in this lab by adjusting the `r` (interest rate) parameter of the cash flow unit $NPV = 0$.   Question 3What is the IRR of the cash flow in the Tracy Treefarmer problem?  Land Expectation Value (LEV)Now, lets have a look at _land expectation value_ (LEV).Recall from class that there are multiple different methods of calculating LEV, but that all methods must account for the same 4 value components:* establishment cost* intermediate revenues and costs* annual revenues and costs* final harvesting revenue and costThe following formula calculates the future value (at the end of the first rotation) for each of these value components, then applies the formula for an infinite series of periodic payments.$$LEV = \frac{-E(1+r)^R + \sum_{t=1}^{R-1}\left[I_t(1+r)^{R-t}\right] + A\left[(1+r)^R - 1\right]r^{-1} + \sum_{p=1}^{n}\left[P_pY_{pR} - C_h\right]}{(1+r)^R - 1}$$where$R$ represents rotation length (in years),$E$ represents stand establishment cost (per unit area),$A$ represents net annual revenue (per unit area),$I_t$ represents net intermediate revenue (per unit area, occurring in the interval $[1, R)$),$Y_{pR}$ represents yield (per unit area) of product $p$ at age $R$,$P_p$ represents unit price of product $P$,$n$ represents the number of products in the final harvest,$C_h$ represents unit cost of final harvest,$r$ represents the real interest rate.The code below implements a functions that calculates LEV and plot LEV, and defines some parameters that we will use in the next step to create an interactive model for a specific case. Note that NPV reported below the figure is calculated on the (finite) rotations displayed in the plot. The<jupyter_code>def pv_pps(a, i, t):
    return a * (1 / (pow(1 + i, t) - 1))

def pv_tps(a, i, t, n):
    return a * ((pow(1 + i, n*t) - 1) / ((pow(1 + i, t) - 1) * pow(1 + i, n*t)))

def lev_fvrot1(R, E, A, I, Y, P, Ch, r):
    result = -E * pow(1 + r, R)
    result += sum(I[t] * pow(1 + r, R - t) for t in I)
    result += A * (pow(1 + r, R) - 1) / r
    result += sum(P[p] * Y[p][R] - Ch for p in P)
    #result /= pow(1 + r, R) - 1
    return result

def plot_lev(R, E, A, I, Y, P, Ch, r, n):
    _lev_fvrot1 = lev_fvrot1(R, E, A, I, Y, P, Ch, r)
    X = np.array([(i + 1) * R for i in range(n)])
    V = np.array([_lev_fvrot1 for i in range(n)])
    plot_cashflow(X, V, i=r, x_scale=pow(R, -1))
    lev1 = pv_pps(_lev_fvrot1, r, R)
    lev2 = pv_tps(_lev_fvrot1, r, R, n)
    print('LEV: $%0.2f' % lev1)
    print('relative truncation error: %0.2f%%' % (100. * (lev2 - lev1) / lev1))
  

df = pd.read_csv('yields.csv', index_col='age') # import yield data from CSV file into a pandas.DataFrame


ysw = {i:df.loc[i]['sw'] for i in df.index} # define yield dict from DataFrame (softwood)
yhw = {i:df.loc[i]['hw'] for i in df.index} # define yield dict from DataFrame (hardwood)
Y = {'sw':ysw, 'hw':yhw}                    # define yields dict (softwood, hardwood)
P = {'sw':100., 'hw':100.}                  # define product unit price dict (softwood, hardwood)

# You can specify ad hoc mid-rotation cash flows here (set to null by default).
# The example below shows net revenue events of -100 in year 50 and +200 in year 60. 
#   I = {50:-100, 60:+200.}
I = {}<jupyter_output><empty_output><jupyter_text>The LEV model includes two products (softwood and hardwood), and the model is set up so that yield $Y_{pR}$ at final harvest changes as a function of both product $p$ and rotation length $R$. Lets have a look at the yield curves, which were borrowed from the Patchworks C5 sample dataset (a wood supply model for the foothills of Alberta). In order, we show softwood, hardwood and total yield (dotted grey line show peak MAI age). This should give you an idea what the optimal rotation is from a pure fibre production point of view.<jupyter_code>fig, ax = plt.subplots(3, 1, figsize=(12, 6))
df['ty'] = df['sw'] + df['hw']
for i, s in enumerate(['sw', 'hw', 'ty']):
    df['mai_%s' % s] = df[s] / df.index
    df[s].plot(ax=ax[i])
    cmai_age = df['mai_%s' % s].idxmax()
    ax[i].axvline(cmai_age, color='gray', linestyle=':')
    ax[i].set_xlabel('Age (years)')
    ax[i].set_ylabel('%s volume (m3/ha)' % s)<jupyter_output><empty_output><jupyter_text>Run the cell below to display an interactive LEV model.<jupyter_code>interact(plot_lev,
         R=widgets.FloatSlider(value=100., min=50., max=200., step=10.),
         E=widgets.FloatSlider(value=500., min=0., max=2000., step=100.),
         A=widgets.FloatSlider(value=0., min=-100., max=100., step=10.),
         I=fixed(I),
         Y=fixed(Y),
         P=fixed(P),
         Ch=widgets.FloatSlider(value=500., min=0., max=2000., step=100.),
         r=widgets.FloatSlider(value=0.01, min=0.01, max=0.20, step=0.001),
         n=widgets.IntSlider(value=1, min=1, max=20))<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.14503642987249546, 'fraction_numerical': 0.032900728597449906, 'mean_word_length': 3.8535911602209945, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 25, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '6', 'dir': 'jupyter-structured-clean-dedup', 'id': '60481', 'license': 'MIT', 'n_tokens_mistral': 3292, 'n_tokens_neox': 3085, 'n_words': 1070, 'path': 'frst318_lab2-part1.ipynb', 'repo_name': 'gparadis/ubc-frst318', 'size': '8784'}