I need to implement an IF statement inside another IF statement in excel!
=IF(DataInput!$D$5 = "James Herriot Freight",
ROUND( (.0025 * I4 + .75 * O4) * T4, 2),
IF( DataInput!$D$5 = "Siegfried Farnon Transport",
ROUND( 1.5+ IF(O4 > 1.0, (O4 – 1.0) * 0.5, 0) * T4, 2),
"ERROR: Invalid Freight Type"
) )
The inner IF statement is doing a completely different check, unreleated to DataInput!$D$5. Is this even possible in excel, or do I need to look in to maybe rewriting the whole thing with and, and or as part of what I need to do? Or do I have an error somewhere else?
Related
i am trying to build compound formula with solidity but I have came across a problem, given enough days, the amount is compounded, amount will overflow uint256 range.
I have read that as long as final result is in the range of uint256, it should be fine but it does not seem to be the case. here is the calculation that i am trying to do
(100 * (100+8)^100) * 10^(6 - 2*100)
as a formula it looks like this:
( BASE * ( (1 * 10^MULTIPLIER) + (YIELD * 10^MULITPLIER) ) ^ COMPOUNDED_DAYS ) * ( 10 ^ (DECIMALS - MULTIPLIER * COMPOUNDED_DAYS) )
as mentioned this is compound formula with 6 decimals, but when i run this in playground i get "0" as a result. what's the problem, and if there is problem how can i fix it?
The reason is that your number becomes smaller than one and the integer turns it into zero
The caret sign ^ represents a bitwise XOR - not an exponential multiplication. If you want to calculate "to the power of", use two asterisks **.
Example: "10 to the power of 2" in Solidity: 10 ** 2
I am curious if there is a way to make my life easier. In excel I am producing a total value, say 750 and need to find out how many orders of pipe I need from values of 50,100,200,250,500. Is there anyway to have excel take a value and then return how many of each of these numbers I would need, so for the 750 case 1 500 and 1 250?
Currently the solution is just worked out in my head
Assuming you want to try to fit pipes in decreasing order of size,and that you have access to the required functions, you can use Reduce as demonstrated here to step through the sizes and successively divide by each one although the formula is a little laboured:
=LET(pipes,{500;250;200;100;50},reqd,750,DROP(REDUCE(0,pipes,
LAMBDA(a,c,VSTACK(a,QUOTIENT(reqd-IF(ROWS(a)>1,SUM(DROP(a,1)*TAKE(pipes,ROWS(a)-1)),0),c)))),1))
As pointed out by #Jos Woolley, this may not give you the answer you want if the total is something like 749. It will fit as many values in as possible and give a result 500+200 total 700 (remainder 49). You could fix it perhaps by rounding up to the next multiple of 50.
For the example of 823, you would have:
=LET(pipes,{500;250;200;100;50},reqd,CEILING(823,MIN(pipes)),DROP(REDUCE(0,pipes,
LAMBDA(a,c,VSTACK(a,QUOTIENT(reqd-IF(ROWS(a)>1,SUM(DROP(a,1)*TAKE(pipes,ROWS(a)-1)),0),c)))),1))
which gives 500+250+100=850.
Well I've got a bit obsessed with this now and I am determined to get a lambda working to find the optimal answer! I have been looking at the brute-force solution to finding the minimum number of coins required to make up a given total in the reference mentioned previously and have managed to translate it into a lambda using Reduce:
Mincoins1= LAMBDA(coins, m, v,
IF(
v <= 0,
0,
REDUCE(
999,
coins,
LAMBDA(a, c,
IF(v >= c, LET(mc, mincoins1.mincoins1(coins, m, v - c) + 1, IF(mc < a, mc, a)), a)
)
)
)
)
This does give the correct answer, 2, for the case when you want to make up a value of 400 from the list of pipes given. The next step will be to modify the code to return the list of pipes which give that total (200,200).
https://www.enjoyalgorithms.com/blog/minimum-coin-change
Here is the lambda modified to return a string containing the chosen pipes:
Mincoins2= LAMBDA(coins, m, v,
IF(
v <= 0,
"",
REDUCE(
rept("x",999),
coins,
LAMBDA(a, c,
IF(v >= c, LET(mc, c&"|"&mincoins2.mincoins2(coins, m, v - c), IF(len(mc) < len(a), mc, a)), a)
)
)
)
);
It does work BUT (and this is a big but) it hits a limit as soon as the value to be produced exceeds 1000 and you get a #value error. Disappointing. But interesting I think as a proof of concept.
Not sure I understand the question but lets try.
if you have 1 450 to divide, have a formula that divides 1 450 with you highest lenght (750) and then round it down.
so the formula would be something of the line: = rounddown(1 450 / 750; 0)
you will then get the answer that you need 1 of the length 750.
then keep the info about how much length you have remaining. So a formula like:
=1 450 - 750 * [the answer from previous formula = 1]. this would sum to 700.
then start over with the same thing, but divide 700 with 500 (second largest size).
Your question is extremely difficult: one might think for this easy solution, starting with value_begin:
amount_of_500 = value_begin DIV 500; // integer division
temp = value_begin - 500 * amount_of_500;
amount_of_250 = temp DIV 250; // again integer division
temp = temp - 250 * amount_of_250;
amount_of_200 = temp DIV 200; // again integer division
temp = temp - 200 * amount_of_200;
...
However, this will not work because of the value 200, which is far too close to 250: just start with value_begin equal to 400 (algorithm solution : 250 + 100 + 50, while best solution : 200 + 200).
Are you sure you need both 200 and 250 as possible numbers to divide by? If yes, you might have a serious problem getting this implemented.
I created a LAMBDA function called LOANAMT to calculate loan amounts recursively for a situation in which you need to borrow to fund the loan payment (yes, I know this can be solved algebraically - I'm trying to learn about LAMBDA).
I incorporated a tolerance check as my escape clause; if the next round of interest calculations is very close to the previous round, the LAMBDA exits. This worked fine with a hard-coded tolerance level of 0.001:
=LAMBDA(opening_balance, base_rate, [interest],
LET(
_int, IF(ISOMITTED(interest), 0, interest),
_new_close, opening_balance + _int,
_new_int, _new_close * base_rate,
_closing_balance, IF(ABS(_new_int-_int)<0.001, _new_close,LOANAMT(opening_balance,base_rate,_new_int)),
_closing_balance
)
)
Gave me 106.38290 where opening_balance = 100, base_rate = 6%, which approximately agrees with the algebraic solution.
However, when I tried incorporating the tolerance as a parameter of the LAMBDA so that it could be adjusted easily, I got a #NUM error.
=LAMBDA(opening_balance, base_rate, tolerance, [interest],
LET(
_int, IF(ISOMITTED(interest), 0, interest),
_new_close, opening_balance + _int,
_new_int, _new_close * base_rate,
_closing_balance, IF(ABS(_new_int-_int)<tolerance, _new_close,LOANAMT2(opening_balance,base_rate,_new_int)),
_closing_balance
)
)
Could anyone explain what's going wrong and help me fix this?
Thanks.
The second version doesn't pass the tolerance value to the recursive call to LOANAMT2, hence the #NUM! error.
This works:
LOANAMT2=LAMBDA(opening_balance, base_rate, tolerance, [interest],
LET(
_int, IF(ISOMITTED(interest), 0, interest),
_new_close, opening_balance + _int,
_new_int, _new_close * base_rate,
_closing_balance, IF(ABS(_new_int-_int)<tolerance, _new_close,LOANAMT2(opening_balance,base_rate,tolerance,_new_int)),
_closing_balance
)
)
I need to construct a loop (simulation) that will iterate a certain number of times and display a value of warrant once the new firm value is close to the guess firm value. Specifically, the idea is to start out with a guess for the firm value (for example the stock price multiplied by the number of shares). Then you value the warrant as a call option (the code below) on this value multiplied by dilution factor, using the same volatility as the vol of the share price. You recompute then the value of the firm (number of shares times share price plus number of warrants times warrant price). This value will be different from the value of the firm you started with. Then you redo the procedure and after a few iterations you will see that the difference in values of the firm tends to zero. For this, I have a following code, but what I get is the following:
TypeError: 'int' object is not subscriptable
Please, help me to figure out the error given the code below:
def bsm_call_value(S0, K, T, r, sigma):
from math import log, sqrt, exp
from scipy import stats
S0 = float(S0)
d1 = (log(S0 / K) + (r + 0.5 * sigma ** 2) * T) / (sigma * sqrt(T))
d2 = (log(S0 / K) + (r - 0.5 * sigma ** 2) * T) / (sigma * sqrt(T))
value = (S0 * stats.norm.cdf(d1, 0.0, 1.0) - K * exp(-r * T) *stats.norm.cdf(d2, 0.0, 1.0))
return value
def warrant_1unobservable(S0, K, T, r, sigma, k, N, M, Iteration):
for i in range(1, Iteration):
Guess_FirmValue = S0*N
dilution = N/(N +k*M)
warrant[i] = bsm_call_value(Guess_FirmValue[i]/N,100,1,0.1,0.2)*dilution
New_FirmValue[i] = Guess_FirmValue[i]+ warrant[i]
Guess_FirmValue[i] - New_FirmValue[i] == 0
return warrant
print(warrant_1unobservable(100,100,1,0.1,0.2,1,100,10, 1000))
I'm not really a python expert and I'm not familiar with the algorithm you're using, but I'll point out a few things that could be causing the issue.
1) In warrant_1observable, you first assign Guess_FirmValue a scalar value (since both S0 and N are scalars the way you call the function), and then you try to access it with an index as Guess_FirmValue[i]. My guess would be that this is causing the error you displayed, since you're trying to index/subscript a variable that, based on your function input values, would be an integer.
2) Both warrant[i] and New_FirmValue[i] are attempts to assign values to an indexed position in a list, but nowhere do you initialize these variables as lists. Lists in python are initialized as warrant = []. Also, it's likely that you would have to either a) pre-allocate the lists to the correct size based on the Iteration or b) use append to push new values onto the back of the list.
3) Guess_FirmValue[i] - New_FirmValue[i] == 0 is a vacuous line of code. All this does is evaluate to either true or false, while performing no other operation. I imagine you're trying to check if the values are equal and then return, but that won't happen even if you stick this in an if statement. It is extremely unlikely that the floating-point representation of the values will ever be identical. This kind of break is accomplished by checking if the difference of the values is below some tolerance, which is set to be a very small number. Ex.:
if (abs(Guess_FirmValue[i] - New_FirmValue[i]) <= 1e-9):
return ...
Well its rather a very strange question
I have a macro which generates the delta of a Option(d1):
Function dOne(UnderlyingPrice, ExercisePrice, Time, Interest, Volatility, Dividend)
dOne = (Log(UnderlyingPrice / ExercisePrice) + (Interest - Dividend + (0.5 * Volatility ^ 2)) * Time) / (Volatility * (Sqr(Time)))
End Function
When I pass the the values to it, it generates the desired output:
However when I try to replicate this in Excel, it gives an entirely different output
I know that the calculations for output generated manually are correct.
However the desired values are those generated from VBA.
Please suggest what am I missing here.
The Log function in VBA is the natural log: ln(x).
The LOG function in the formula is log base 10: log10(x).
If you want log base 10 in VBA you will have to use the logarithmic identity for converting bases:
Log(x)/Log(10)
In your case
dOne = (Log(UnderlyingPrice / ExercisePrice) / Log(10) + (Interest - Dividend + (0.5 * Volatility ^ 2)) * Time) / (Volatility * (Sqr(Time)))