Repository: econ-ark/HARK

Issue:
Consistent t-index for time varying shock parameters.
Referring to #1021 and #326

Parameters for a time-varying income process are entered like this:

```
# Parameters that specify the income distribution over the lifecycle
    "PermShkStd" : [0.1,0.2,0.1,0.2,0.1,0.2,0.1,0,0,0],
    "PermShkCount" : 7,                    # Number of points in discrete approximation to permanent income shocks
    "TranShkStd" : [0.3,0.2,0.1,0.3,0.2,0.1,0.3,0,0,0],
    "TranShkCount" : 7,                    # Number of points in discrete approximation to transitory income shocks
```

But against what one might expect, the 0th element of the list is interpreted as the shock that occurs at the 0th as well as 1th periods. The 1th element of the list corresponds to the 2th shock, etc.

This not a natural way to define a model and is not very well documented; it is done this way because of some logic imported from earlier solution code. That code should be ammended.

Discussion:

Patch:
diff --git a/Documentation/CHANGELOG.md b/Documentation/CHANGELOG.md
index 73722e10..e24fd84e 100644
--- a/Documentation/CHANGELOG.md
+++ b/Documentation/CHANGELOG.md
@@ -14,6 +14,7 @@ Release Data: TBD
 
 #### Major Changes
 
+* Input parameters for cyclical models now indexed by t [#1039](https://github.com/econ-ark/HARK/pull/1039)
 * A IndexDistribution class for representing time-indexed probability distributions [#1018](https://github.com/econ-ark/pull/1018/).
 * Adds new consumption-savings-portfolio model `RiskyContrib`, which represents an agent who can save in risky and risk-free assets but faces
 frictions to moving funds between them. To circumvent these frictions, he has access to an income-deduction scheme to accumulate risky assets.
diff --git a/HARK/ConsumptionSaving/ConsIndShockModel.py b/HARK/ConsumptionSaving/ConsIndShockModel.py
index 892737bb..28f601c6 100644
--- a/HARK/ConsumptionSaving/ConsIndShockModel.py
+++ b/HARK/ConsumptionSaving/ConsIndShockModel.py
@@ -1729,7 +1729,7 @@ class PerfForesightConsumerType(AgentType):
         # Determine who dies
         DiePrb_by_t_cycle = 1.0 - np.asarray(self.LivPrb)
         DiePrb = DiePrb_by_t_cycle[
-            self.t_cycle - 1
+            self.t_cycle - 1 if self.cycles == 1 else self.t_cycle
         ]  # Time has already advanced, so look back one
 
         # In finite-horizon problems the previous line gives newborns the
@@ -2173,12 +2173,17 @@ class IndShockConsumerType(PerfForesightConsumerType):
         newborn = self.t_age == 0
         for t in range(self.T_cycle):
             these = t == self.t_cycle
+
+            # temporary, see #1022
+            if self.cycles == 1:
+                t = t - 1
+
             N = np.sum(these)
             if N > 0:
                 IncShkDstnNow = self.IncShkDstn[
-                    t - 1
+                    t
                 ]  # set current income distribution
-                PermGroFacNow = self.PermGroFac[t - 1]  # and permanent growth factor
+                PermGroFacNow = self.PermGroFac[t]  # and permanent growth factor
                 # Get random draws of income shocks from the discrete distribution
                 IncShks = IncShkDstnNow.draw(N)
 
@@ -3047,7 +3052,7 @@ init_lifecycle.update({"LivPrb": liv_prb})
 
 # Make a dictionary to specify an infinite consumer with a four period cycle
 init_cyclical = copy(init_idiosyncratic_shocks)
-init_cyclical['PermGroFac'] = [1.082251, 2.8, 0.3, 1.1]
+init_cyclical['PermGroFac'] = [1.1, 1.082251, 2.8, 0.3]
 init_cyclical['PermShkStd'] = [0.1, 0.1, 0.1, 0.1]
 init_cyclical['TranShkStd'] = [0.1, 0.1, 0.1, 0.1]
 init_cyclical['LivPrb'] = 4*[0.98]
diff --git a/HARK/core.py b/HARK/core.py
index 8f00c43b..557755d6 100644
--- a/HARK/core.py
+++ b/HARK/core.py
@@ -1004,10 +1004,12 @@ def solve_one_cycle(agent, solution_last):
     # Initialize the solution for this cycle, then iterate on periods
     solution_cycle = []
     solution_next = solution_last
-    for t in range(T):
+    
+    cycles_range = [0] + list(range(T - 1, 0, -1))
+    for k in (range(T-1, -1, -1) if agent.cycles == 1 else cycles_range):
         # Update which single period solver to use (if it depends on time)
         if hasattr(agent.solve_one_period, "__getitem__"):
-            solve_one_period = agent.solve_one_period[T - 1 - t]
+            solve_one_period = agent.solve_one_period[k]
         else:
             solve_one_period = agent.solve_one_period
 
@@ -1019,8 +1021,7 @@ def solve_one_cycle(agent, solution_last):
         # Update time-varying single period inputs
         for name in agent.time_vary:
             if name in these_args:
-                # solve_dict[name] = eval('agent.' + name + '[t]')
-                solve_dict[name] = agent.__dict__[name][T - 1 - t]
+                solve_dict[name] = agent.__dict__[name][k]
         solve_dict["solution_next"] = solution_next
 
         # Make a temporary dictionary for this period


Test patch:
diff --git a/HARK/ConsumptionSaving/tests/test_IndShockConsumerType.py b/HARK/ConsumptionSaving/tests/test_IndShockConsumerType.py
index aae33d65..c2f50002 100644
--- a/HARK/ConsumptionSaving/tests/test_IndShockConsumerType.py
+++ b/HARK/ConsumptionSaving/tests/test_IndShockConsumerType.py
@@ -313,7 +313,7 @@ CyclicalDict = {
     "Rfree": 1.03,  # Interest factor on assets
     "DiscFac": 0.96,  # Intertemporal discount factor
     "LivPrb": 4 * [0.98],  # Survival probability
-    "PermGroFac": [1.082251, 2.8, 0.3, 1.1],
+    "PermGroFac": [1.1, 1.082251, 2.8, 0.3],
     # Parameters that specify the income distribution over the lifecycle
     "PermShkStd": [0.1, 0.1, 0.1, 0.1],
     "PermShkCount": 7,  # Number of points in discrete approximation to permanent income shocks
@@ -358,6 +358,11 @@ class testIndShockConsumerTypeCyclical(unittest.TestCase):
             CyclicalExample.solution[3].cFunc(3).tolist(), 1.5958390056965004
         )
 
+        CyclicalExample.initialize_sim()
+        CyclicalExample.simulate()
+
+        self.assertAlmostEqual(CyclicalExample.state_now['aLvl'][1], 0.41839957)
+
 # %% Tests of 'stable points'