Calculate contributions changing at set rate toward known future value - quantitative-finance

I need to solve a financial math problem. I have a revenue goal set based on target company growth rate. Given this total revenue goal for next year, I need to set sales goals each month that have the growth rate (monthly) applied to them. They will total the annual revenue goal. What this looks like is contributions that increase every occurrence by a set rate. Once I determine either the first or last month's goal, I can discount back or find the future values easily.
The problem I have is that I know what these goals need to total, but not what the first or last goal would equal. Hypothetically, I supposed I could use the mean goal (annual goal/12) to give me the goal for the middle of the year and discount back and scale up from June. However, since there is a growth rate, the compounding causes exponential rather than linear growth of the goals. What kind of formula can I use to solve this? Would I treat this as ongoing (but changing) contributions toward an investment with a set future value and growth rate? Or is there some sort of Goal Solver functionality that will help? I am currently doing this in Google Sheets but can switch to Excel or another medium. (I use R heavily, so not afraid of some programmatic methods).
If I cannot figure this out, I will just apply a linear function to it and use the difference in revenue each year as the slope.

Approach:
Let's assume your business starts in Sep-2017, a Month 0, with S units sold.
The constant growth rate, for each next month, was defined in your Business Case as a q, equal to 8% ( 1.08 )
Month 0: S [units], be it 1, 3 or 76,538,112,257
Month 1: S * q
Month 2: S * q * q
Month 3: S * q * q * q
..
Month 11: S * q * q * q * ... * q
>>> S = 1
>>> q = 1.08
>>> [ S * ( q ** i ) for i in range( 12 ) ]
[ 1.0,
1.08,
1.1664,
1.2597120000000002,
1.3604889600000003,
1.4693280768000005,
1.5868743229440005,
1.7138242687795209,
1.8509302102818825,
1.9990046271044333,
2.158924997272788,
2.331638997054611
]
The S units "Scale-free" sum ( independent on the initial amount )
help determine the relation between the target T units sold in total and any S, given q
>>> sum( [ S * ( q**i ) for i in range( 12 ) ] )
18.977126460237237
Here one can see, how inaccurate would be any attempt to use averages and similar guesses to approximate the progress of the powers of q during the period of compounding a constant growth rate ( yielding a T of ~ 19 x the S over 12 months at a given constant rate q of just 8% -- do not hesitate to experiment with other values of q to see the effect sharper and sharper ).
So for an example of a total T of 19,000 units sold during the Year 0, keeping the growth rate of 8% p.m.:
The initial seed for S would be a target T divided by the sum of ( constant growth ) scaling coefficients:
T / sum( [ S * ( q**i ) for i in range( 12 ) ] )
To be on the safer side,
>>> int( 1 + T / sum( [ S * ( q**i ) for i in range( 12 ) ] ) )
1002
>>> sum( [ 1002 * ( q**i ) for i in range( 12 ) ] )
19015.08 ...
>>> [ int( 1002 * ( q**i ) ) for i in range( 12 ) ]
[ 1002,
1082,
1168,
1262,
1363,
1472,
1590,
1717,
1854,
2003,
2163,
2336
]
Month 0: S ~ 1,002 [units]
Month 1: S * q ~ 1,082
Month 2: S * q * q ~ 1,168
Month 3: S * q * q * q ~ 1,262
.. ~ 1,363
. ~ 1,472
~ 1,590
~ 1,717
~ 1,854
. ~ 2,003
.. ~ 2,163
Month 11: S * q * q * q * ... * q ~ 2,336
_____________________________________________________________
19,012 [unit] per Year 0
So Good Luck & Go Get It Sold!

Related

Dynamic Programming Problem - Maximize Profit by Selling Stocks

I am looking at this code challenge:
You are selling stocks over n days and you have x number of stocks.
x = y1 + y2 + ... + yn denoting the number of stocks you sell per day over n days.
There is a list of default prices for each day p[1..n] and a list of selling deduction f[0..x].
Selling deduction depends on how many stocks you sell at a time hence 0 to x.
Actual price per day depends on how many stocks you sell.
For instance, p[1] is 500 and f[120] is 60. If you have 200 stocks and you sell 120 on day 1.
Profit = 120 * (500 - 60) = 50400
The deduction carries on into subsequent days, so if you sell the remaining stocks on day 2 with p[2] = 300 and f[80] = 40.
Profit = 80 * (300 - 40 - 60) = 16000
I'm trying to maximize total profit by deciding how many stocks to sell on each day.
I'm not very good at DP problems and have only practiced the traditional problems. I'm getting kind of stuck on this one. I think the approach might use a 3D array with x, n, and p being number of stocks, number of days, and price on that day after the deductions from previous days and the day of if applicable.
I'm trying to figure out the recurrence first for P(x,i,p) denoting maximum profit by selling x shares by day i with p being the price of stocks on day i, but I'm getting stuck as well trying to figure out patterns by working with small examples.
How can I approach this?
One simple recursive that could solve this problem in O(x * n) is like bellow (Where x is the total amount of stocks and n is the total number of days) :
p = [100, 200, 90, 190]
f = [1, 3, 4, 5, 6, 3, 5]
def max_profit(stocks, day):
if day == 1:
return stocks * (p[day - 1] - f[stocks - 1]), [stocks]
max = 0
history = []
for i in range(0, stocks + 1):
prev_profit, prev_history = max_profit(stocks - i, day - 1)
profit = prev_profit + i * (p[day - 1] * f[stocks - 1])
if profit > max:
max = profit
history = prev_history
history.append(i)
return max, history
print(max_profit(7, 4))
In this algorithm I've considered all the ways that is possible to sell stock, I mean 0 share , 1 share, 2 share , .... x shares, and then called max_profit for previouse day recursively.

A variant of the Knapsack algorithm

I have a list of items, a, b, c,..., each of which has a weight and a value.
The 'ordinary' Knapsack algorithm will find the selection of items that maximises the value of the selected items, whilst ensuring that the weight is below a given constraint.
The problem I have is slightly different. I wish to minimise the value (easy enough by using the reciprocal of the value), whilst ensuring that the weight is at least the value of the given constraint, not less than or equal to the constraint.
I have tried re-routing the idea through the ordinary Knapsack algorithm, but this can't be done. I was hoping there is another combinatorial algorithm that I am not aware of that does this.
In the german wiki it's formalized as:
finite set of objects U
w: weight-function
v: value-function
w: U -> R
v: U -> R
B in R # constraint rhs
Find subset K in U subject to:
sum( w(u) <= B ) | all w in K
such that:
max sum( v(u) ) | all u in K
So there is no restriction like nonnegativity.
Just use negative weights, negative values and a negative B.
The basic concept is:
sum( w(u) ) <= B | all w in K
<->
-sum( w(u) ) >= -B | all w in K
So in your case:
classic constraint: x0 + x1 <= B | 3 + 7 <= 12 Y | 3 + 10 <= 12 N
becomes: -x0 - x1 <= -B |-3 - 7 <=-12 N |-3 - 10 <=-12 Y
So for a given implementation it depends on the software if this is allowed. In terms of the optimization-problem, there is no problem. The integer-programming formulation for your case is as natural as the classic one (and bounded).
Python Demo based on Integer-Programming
Code
import numpy as np
import scipy.sparse as sp
from cylp.cy import CyClpSimplex
np.random.seed(1)
""" INSTANCE """
weight = np.random.randint(50, size = 5)
value = np.random.randint(50, size = 5)
capacity = 50
""" SOLVE """
n = weight.shape[0]
model = CyClpSimplex()
x = model.addVariable('x', n, isInt=True)
model.objective = value # MODIFICATION: default = minimize!
model += sp.eye(n) * x >= np.zeros(n) # could be improved
model += sp.eye(n) * x <= np.ones(n) # """
model += np.matrix(-weight) * x <= -capacity # MODIFICATION
cbcModel = model.getCbcModel()
cbcModel.logLevel = True
status = cbcModel.solve()
x_sol = np.array(cbcModel.primalVariableSolution['x'].round()).astype(int) # assumes existence
print("INSTANCE")
print(" weights: ", weight)
print(" values: ", value)
print(" capacity: ", capacity)
print("Solution")
print(x_sol)
print("sum weight: ", x_sol.dot(weight))
print("value: ", x_sol.dot(value))
Small remarks
This code is just a demo using a somewhat low-level like library and there are other tools available which might be better suited (e.g. windows: pulp)
it's the classic integer-programming formulation from wiki modifies as mentioned above
it will scale very well as the underlying solver is pretty good
as written, it's solving the 0-1 knapsack (only variable bounds would need to be changed)
Small look at the core-code:
# create model
model = CyClpSimplex()
# create one variable for each how-often-do-i-pick-this-item decision
# variable needs to be integer (or binary for 0-1 knapsack)
x = model.addVariable('x', n, isInt=True)
# the objective value of our IP: a linear-function
# cylp only needs the coefficients of this function: c0*x0 + c1*x1 + c2*x2...
# we only need our value vector
model.objective = value # MODIFICATION: default = minimize!
# WARNING: typically one should always use variable-bounds
# (cylp problems...)
# workaround: express bounds lower_bound <= var <= upper_bound as two constraints
# a constraint is an affine-expression
# sp.eye creates a sparse-diagonal with 1's
# example: sp.eye(3) * x >= 5
# 1 0 0 -> 1 * x0 + 0 * x1 + 0 * x2 >= 5
# 0 1 0 -> 0 * x0 + 1 * x1 + 0 * x2 >= 5
# 0 0 1 -> 0 * x0 + 0 * x1 + 1 * x2 >= 5
model += sp.eye(n) * x >= np.zeros(n) # could be improved
model += sp.eye(n) * x <= np.ones(n) # """
# cylp somewhat outdated: need numpy's matrix class
# apart from that it's just the weight-constraint as defined at wiki
# same affine-expression as above (but only a row-vector-like matrix)
model += np.matrix(-weight) * x <= -capacity # MODIFICATION
# internal conversion of type neeeded to treat it as IP (or else it would be
LP)
cbcModel = model.getCbcModel()
cbcModel.logLevel = True
status = cbcModel.solve()
# type-casting
x_sol = np.array(cbcModel.primalVariableSolution['x'].round()).astype(int)
Output
Welcome to the CBC MILP Solver
Version: 2.9.9
Build Date: Jan 15 2018
command line - ICbcModel -solve -quit (default strategy 1)
Continuous objective value is 4.88372 - 0.00 seconds
Cgl0004I processed model has 1 rows, 4 columns (4 integer (4 of which binary)) and 4 elements
Cutoff increment increased from 1e-05 to 0.9999
Cbc0038I Initial state - 0 integers unsatisfied sum - 0
Cbc0038I Solution found of 5
Cbc0038I Before mini branch and bound, 4 integers at bound fixed and 0 continuous
Cbc0038I Mini branch and bound did not improve solution (0.00 seconds)
Cbc0038I After 0.00 seconds - Feasibility pump exiting with objective of 5 - took 0.00 seconds
Cbc0012I Integer solution of 5 found by feasibility pump after 0 iterations and 0 nodes (0.00 seconds)
Cbc0001I Search completed - best objective 5, took 0 iterations and 0 nodes (0.00 seconds)
Cbc0035I Maximum depth 0, 0 variables fixed on reduced cost
Cuts at root node changed objective from 5 to 5
Probing was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
Gomory was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
Knapsack was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
Clique was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
MixedIntegerRounding2 was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
FlowCover was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
TwoMirCuts was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
Result - Optimal solution found
Objective value: 5.00000000
Enumerated nodes: 0
Total iterations: 0
Time (CPU seconds): 0.00
Time (Wallclock seconds): 0.00
Total time (CPU seconds): 0.00 (Wallclock seconds): 0.00
INSTANCE
weights: [37 43 12 8 9]
values: [11 5 15 0 16]
capacity: 50
Solution
[0 1 0 1 0]
sum weight: 51
value: 5

Find the nearest nice number

Given a base currency of GBP £, and a table of other currencies accepted in a shop:
Currency Symbol Subunits LastToGBPRate
------------------------------------------------------
US Dollars $ 100 0.592662000
Euros € 100 0.810237000
Japanese Yen ¥ 1 0.005834610
Bitcoin ฿ 100000000 301.200000000
We have a working method that converts a given amount in GBP Pence (AKA cents) into Currency X cents. Given a price of 999 (£9.99), for the above currencies it would return:
Currency Symbol
---------------------
US Dollars 1686
Euros 1233
Japanese Yen 1755
Bitcoin 3482570
This is all working absolutely fine. We then have a Format Currency method which converts them all into nice looking numbers:
Currency Formatted
---------------------
US Dollars $16.86
Euros €12.33
Japanese Yen ¥1755
Bitcoin ฿0.03482570
Now the problem we want to solve, is to round these amounts to the nearest meaningful pretty number in a general purpose algorithm given the information above.
This serves two important benefits:
Prices for most currencies should appear static for visitors over short-medium term time frames
Presents the visitor with a culturally meaningul price point which encourages sales
A meaningful number is one where the smallest unit displayed isn't smaller than the value of say £0.10, and a pretty number is one which ends in 49 or 99. Example outputs:
Currency Formatted Meaninful and Pretty
-----------------------------------------------------
US Dollars $16.86 $16.99
Euros €12.33 €12.49
Japanese Yen ¥1755 ¥1749
Bitcoin ฿0.03482570 ฿0.0349
I know it is possible to do this with a single algorithm with all the information given, but I'm struggling to work out even where to start. Can anyone show me how to achieve this, or give pointers?
Please note, storing a general formatting rule for each currency is not adequate because assume for example the price of Bitcoin 10x's, the formatting rule will need updating. I'm looking for a solution that doesn't need any manual maintainance/checking.
For a given decimal value X, you want to find the smallest integer Y such that YA + B as close as possible to X, for some given A and B. E.g. in the case of dollar, you have A = .5 and B = .49.
In general, for your problem, A and B can be computed via the formula:
V = value of £0.10 in target currency
K = smallest power of ten (10^k) such that 9*10^k >= V
and k <= -2 (this condition I added based on your examples, but contrary
to your definition)
= 10^min(-2, ceil(log10(V / 9)))
A = 50 * K
B = 49 * K
Note that without the extra condition, since 0.09 dollars is less than 0.10 pounds, we would get 14.9 as the result for 16.86 dollars.
With some transformation we get
Y ~ (X - B) / A
And since Y is integer, we have
Y = round((X - B) / A)
The result is then YA + B.
Convert £0.10 to the current currency to determine the smallest displayable digit (SDD)
(bounded by the number of available digits in that currency).
Now we basically have 3 choices of numbers:
... (3rdSDD-1) 9 9 (if 3rdSDD is 0, it will obviously carry from 4thSDD and so on, as subtraction normally works)
We'll pick this when 10*2ndSDD + 1stSDD < 24
... 3rdSDD 4 9
We'll pick this when 24 <= 10*2ndSDD + 1stSDD < 74
... 3rdSDD 9 9
We'll pick this when 74 < 10*2ndSDD + 1stSDD
It should be trivial to figure it out from here.
Some multiplication and modulus to get you 2ndSDD and 1stSDD.
Basic subtraction to get you ... (3rdSDD-1).
A few if-statements to pick one of the above cases.
Example:
For $16.86, our 3 choices are $15.99, $16.49 and $16.99.
We pick $16.99 since 74 < 86.
For €12.33, our 3 choices are €11.99, €12.49 and €12.99.
We pick €12.49 since 24 <= 33 < 74.
For ¥1755, our 3 choices are ¥1699, ¥1749 and ¥1799.
We pick ¥1749 since 24 <= 55 < 74.
For ฿0.03482570, our 3 choices are ฿0.0299, ฿0.0349 and ฿0.0399.
We pick ฿0.0349 since 24 <= 48 < 74.
And, just to show the carry:
For $100000.23, our 3 choices are $99999.99, $100000.49 and $100000.99.
We pick $99999.99 since 23 < 24.
Here's an ugly answer:
def retail_round(number):
"""takes a decimal.Decimal and retail rounds it"""
ending_digits = str(number)[-2:]
if not ending_digits in ("49","99"):
rounding_adjust = (99 - int(ending_digits)) % 50
if rounding_adjust <= 25:
number = str(number)[:-2]+str(int(ending_digits)+int(rounding_adjust))
else:
if str(number)[-3] == '.':
number = str(int(number) - .01)
else:
number = str(int(str(number)[:-2]+"00")-1)
return decimal.Decimal(number)
>>> import decimal
>>> retail_round(decimal.Decimal("15.50"))
Decimal('14.99')
>>> retail_round(decimal.Decimal("15.51"))
Decimal('14.99')
>>> retail_round(decimal.Decimal("15.75"))
Decimal('15.99')
>>> retail_round(decimal.Decimal("1575"))
Decimal('1599')
>>> retail_round(decimal.Decimal("1550"))
Decimal('1499')
EDIT: this is a bit better solution, using decimal.Decimal
Currency = collections.namedtuple("Currency",["name","symbol",
"subunits"])
def retail_round(currency, amount):
"""returns a decimal.Decimal amount of the currency, rounded to
49 or 99."""
adjusted = ( amount / currency.subunits ) % 100 # last two digits
print(adjusted)
if adjusted < 24:
amount -= (adjusted + 1) * currency.subunits # down to 99
elif 24 <= adjusted < 74:
amount -= (adjusted - 49) * currency.subunits # to 49
else:
amount -= (adjusted - 99) * currency.subunits # up to 99
return amount
Calculate the maximum length of the price, assume its something like 0.00001. (You can do that by changing £0.10 to the currency, then taking the 10 base log of it, getting its ceil and that power of 10).
Eg: £0.10 = 17.1421309¥
log(17.1421309) = 1.234
ceil(1.234) = 2
10^2 = 100
so
¥174055 will be ¥174900
Adjust the number for the digit, add 1, round to 50, subtract 1:
174055 -> (round((174055/100+1)/50)*50-1)*100 = 174900
Plain and simple.

Is there an algorithm that can divide a number into three parts and have their totals match the original number?

For example if you take the following example into consideration.
100.00 - Original Number
33.33 - 1st divided by 3
33.33 - 2nd divided by 3
33.33 - 3rd divided by 3
99.99 - Is the sum of the 3 division outcomes
But i want it to match the original 100.00
One way that i saw it could be done was by taking the original number minus the first two divisions and the result would be my third number. Now if i take those 3 numbers i get my original number.
100.00 - Original Number
33.33 - 1st divided by 3
33.33 - 2nd divided by 3
33.34 - 3rd number
100.00 - Which gives me my original number correctly. (33.33+33.33+33.34 = 100.00)
Is there a formula for this either in Oracle PL/SQL or a function or something that could be implemented?
Thanks in advance!
This version takes precision as a parameter as well:
with q as (select 100 as val, 3 as parts, 2 as prec from dual)
select rownum as no
,case when rownum = parts
then val - round(val / parts, prec) * (parts - 1)
else round(val / parts, prec)
end v
from q
connect by level <= parts
no v
=== =====
1 33.33
2 33.33
3 33.34
For example, if you want to split the value among the number of days in the current month, you can do this:
with q as (select 100 as val
,extract(day from last_day(sysdate)) as parts
,2 as prec from dual)
select rownum as no
,case when rownum = parts
then val - round(val / parts, prec) * (parts - 1)
else round(val / parts, prec)
end v
from q
connect by level <= parts;
1 3.33
2 3.33
3 3.33
4 3.33
...
27 3.33
28 3.33
29 3.33
30 3.43
To apportion the value amongst each month, weighted by the number of days in each month, you could do this instead (change the level <= 3 to change the number of months it is calculated for):
with q as (
select add_months(date '2013-07-01', rownum-1) the_month
,extract(day from last_day(add_months(date '2013-07-01', rownum-1)))
as days_in_month
,100 as val
,2 as prec
from dual
connect by level <= 3)
,q2 as (
select the_month, val, prec
,round(val * days_in_month
/ sum(days_in_month) over (), prec)
as apportioned
,row_number() over (order by the_month desc)
as reverse_rn
from q)
select the_month
,case when reverse_rn = 1
then val - sum(apportioned) over (order by the_month
rows between unbounded preceding and 1 preceding)
else apportioned
end as portion
from q2;
01/JUL/13 33.7
01/AUG/13 33.7
01/SEP/13 32.6
Use rational numbers. You could store the numbers as fractions rather than simple values. That's the only way to assure that the quantity is truly split in 3, and that it adds up to the original number. Sure you can do something hacky with rounding and remainders, as long as you don't care that the portions are not exactly split in 3.
The "algorithm" is simply that
100/3 + 100/3 + 100/3 == 300/3 == 100
Store both the numerator and the denominator in separate fields, then add the numerators. You can always convert to floating point when you display the values.
The Oracle docs even have a nice example of how to implement it:
CREATE TYPE rational_type AS OBJECT
( numerator INTEGER,
denominator INTEGER,
MAP MEMBER FUNCTION rat_to_real RETURN REAL,
MEMBER PROCEDURE normalize,
MEMBER FUNCTION plus (x rational_type)
RETURN rational_type);
Here is a parameterized SQL version
SELECT COUNT (*), grp
FROM (WITH input AS (SELECT 100 p_number, 3 p_buckets FROM DUAL),
data
AS ( SELECT LEVEL id, (p_number / p_buckets) group_size
FROM input
CONNECT BY LEVEL <= p_number)
SELECT id, CEIL (ROW_NUMBER () OVER (ORDER BY id) / group_size) grp
FROM data)
GROUP BY grp
output:
COUNT(*) GRP
33 1
33 2
34 3
If you edit the input parameters (p_number and p_buckets) the SQL essentially distributes p_number as evenly as possible among the # of buckets requested (p_buckets).
I've solved this problem yesterday by subtracting 2 of 3 parts from the starting number, e.g. 100 - 33.33 - 33.33 = 33.34 and the result of summing it up is still 100.

Logic for rate approximation

I am looking for some logic to solve the below problem.
There are n transaction amounts : T1,T2,T3.. Tn.
Commission for these transactions are calculated using a rate table provided as below.
if amount between 0 and A1 -> rate is r1
if amount between A1 and A2 -> rate is r2
if amount between A2 and A1 -> rate is r3
...
...
if amount greater than An -> rate is r4
So if T1 < A1 then rate table returns r1 else if r1 < T1 < r2;it returns r2.
So,lets says the rate table results for T1,T2 and T3 are r1,r2 and r3 respectively.
Commission C = T1 * r1 + T2 * r2 + T3 * r3
e.g; if rate table is defined(rates are in %)
0 - 2500 -> 1
2501 - 5000 -> 2
5001 - 10000 -> 4
10000 or more-> 6
If T1 = 6000,T2 = 3000, T3 = 2000, then
C= 6000 * 0.04 + 3000* 0.02 + 2000 * 0.01 = 320
Now my problem is whether we can approximate the commission amount if instead of individual values of T1,T2 and T3 we are provided with T1+T2+T3 (T)
In the above example if T (11000) is applied to the rate tablewe would get 6% and which would result in a commision of 600.
Is there a way to approximate the commission value given T instead of individual values of T1,T2,T3?
Come up with some probabilities for the percentage of transactions that fall into each bracket.
P(r1) = x // The probability of a transaction falling into a rate 1 bracket
P(r2) = y // The probability of a transaction falling into a rate 2 bracket
P(r3) = z // The probability of a transaction falling into a rate 3 bracket
You can therefore estimate the amounts from the transaction that fell into each bracket
Estimated amount of commission at
rate 1: x * (T1 + T2 + T3) * r1
rate 2: y * (T1 + T2 + T3) * r2
rate 3: z * (T1 + T2 + T3) * r3
You can get estimates for x y and z by looking at historic transactions. The amount of money from a transaction you are actually charging at any rate could be less than the requirement for the bracket, but it doesn't matter. On average transactions will accrue the average rate of commission across all bands.
Though I'd like to disclaim, this will give you an estimate but the accuracy of the estimate for a single transaction depends on the standard deviation of your data set, but will on average give you a fair estimate across a large number of transactions. You need to decide if this is sensible in your use case.

Resources