Business Feasibility Overview

The purpose of this notebook is to analyze the feasibility of a business based on its intrinsic probabilities of loss/gain and return on investment in the cases of loss/gain.

This type of analysis refers to a very specific type of bussiness in which you have defined iterations. As far as we can think in a first approach there are 2 types of bussinessess:

  1. One starts with a principal P, bussiness has a defined madurity time T, and at the end of such maturity time the capital becomes O, in which, O = P + G, where G corresponds to the gain which can be positive or negative, each possible value of the range of G has a certain specific probability.
  2. One starts with a principal P, which is composed of a "sunken capital" S and a "working capital" W bussiness should in principle go on forever, however if bussiness does not adapt correctly to market conditions it will have an expiration date, which usually occurs, be it 100 years or 10 years, there is also a probability of initial kickstart success or failure Pk, this type of bussiness gives periodically a profit or loss G in periods of time T which are smaller than the expiration date, which is uncertain. The sunken part of the principal S devaluates (due to devaluation of assets) or valuates in time (due to brand awareness). With regard to the expiration date it is uncertain but one could assume a range in which it could take values with increasing probability of expiration as the time increases, asymptotically reaching 1 (this is the assumption that no bussiness lives forever, think universe imploding).

The questions to solve in this Notebook refer to the first type of bussiness.

Questions to solve:

Given the parameters of the business, namely:

  • The return on investment when a gain event occurs ROI_G.
  • The return on investment when a loss event occurs ROI_L.
  • The probability that a gain event occurs P_G.

Where we have made simplifying assumptions given that the ROI_G, ROI_L are continuous variable P_G(ROI_G) is actually a single continuous real function. Also, we have made the simplifying assumption that the madurity time T is always the same. Which is also not absolutely true.

  1. Starting with a principal P, after N iterations, what is the probability to see that capital become O for each possible O that is allowed by the binomial process.

  2. On would also like to see how the capital P evolves through the Bernoulli process. However since at iteration N regardless of the specific Bernoulli process what matters is where this process falls in the Binomial distribution. Each Bernoulli process has equal probability of ocurring as another which has the same amount of YES/NO Bernoulli trials in it. A graph of different timelines for each possible Bernoulli trial would be inadequate at best. Instead it would be interesting to see how the probability spreads out over the possible range of values of the Binomial process once the number of iterations increases. One would require a color plot. (Something similar to a Choropleth). This would be the time evolution of the projection to the x axis of the figure obtained in question 1.

  3. Obtain a single parameter that indicates whether a business is feasible in this sense or not. The definition of feasibility to use is to have X percent of the mass of the pmf above a certain ROI after n iterations. e.g. having 80% of the mass of the pmf above a factor of 2 or 200% ROI (profit) after 10 iterations. i.e. to have a 80% probability of earning a 200% profit after 10 iterations. According to this criteria one would determine if a business is feasible or not. To define it after n=1 iterations would just result in the original parameters. This is a special case in which the answer of the questions is simplified and does not require numerical computations.

  4. Get probability of seeing a capital decline of X percent over the next n iterations. It does not matter the nominal value of capital you start at. Produce a plot where each curve represents the decline probability vs iterations for each cutoff percentage.

  5. Based on the results of question 4 obtain the probability of bankruptcy in n iterations. The probability of bankruptcy should be defined as seeing the capital decline over X percent i.e. it would be the probability attained by performing a sum over all curves that see a capital decline bigger than the cutoff value.

Import Modules


In [1]:
# Numpy
import numpy as np
# Scipy
from scipy import stats
from scipy import linspace
# Plotly
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
import plotly.graph_objs as go
init_notebook_mode(connected=True) # Offline plotting


Define Common Parameters


In [2]:
# Probabilities
P_G = 0.8
# Return on investment rates
ROI_G = 1
ROI_L = -0.2
# Principal (initial capital)
P = 1

Question 1.

Starting with a principal P, after N iterations, what is the probability to see that capital become O for each possible O that is allowed by the binomial process.

Define the functions that will evolve the principal capital P a Binomial process.


In [3]:
# Takes the principal P and performs the evolution of the capital using 
# the result x of the random binomial variable after n trials
def evolve_with_binomial(P, x, n):
    return P * ((1 + ROI_G) ** x) * ((1 + ROI_L) ** (n - x))

Run the simulation using the Binomial process which is equivalent to performing a very large (~1000's) Bernoulli processes and grouping their results. Since the order in which 1's and 0's occur in the sequence does not affect the final result.


In [4]:
# Number of iterations
years = 5
iterations_per_year = 2
n = iterations_per_year * (years)

# Sorted array of unique values ocurring in instance of Binomial process 
x_binomial = linspace(0,n,n+1)

# Arrays of data to plot
data_dict = { 'x': [], 'y': []}
data_dict['x'] = [evolve_with_binomial(P, x, max(x_binomial)) for x in x_binomial]
data_dict['y'] = stats.binom.pmf(x_binomial,max(x_binomial),P_G)

# Plot data variable. It contains the trace objects
fig_data = [
                go.Bar( 
                        x=data_dict['x'], 
                        y=data_dict['y'], 
                        name="Probabilities" 
                ),
                go.Scatter( 
                        x=data_dict['x'], 
                        y=data_dict['y'], 
                        mode='lines+markers', 
                        name="Fitting",
                        line=dict(
                            shape='spline'
                        )
                )
            ]

# Set layout for figure
layout = go.Layout(
    title='Binomial Distribution of Capital at N Iterations',
    font=dict(
        family='Arial, sans-serif;',
        size=12,
        color='#000'
    ),
    xaxis = dict(title='Capital Multiplier'),
    yaxis = dict(title='Event Probability'),
    orientation=0,
    autosize=True,
    annotations=[
        dict(
            x=max(data_dict['x'])/2,
            y=max(data_dict['y']),
            text='N: {0} | P_G: {1}'.format(n, P_G),
            showarrow=False
        )
    ]
)

# Plot figure
#iplot({"data": fig_data, "layout": layout})

Question 2.

Plot the time evolution of the principal P through the Binomial process. Where a more intense color means a higher probability and a less intense color means a lower probability.

In [5]:
# Number of iterations
years = 5
iterations_per_year = 2
n = iterations_per_year * (years)

# Arrays of data to plot
data_dict = { 'values': [], 'probs': np.array([]), 'iterations': [], 'mean': [], 'most_prob': [], 'uniq_iterations': []}


# For each iteration less than the maximun number of iterations
i = 1
while i <= n:
    x_i = linspace(0,i,i+1) # Possible values of success event in "i" trials
    values = [evolve_with_binomial(P, x, max(x_i)) for x in x_i] # Capital evolution according to Binomial process
    probs = stats.binom.pmf(x_i,max(x_i),P_G) # Probabilities of Binomial process
    # Set values in dictionary
    data_dict['values'] = data_dict['values'] + values
    data_dict['mean'].append(np.mean(values))
    data_dict['most_prob'].append(values[np.argmax(probs)])
    data_dict['uniq_iterations'].append(i)
    data_dict['probs'] = np.concatenate((data_dict['probs'], probs), axis=0)
    data_dict['iterations'] = data_dict['iterations'] + [i]*len(x_i)
    i += 1

# Plot data variable. It contains the trace objects
fig_data = [
                go.Scatter( 
                        x=data_dict['iterations'], 
                        y=data_dict['values'], 
                        mode='markers',
                        name="Evolution",
                        marker=dict(
                            cmin = 0,
                            cmax = 1,
                            color = data_dict['probs'],
                            size = 16
                        )
                ),
                go.Scatter( 
                        x=data_dict['uniq_iterations'], 
                        y=data_dict['mean'], 
                        mode='lines+markers', 
                        name="Mean",
                        line=dict(
                            shape='spline'
                        )
                ),
                go.Scatter( 
                        x=data_dict['uniq_iterations'], 
                        y=data_dict['most_prob'], 
                        mode='lines+markers', 
                        name="Most Probable",
                        line=dict(
                            shape='spline'
                        )
                )
            ]

# Set layout for figure
layout = go.Layout(
    title='Evolution of Capital Through Binomial Process',
    font=dict(
        family='Arial, sans-serif;',
        size=12,
        color='#000'
    ),
    xaxis = dict(title='Iteration Number'),
    yaxis = dict(title='Capital Multiplier'),
    orientation=0,
    autosize=True,
    annotations=[
        dict(
            x=n/2,
            y=max(data_dict['values']),
            text='P_G: {0}'.format(P_G),
            showarrow=False
        )
    ]
)

# Plot figure
#iplot({"data": fig_data, "layout": layout})

The previous plot shows the evolution of the capital throughout the Binomial process, alongside we show the mean and the most probable value of the possible outcomes. As one increases the number of iterations the mean surpassess the most probable value for good while maintaining a very close gap.

Question 4.

We want to see how likely it is to have a capital decline of "X" percent over the next "n" iterations.

The plot we want is obtained by selecting a subset of the evolution curve. The subset of the values correspond to those where the multiplying factors are less than 1. After such values are selected one applies the transformation:

$$ y = 1-x$$

In this new scale the y value represents the capital decline.


In [6]:
# Calculate the possible capital declines and their respective probabilities 
data_dict["decline_values"] = []
data_dict["decline_probs"] = []
data_dict["decline_iterations"] = []
for index, val in enumerate(data_dict["values"]):
    if val < 1:
        data_dict["decline_values"].append((1-val)*100)
        data_dict["decline_probs"].append(100*data_dict["probs"][index])
        data_dict["decline_iterations"].append(data_dict["iterations"][index])
        
# Plot data variable. It contains the trace objects
fig_data = [
                go.Scatter( 
                        x=data_dict['decline_iterations'], 
                        y=data_dict['decline_values'], 
                        mode='markers',
                        name="Evolution",
                        marker=dict(
                            cmin = 0,
                            cmax = 1,
                            color = data_dict['decline_probs']
                        )
                )
            ]

fig_data[0].text = ["Probability: {0:.2f}%".format(prob) for prob in data_dict["decline_probs"]]

# Set layout for figure
layout = go.Layout(
    title='Possible Capital Decline Through Binomial Process',
    font=dict(
        family='Arial, sans-serif;',
        size=12,
        color='#000'
    ),
    xaxis = dict(title='Iteration Number'),
    yaxis = dict(title='Percentage Decline [%]'),
    orientation=0,
    autosize=True,
    annotations=[
        dict(
            x=max(data_dict["decline_iterations"])/2,
            y=max(data_dict['decline_values']),
            text='P_G: {0}'.format(P_G),
            showarrow=False
        )
    ]
)

# Plot figure
#iplot({"data": fig_data, "layout": layout})

Question 5.

Obtain the probability of bankrupcty after N iterations, bankruptcy is defined for the purposes of this notebook as the event in which the principal perceives a capital decline bigger than or equal to X percent


In [7]:
# Capital percentage decline of bankruptcy
CP_br = 20

# Variable to store the plot data
data_dict["bankruptcy_probs"] = []
data_dict["bankruptcy_iterations"] = []

# Calculate for each iteration the probability of bankruptcy
iter_counter = 0
for i, iteration in enumerate(data_dict["decline_iterations"]):
    if data_dict["decline_values"][i] >= CP_br:
        if iteration > iter_counter:
            data_dict["bankruptcy_probs"].append(data_dict["decline_probs"][i])
            data_dict["bankruptcy_iterations"].append(iteration)
        else:
            data_dict["bankruptcy_probs"][-1] = data_dict["bankruptcy_probs"][-1] + data_dict["decline_probs"][i]
        iter_counter = iteration

# Plot data variable. It contains the trace objects
fig_data = [
                go.Scatter( 
                        x=data_dict['bankruptcy_iterations'], 
                        y=data_dict['bankruptcy_probs'], 
                        mode='lines+markers', 
                        name="Mean",
                        line=dict(
                            shape='spline'
                        )
                )
            ]

# Set layout for figure
layout = go.Layout(
    title='Probability of Bankruptcy Through Binomial Process',
    font=dict(
        family='Arial, sans-serif;',
        size=12,
        color='#000'
    ),
    xaxis = dict(title='Iteration Number'),
    yaxis = dict(title='Event Probability [%]'),
    orientation=0,
    autosize=True,
    annotations=[
        dict(
            x=max(data_dict['bankruptcy_iterations'])/2,
            y=max(data_dict['bankruptcy_probs']),
            text='P_G: {0} | CP_br: {1}%'.format(P_G, CP_br),
            showarrow=False
        )
    ]
)

# Plot figure
#iplot({"data": fig_data, "layout": layout})