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()