Errors with DateDiff between two calculated columns in PowerBi - dax

I work for an FI and need tips on creating a measure that will allow me to find the days between when a transaction takes an account negative and when the next deposit takes the account positive. Right now we have identified the negative and positive dates using 2 calculated columns. But the measure used to find the difference between those days is not working.
Negative balance calculated column:
Balance After Tran Neg =
IF('Accounts Going Negative'[CATEGORY] =
"W" && 'Accounts Going Negative'[PRINCIPAL] < 'Accounts Going Negative'[NEW_BALANCE]
&& 'Accounts Going Negative'[NEW_BALANCE] < 0,
'Accounts Going Negative'[POSTING_DATE], BLANK())
Positive balance calculated column:
Balance After Tran Pos =
IF('Accounts Going Negative'[CATEGORY]=
"D" && 'Accounts Going Negative'[PRINCIPAL]
> 'Accounts Going Negative'[NEW_BALANCE]
&& 'Accounts Going Negative'[NEW_BALANCE] > 0,
'Accounts Going Negative'[POSTING_DATE], BLANK())
I created a measure that should calculate the days between the two dates:
Date Diff =
DATEDIFF('Accounts Going Negative'[Balance After Tran Neg],
'Accounts Going Negative'[Balance After Tran Pos], DAY)
This datediff measure just returns with blank results in the visual. Any tips as to how to solve this problem?
Thank you!

Related

Calculating Moving Average for N Months in DAX Power BI

I have a measure that calculates Moving Average for 3 months:
Moving_Avg_3_Months = AVERAGEX(DATESINPERIOD('Calendar FY'[Date],
LASTDATE('Calendar FY'[Date]), -3, MONTH),[CUS Revenue Credible All])
Is it possible to create a measure that would calculate Moving Average for my [CUS Revenue Credible All] - but for N months. Where N = 3 or N = 6 or N = whatever number I'd like?
If you create a new table with the different values for moving average you want to use eg. TableMovingAverage: [-3,-6,-12,-24,...,N]
and modify you DAX formula like this:
Moving_Avg_3_Months =
AVERAGEX(
DATESINPERIOD('Calendar FY'[Date],
LASTDATE('Calendar FY'[Date]),
SELECTEDVALUE('TableMovingAverage', -3),
MONTH),
[CUS Revenue Credible All])
SELECTEDVALUE returns a scalar if only one value is in the specified table, otherwise it return a default value -3 in this case.
If you filter TableMovingAverage you can switch between different moving averages

Time subtraction & conditional formatting in Google Sheets

I'm working on a simple 3-column table for logging sleep hours. It's based on "went to bed" time (col 1), "woke up" time (col 2) and "time in bed" (col 3).
All 3 columns are formatted as - h:mm - and Google seems to calculate the time difference correctly, considering that it has to subtract "backwards", as in "woke up" time minus "went to bed" time.
The problem arises when I add conditional formatting to the "time in bed" column. What I want is the hours spent in bed in green if >= 8:00:00 or in orange if < 8:00:00.
Adding the date as well to the "went to bed" time and "woke up" time didn't help.
The ABS function on the difference didn't help either.
When "time in bed" is >= 8:00:00 AND "went to bed" time happens to be BEFORE midnight, I see an orange number, where I should see a green one
Every other case works as expected.
custom formula for green color:
=IF(TIMEVALUE(D4)>=0.33,1)

Maximum profit that can be obtained - Buying and Selling

Say we have an accurate prediction of Messi’s prices for a period of N days. The prediction is given as a list in which p_i represents the player’s price in day i. Bob plans to make multiple, successive transactions during this period, but CAN’T have more than one Messi at a time, and therefore needs to sell him before buying him again.
Bob starts out with a limited budget B and can’t buy a Messi which costs more than he can afford. Of course, Bob can add to his budget any profit he gets from buying and selling his Messis. Luckily for him, some of the times he starts with a Messi from opening a random gift pack beforehand.
At the end Bob just wants to have as much profit as possible, and sell hist last Messi.
Input format :
On the first line of the input file, you will find 3 integers, N, B and M.
N represents the number of days for which Bob has a prediction of Messi’s price.
B represents Bob’s initial budget.
M can be either 0 or 1; 0 if Bob starts without an initial Messi to sell and 1 if he does start with an initial Messi to sell.
On the next line you will find N integers: p1, p2, … , pN, separated by a whitespace, in which pi, represents Messi’s price on day i.
Given testcases
Test 1
7 5 0
20 10 30 5 10 10 20
Correct answer : 15
Explanation : Bob starts with an initial budget of 5 and no initial Messi to sell. He cannot buy any Messi until his price drops to 5, so his profit is only (20-5) = 15
Test 2
7 0 1
20 10 50 80 60 20 10
Correct answer: 90
Explanation:
Bob starts with an initial budget of 0 and one Messi to sell. Therefore he sells his initial Messi for 20, buys him back for 10 and sells him for 80, so his profit is 20 + (80-10) = 90
This problem was given to me in an interview and I haven't been able to produce a functioning solution. In the meantime I've found a few simpler variations on this problem such as Maximum profit by buying and selling a share at most twice , but I've been unsuccessful in understanding how to adapt the thinking to my problem.
So far I've only been able to come up with a brute force solution that goes way beyond the time restrictions I was given (0.1 seconds for C++, where 1 <= N <= 10^5).
I'm looking for a solution and a way of thinking about this kind of problem, I can't seem to find the right way to think about this.
We can use dynamic programming.
Let's define f0(i) as the maximum budget we can obtain if we don't have Messi at the beginning of the day i.
Let f1(i) be the same value in case we've got him.
Base values for i = 0 depend on whether we have him at the very beginning or not.
The transitions go as follows:
We can go from i to i + 1 and do nothing
If we have Messi, we can sell him (setting f0(i + 1) = max(f0(i + 1), f1(i) + price(i)))
If we don't have him and our budget is big enough, we can buy him
(doing f1(i + 1) = max(f1(i + 1), f0(i) - price(i)))
The answer is f0(n) (which mean that all days passed and we don't have him).
This solution clearly requires a linear amount of time and space, so any
reasonable C++ implementation should fit your requirements.
First simplification of the problem is to convert the initial "gift" of Messi to an equal amount of money at the initial price of Messi. The user has a choice to either buy that Messi back or not at the beginning.
Afterwards, you would find the first price that's low enough for the user to buy a Messi, and discard every prediction before that. Then, find all the local minimal and local maximal of the predicted prices, and buy on all the minimals and sell on all the maximals, but remember not to buy back if the local minimal is the last prediction.
This should solve the problem in O(N).
EDIT: A local minimal or maximal can be found by the 2nd-degree difference of the sequence:
d[i] = p[i+1] - p[i]
d2[i] = d[i] - d[i-1]
If d2[i] > 0, then it's local minimal; if d2[i] < 0, then it's local maximal. Obviously there will be some boundary conditions that you need to take care of, but it shouldn't be too hard.
// input
long predictionLength;
long budget;
bool startWithMessi;
long prediction[MAX_PREDICTION_LENGTH];
// output
long profit;
ifstream fin;
fin.open( DATA_FILE_NAME );
fin >> predictionLength >> budget >> startWithMessi;
for( long day = 0; day < predictionLength; day++ )
fin >> prediction[day];
fin.close();
long money = budget;
bool messi = startWithMessi;
long dayIndex = 0;
while( dayIndex < predictionLength )
{
if( messi )
{
if( dayIndex == predictionLength - 1
|| prediction[dayIndex] > prediction[dayIndex + 1] )
{
money += prediction[dayIndex];
messi = false;
}
}
else
if( dayIndex < predictionLength - 1
&& prediction[dayIndex] < prediction[dayIndex + 1]
&& money >= prediction[dayIndex] )
{
money -= prediction[dayIndex];
messi = true;
}
dayIndex++;
}
profit = money - budget;
cout << profit << endl;

How to decide on weights?

For my work, I need some kind of algorithm with the following input and output:
Input: a set of dates (from the past). Output: a set of weights - one weight per one given date (the sum of all weights = 1).
The basic idea is that the closest date to today's date should receive the highest weight, the second closest date will get the second highest weight, and so on...
Any ideas?
Thanks in advance!
First, for each date in your input set assign the amount of time between the date and today.
For example: the following date set {today, tomorrow, yesterday, a week from today} becomes {0, 1, 1, 7}. Formally: val[i] = abs(today - date[i]).
Second, inverse the values in such a way that their relative weights are reversed. The simplest way of doing so would be: val[i] = 1/val[i].
Other suggestions:
val[i] = 1/val[i]^2
val[i] = 1/sqrt(val[i])
val[i] = 1/log(val[i])
The hardest and most important part is deciding how to inverse the values. Think, what should be the nature of the weights? (do you want noticeable differences between two far away dates, or maybe two far away dates should have pretty equal weights? Do you want a date which is very close to today have an extremely bigger weight or a reasonably bigger weight?).
Note that you should come up with an inverting procedure where you cannot divide by zero. In the example above, dividing by val[i] results in division by zero. One method to avoid division by zero is called smoothing. The most trivial way to "smooth" your data is using the add-one smoothing where you just add one to each value (so today becomes 1, tomorrow becomes 2, next week becomes 8, etc).
Now the easiest part is to normalize the values so that they'll sum up to one.
sum = val[1] + val[2] + ... + val[n]
weight[i] = val[i]/sum for each i
Sort dates and remove dups
Assign values (maybe starting from the farthest date in steps of 10 or whatever you need - these value can be arbitrary, they just reflect order and distance)
Normalize weights to add up to 1
Executable pseudocode (tweakable):
#!/usr/bin/env python
import random, pprint
from operator import itemgetter
# for simplicity's sake dates are integers here ...
pivot_date = 1000
past_dates = set(random.sample(range(1, pivot_date), 5))
weights, stepping = [], 10
for date in sorted(past_dates):
weights.append( (date, stepping) )
stepping += 10
sum_of_steppings = sum([ itemgetter(1)(x) for x in weights ])
normalized = [ (d, (w / float(sum_of_steppings)) ) for d, w in weights ]
pprint.pprint(normalized)
# Example output
# The 'date' closest to 1000 (here: 889) has the highest weight,
# 703 the second highest, and so forth ...
# [(151, 0.06666666666666667),
# (425, 0.13333333333333333),
# (571, 0.2),
# (703, 0.26666666666666666),
# (889, 0.3333333333333333)]
How to weight: just compute the difference of all dates and the current date
x(i) = abs(date(i) - current_date)
you can then use different expression to assign weights:
w(i) = 1/x(i)
w(i) = exp(-x(i))
w(i) = exp(-x(i)^2))
use gaussian distribution - more complicated, do not recommend
Then use normalized weights: w(i)/sum(w(i)) so that the sum is 1.
(Note that the exponential func is always used by statisticians in survival analysis)
The first thing that comes to my mind to to use a geometric series:
http://en.wikipedia.org/wiki/Geometric_series
(1/2)+(1/4)+(1/8)+(1/16)+(1/32)+(1/64)+(1/128)+(1/256)..... sums to one.
Yesterday would be 1/2
2 days ago would be 1/4
and so on
Is is the index for the i-th date.
Assign weights equal to to Ni / D.
D0 is the first date.
Ni is the difference in days between the i-th date and the first date D0.
D is the normalization factor
converts dates to yyyymmddhhmiss format (24 hours), add all these values ​​and the total, divide by the total time, and sort by this value.
declare #data table
(
Date bigint,
Weight float
)
declare #sumTotal decimal(18,2)
insert into #Data (Date)
select top 100
replace(replace(replace(convert(varchar,Datetime,20),'-',''),':',''),' ','')
from Dates
select #sumTotal=sum(Date)
from #Data
update #Data set
Weight=Date/#sumTotal
select * from #Data order by 2 desc

Who owes who money optimization

Say you have n people, each who owe each other money. In general it should be possible to reduce the amount of transactions that need to take place. i.e. if X owes Y £4 and Y owes X £8, then Y only needs to pay X £4 (1 transaction instead of 2).
This becomes harder when X owes Y, but Y owes Z who owes X as well. I can see that you can easily calculate one particular cycle. It helps for me when I think of it as a fully connected graph, with the edges being the amount each person owes.
Problem seems to be NP-complete, but what kind of optimisation algorithm could I make, nevertheless, to reduce the total amount of transactions? Doesn't have to be that efficient, as N is quite small for me.
Edit:
The purpose of this problem would be to be able to have in the accounting system something that can say to each person when they log in "You can remove M amount of transactions by simply paying someone X amount, and someone else Y amount". Hence the bank solution (though optimal if everyone is paying at the same time) cannot really be used here.
Are people required to clear their debts by paying somebody that they actually owe money to personally? If not, the following seems to work suspiciously easily:
For each person, work out the net amount they should pay, or should receive.
Have somebody who owes money net pay somebody who should receive money net min(amount owed, amount to be received). After this, at least one of the two participants owes nothing and should receive nothing, and so can be removed from the problem.
Assuming I have missed something, what are the constraints that apply (or gross error made)?
I have created an Android app which solves this problem. You can input expenses during the trip, it even recommends you "who should pay next". At the end it calculates "who should send how much to whom". My algorithm calculates minimum required number of transactions and you can setup "transaction tolerance" which can reduce transactions even further (you don't care about $1 transactions) Try it out, it's called Settle Up:
https://market.android.com/details?id=cz.destil.settleup
Description of my algorithm:
I have basic algorithm which solves the problem with n-1 transactions, but it's not optimal. It works like this: From payments, I compute balance for each member. Balance is what he paid minus what he should pay. I sort members according to balance increasingly. Then I always take the poorest and richest and transaction is made. At least one of them ends up with zero balance and is excluded from further calculations. With this, number of transactions cannot be worse than n-1. It also minimizes amount of money in transactions. But it's not optimal, because it doesn't detect subgroups which can settle up internally.
Finding subgroups which can settle up internally is hard. I solve it by generating all combinations of members and checking if sum of balances in subgroup equals zero. I start with 2-pairs, then 3-pairs ... (n-1)pairs. Implementations of combination generators are available. When I find a subgroup, I calculate transactions in the subgroup using basic algorithm described above. For every found subgroup, one transaction is spared.
The solution is optimal, but complexity increases to O(n!). This looks terrible but the trick is there will be just small number of members in reality. I have tested it on Nexus One (1 Ghz procesor) and the results are: until 10 members: <100 ms, 15 members: 1 s, 18 members: 8 s, 20 members: 55 s. So until 18 members the execution time is fine. Workaround for >15 members can be to use just the basic algorithm (it's fast and correct, but not optimal).
Source code:
Source code is available inside a report about algorithm written in Czech. Source code is at the end and it's in English:
http://settleup.destil.cz/report.pdf
Nominate one person arbitrarily to be the banker.
Each other person transfers the sum of all the outgoing transactions minus the incoming transactions (so either deposits or withdraws) to that person.
There will be a maximum of (n-1) transactions, which is pretty small. It is fast. It is simple.
Given that everyone who transfers money will have to be involved in a transaction anyway*, it is bounded to be at worst twice the optimal case.**
* The exception is the banker themselves. A quick optimisation is to ensure the nominated banker is not someone who holds a neutral position.
** Explaining my upper bound logic further:
Suppose the optimal case is A gives $1 to B, and C gives $1 to D, and E is neutral = two transactions.
Then with this logic, if E is the nominated banker, A gives $1 to E, E gives $1 to B, C gives $1 to E and E gives $1 to D = four transactions.
With the optimisation, making sure you don't choose a neutral person for banker, select A instead.
A gives $1 to B, C gives $1 to A. A gives $1 to D = three transactions.
for each debt in debts
debt.creditor.owed -= debt.amount
debt.deptor.owed += debt.amount
end
for each person in persons
if person.owed > 0 then
deptors.add person
else if person.owed < 0 then
creditors.add person
end
end
deptors.sort_by_owed_desc
creditor.sort_by_owed_asc
for each debtor in deptors
while debtor.owed > 0
creditor = creditors.top
amount = min( debtor.owed, -creditor.owed)
creditor.owed += amount
debtor.owed -= amount
if creditor.owed == 0 then
creditors.remove_top
end
write debtor.name " owes " creditor.name " " amount "€"
end
end
Just thinking about it I'd start by looking at each cycle in the directed graph and reducing each edge in the cycle by the value of the minimum edge in the cycle, then remove the minimum edge altogether. Rinse and repeat.
Here's the Python solution I used; it's the same idea as Gunner's post, with a few line changes:
for i in N:
for j in N:
if i!=j and owes[i][j] > owes[j][i]:
owes[i][j] -= owes[j][i]
owes[j][i] = 0
for k in N:
for i in N:
for j in N:
if k == i or i == j or k == j:
continue
if owes[j][k] > owes[i][j]:
owes[i][k] += owes[i][j]
owes[j][k] -= owes[i][j]
owes[i][j] = 0;
Works a treat.
You can test it with i.e.:
owes = [[0,2,11], [4,0,7], [2,3,0]]
N = range(len(owes))
I think you need to build a different data structure ( a tree, each time one person is the root node) that will check for each person how many "transaction" can you "kill", than, choose the best one, make the cycle, and rebuild it again.it is not o(N), I Think it's N^2 though, and it will not give you the best result. it is just a strategy.
This problem may be tackled with the Warshall algorithm.
for(i=0;i<n;i++)
for(j=0;j<n;j++)
if ( i!= j && owes[i][j] > owes[j][i] )
owes[i][j] -= (owes[i][j] - owes[j][i]), owes[j][i] = 0;
for(k=0;k<n;k++)
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
if( k == i || i == j || k == j ) continue;
if ( owes[j][k] > owes[i][j] )
{
int diff = owes[j][k] - owes[i][j];
owes[i][j] = 0;
owes[i][k ] += diff;
owes[j][k] -= diff;
}
}
After the algorithm finishes, the total number of transactions required would be the number of positive entries in the owes table.
I have not verified yet whether the algorithm will work, based on nature of the problem it may work. Solution is O(N^3).
I think you must remove all cicles reducing edges by minimal edge value and removingedges with value 0. After it you will get graph withouth cicles. I think you must find vertexes, wich have no pointers to them (man's wich owes only others money). This man's must pay money, beacouse there is no one to pay the money for them. So my point is that you must find somehow who they must pay.
I have a solution to the problem written in matlab. It is based on a matrix of who owes who what. The number in the (i,j) means that person j owes person i the number. E.g.
B owes A 2
and A owes B 1
of course in this case it is trivial that B should just give A 1
This becomes more complex with more entries. However, with the algorithm i wrote i can guarantee that no more than N-1 transactions occurs where N is the number of persones 2 in this case.
Here is the code i wrote.
function out = whooweswho(matrix)
%input sanitation
if ~isposintscalar(matrix)
[N M] = size(matrix);
if N ~= M
error('Matrix must be square');
end
for i=1:N
if matrix(N,N) ~= 0
error('Matrix must have zero on diagonals');
end
end
else
%construction of example matrix if input is a positive scalar
disp('scalar input: Showing example of NxN matrix randomly filled');
N = matrix;
matrix = round(10*N*rand(N,N)).*(ones(N,N)-eye(N))
end
%construction of vector containing each persons balance
net = zeros(N,1);
for i=1:N
net(i) = sum(matrix(i,:))-sum(matrix(:,i));
end
%zero matrix, so it can be used for the result
matrix = zeros(size(matrix));
%sum(net) == 0 always as no money dissappears. So if min(net) == 0 it
%implies that all balances are zero and we are done.
while min(net) ~= 0
%find the poorest and the richest.
[rec_amount reciever] = max(net);
[give_amount giver] = min(net);
%balance so at least one of them gets zero balance.
amount =min(abs(rec_amount),abs(give_amount));
net(reciever) = net(reciever) - amount;
net(giver) = net(giver) + amount;
%store result in matrix.
matrix(reciever,giver) = amount;
end
%output equivalent matrix of input just reduced.
out = matrix;
end

Resources