Skip to content

Instantly share code, notes, and snippets.

@rloredo
Last active December 11, 2021 12:48
Show Gist options
  • Save rloredo/4c3f797e89171028fcc5ff0929b97c42 to your computer and use it in GitHub Desktop.
Save rloredo/4c3f797e89171028fcc5ff0929b97c42 to your computer and use it in GitHub Desktop.
Revenue accrual
import pandas as pd
from pandas.tseries.offsets import MonthEnd
def assign_to_months(start_date:pd.Timestamp, end_date:pd.Timestamp, total:float, year:int) -> pd.Series:
"""
start_date: start date of the contract
end_date: end date of the contract
total: total amount of the contract
year: year to be accrued, everything outside this year will not be accrued
"""
n_of_days = (end_date - start_date) / pd.Timedelta(1, 'days')
try:
daily = total / n_of_days
except:
daily = -1 #Add this to flag errors in contract dates. Any negative number must be checked.
months = [i for i in range(1,13)]
month_dict = dict.fromkeys(months, 0)
for p in pd.period_range(start_date, end_date, freq='D'):
if p.year == year:
month_dict[p.month] += 1
for k in month_dict.keys():
if (end_date.month == k) & (end_date.year == year):
month_dict[k] = max(0,(month_dict[k] * daily) - daily)
else:
month_dict[k] = (month_dict[k] * daily)
return pd.Series([round(v,2) for v in month_dict.values()], index=[f'{year}-{m}' for m in months])
#Usage
df = pd.DataFrame({'start_date':[pd.Timestamp('2020-01-10')], 'end_date': [pd.Timestamp('2020-02-20')], 'total': [10]})
df.apply(lambda x: assign_to_months(x['start_date'], x['end_date'], x['total'], 2020), axis=1)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment