I have an input DataFrame with one row per product with balances, rates, etc. I want to be able to take that starting balance, and other inputs from the row (characteristics of the product), and forecast out 12 months of balances. What is the best approach to turn this one row per product information (there are a lot of individual products) and turn it into a summary forecast 12 months forward looking? The below is an example of one type of product that would have to be modelled. **The below code works, but I would like to know whether there is a better way overall to create forecasts with scenarios using python, pandas or numpy.** **Example input:** [![enter image description here][1]][1] **Example Output Created using code below:** [![enter image description here][2]][2] [1]: https://i.sstatic.net/EYNuk.png [2]: https://i.sstatic.net/YR4oQ.png Code that gets me from one to the other: Creates generator function that creates Ordered Dict, when called in pandas DataFrame outputs the example output. def dmd_flow(balance, start_date, num_periods, run_off_rate, new_funds_rate, int_rate, period='monthly'): """ Implements the cash flow modeling for demand products Arguments: balance -- initial balance of product at t0 start_date -- calendar date of t0 num_periods -- number of period to model run_off_rate -- annualized rate at which deposit runs off- straight line new_funds_rate -- annualized rate at which funds increase (net) int_rate -- rate paying on deposit which would be used if modeling interest payable period -- the period used for modeling i.e. monthly, annual Returns: liq_sched -- a schedule of liquidity based on the inputs ordered by time (ordered dictionary) """ p=1 b_bal = balance e_bal = balance current_date = start_date while p <= num_periods: if period == 'monthly': e_bal = round(b_bal - (balance*1/12*run_off_rate), 4) e_bal += round((balance*1/12*new_funds_rate), 4) if period == 'annual': e_bal = round(b_bal - (balance*run_off_rate), 4) e_bal += round((balance*new_funds_rate), 4) yield(OrderedDict([('Month', current_date), ('Period', p), ('Beg bal', b_bal), ('End Bal', e_bal), ])) p += 1 current_date += relativedelta(months=+1, day=31) b_bal = e_bal def create_timeseries_df(input=None, func=None, args=(dt.date(2018,1,31), 0, 0, 0, 0, 'monthly')): '''takes a series as an input and applies the fuctions to create the timeseries in the right shape''' new_df = input['balance'].apply( func, args=args) return pd.DataFrame([o_dict for gen in new_df for o_dict in gen]) out_df = create_timeseries_df(dmd_df, func=dmd_flow, args=(dt.date(2018,1,31), 12, 0, .10, .03, 'monthly')) out_df.groupby(['Month', 'Period'])[[ 'End Bal']].sum()