def test_ctor_1(self): mod = Model() ext = ExternalSector(mod) # Check that these sectors exist xr = ext['XR'] fx = ext['FX'] self.assertIs(ExchangeRates, type(xr)) self.assertIn('NUMERAIRE', xr.EquationBlock) self.assertIs(ForexTransations, type(fx))
def test_setRHS(self): mod = Model() us = Country(mod, 'US', 'USA') s = Sector(us, 'HH', 'Household') s.AddVariable('foo', 'variable foo', 'x') self.assertEqual('x', s.EquationBlock['foo'].RHS()) s.SetEquationRightHandSide('foo', 'y') self.assertEqual('y', s.EquationBlock['foo'].RHS()) with self.assertRaises(KeyError): s.SetEquationRightHandSide('LittleBunnyFooFoo', 'z')
def test_MissingExternalForGoldSectors(self): mod = Model() ca = Country(mod, 'CA', 'Canada') gov = GoldStandardGovernment(ca, 'GOV', ' ', 1000.) with self.assertRaises(LogicError): gov._GenerateEquations() tre = Treasury(ca, 'TRE', 'FinMin') cb = GoldStandardCentralBank(ca, 'CB', 'desc', treasury=tre) with self.assertRaises(LogicError): cb._GenerateEquations()
def test_GenerateEquations_insert_supply(self): mod = Model() can = Country(mod, 'Eh', 'Canada') mar = Market(can, 'LAB', 'Market') bus = Sector(can, 'BUS', 'Business') hh = Sector(can, 'HH', 'Household') hh2 = Sector(can, 'HH2', 'Household') bus.AddVariable('DEM_LAB', 'desc', 'x') hh.AddVariable('SUP_LAB_WRONG_CODE', 'desc 2', '') hh2.AddVariable('SUP_LAB_WRONG_CODE', 'desc 2', '') mod._GenerateFullSectorCodes() mar.AddSupplier(hh2) mar.AddSupplier(hh, 'SUP_LAB/2') # mar.SupplyAllocation = [[(hh, 'SUP_LAB/2')], hh2] mar._GenerateEquations() self.assertEqual('SUP_LAB/2', mar.EquationBlock['SUP_HH'].RHS()) self.assertEqual('SUP_LAB-SUP_HH', kill_spaces(mar.EquationBlock['SUP_HH2'].RHS())) self.assertEqual('LAB__SUP_HH', hh.EquationBlock['SUP_LAB'].RHS()) self.assertEqual('LAB__SUP_HH2', hh2.EquationBlock['SUP_LAB'].RHS())
def test_IsSharedCurrencyZone(self): mod = Model() ca = Country(mod, 'CA', 'Name', currency='CAD') ca_h = Sector(ca, 'HH', 'Sec') us = Country(mod, 'US', 'Name', currency='RMB') us_h = Sector(us, 'HH', 'name') china = Country(mod, 'China', 'Name', currency='RMB') china_h = Sector(china, 'HH', 'name') self.assertFalse(ca_h.IsSharedCurrencyZone(us_h)) self.assertFalse(us_h.IsSharedCurrencyZone(ca_h)) self.assertTrue(us_h.IsSharedCurrencyZone(china_h))
def test_AddCashFlow_2(self): mod = Model() us = Country(mod, 'US', 'USA') s = Sector(us, 'HH', 'Household') s.AddCashFlow('A', 'equation', 'Desc A') s.AddCashFlow('', 'equation', 'desc') with self.assertRaises(ValueError): s.AddCashFlow('-', 'B', 'Desc B') with self.assertRaises(ValueError): s.AddCashFlow('+', 'X', 'Desc C') self.assertEqual('LAG_F+A', s.EquationBlock['F'].RHS()) self.assertEqual('equation', s.EquationBlock['A'].RHS())
def test_GoldSectors(self): # Relatively big test, but it takes a lot of work to get a model # where we can create a GoldStandardCentralBank, and to set up the # equations so that they need to intervene. # Consider this an end-to-end test. mod = Model() ext = ExternalSector(mod) ca = Country(mod, 'CA', 'Canada', currency='CAD') us = Country(mod, 'US', 'United States', currency='USD') gov_us = GoldStandardGovernment(us, 'GOV') # gov_ca = GoldStandardGovernment(ca, 'CA Gov', 'GOV', 200.) tre_ca = Treasury(ca, 'TRE', 'Ministry of Finance') cb_ca = GoldStandardCentralBank(ca, 'CB', treasury=tre_ca) mon = MoneyMarket(ca, issuer_short_code='CB') dep = DepositMarket(ca, issuer_short_code='TRE') gov_us.AddVariable('T', 'Government Taxes', '0.') tre_ca.AddVariable('T', 'Government Taxes', '0.') tre_ca.SetEquationRightHandSide('DEM_GOOD', '20.') market = Market(ca, 'GOOD', 'Market') supplier_ca = Sector(ca, 'BUS', 'Canada supplier') supplier_us = Sector(us, 'BUS', 'US Supplier') market.AddSupplier(supplier_ca) market.AddSupplier(supplier_us, '10.') mod.EquationSolver.MaxTime = 1 mod.EquationSolver.MaxIterations = 90 mod.EquationSolver.ParameterErrorTolerance = 1e-1 mod.main() mod.TimeSeriesSupressTimeZero = True # markets should be balanced self.assertAlmostEqual(0., mod.GetTimeSeries('EXT_FX__NET_CAD')[0], places=2) self.assertAlmostEqual(0., mod.GetTimeSeries('EXT_FX__NET_USD')[0], places=2) # U.S. buys 10 units of GOLD self.assertAlmostEqual(10., mod.GetTimeSeries('US_GOV__GOLDPURCHASES')[0], places=2) # Canada sells 10 units self.assertAlmostEqual(-10., mod.GetTimeSeries('CA_CB__GOLDPURCHASES')[0], places=2)
def test_all(self): mod = Model() can = Country(mod, 'Eh', 'Canada') gov = ConsolidatedGovernment(can, 'GOV', 'Government') hou = Household(can, 'HH', 'Household', .5) dummy = Sector(can, 'DUM', 'Dummy') mm = MoneyMarket(can) dep = DepositMarket(can) # Need to add demand functions in household sector mod._GenerateFullSectorCodes() hou.AddVariable('DEM_MON', 'Demand for Money', '0.5 * ' + hou.GetVariableName('F')) hou.AddVariable('DEM_DEP', 'Demand for Deposits', '0.5 * ' + hou.GetVariableName('F')) mod._GenerateEquations() # Supply = Demand self.assertEqual('GOV__SUP_DEP', dep.EquationBlock['SUP_DEP'].RHS()) # Demand = Demand of two sectors self.assertEqual('HH__DEM_DEP', dep.EquationBlock['DEM_DEP'].RHS().replace(' ', '')) # At the sector level, demand = F self.assertEqual('0.5*HH__F', kill_spaces(hou.EquationBlock['DEM_MON'].RHS())) self.assertEqual('0.5*HH__F', kill_spaces(hou.EquationBlock['DEM_DEP'].RHS())) # Make sure the dummy does not have cash flows self.assertEqual('LAG_F', dummy.EquationBlock['F'].RHS()) # Household has a deposit interest cash flow self.assertIn('INTDEP', hou.EquationBlock['F'].RHS())
def test_GenerateEquations_2_supply_multicountry_2(self): mod = Model() can = Country(mod, 'CA', 'Canada, Eh?') US = Country(mod, 'US', 'USA! USA!') mar = Market(can, 'LAB', 'Market') bus = Sector(can, 'BUS', 'Business') hh = Sector(can, 'HH', 'Household') hh2 = Sector(can, 'HH2', 'Household') bus.AddVariable('DEM_LAB', 'desc', 'x') hh.AddVariable('SUP_LAB', 'desc 2', '') hh2.AddVariable('SUP_LAB', 'desc 2', '') mod._GenerateFullSectorCodes() mar.AddSupplier(hh2) mar.AddSupplier(hh, 'SUP_LAB/2') #nmar.SupplyAllocation = [[(hh, 'SUP_LAB/2')], hh2] mar._GenerateEquations() self.assertEqual('SUP_LAB/2', mar.EquationBlock['SUP_CA_HH'].RHS()) self.assertEqual('SUP_LAB-SUP_CA_HH', mar.EquationBlock['SUP_CA_HH2'].RHS()) self.assertEqual('CA_LAB__SUP_CA_HH', hh.EquationBlock['SUP_LAB'].RHS()) self.assertIn('SUP_LAB', hh.EquationBlock['F'].RHS()) self.assertEqual('CA_LAB__SUP_CA_HH2', hh2.EquationBlock['SUP_LAB'].RHS()) self.assertIn('SUP_LAB', hh2.EquationBlock['F'].RHS())
def test_GenerateEquations_2_supply_multicountry(self): mod = Model() # Have to have the same currency for this test can = Country(mod, 'CA', 'Canada, Eh?', currency='LOC') US = Country(mod, 'US', 'USA! USA!', currency='LOC') mar = Market(can, 'LAB', 'Market') bus = Sector(can, 'BUS', 'Business') hh = Sector(can, 'HH', 'Household') # Somehow, Americans are supplying labour in Canada... hh2 = Sector(US, 'HH2', 'Household') bus.AddVariable('DEM_LAB', 'desc', 'x') hh.AddVariable('SUP_LAB', 'desc 2', '') hh2.AddVariable('SUP_CA_LAB', 'desc 2', '') mod._GenerateFullSectorCodes() mar.AddSupplier(hh, 'SUP_LAB/2') mar.AddSupplier(hh2) # mar.SupplyAllocation = [[(hh, 'SUP_LAB/2')], hh2] mar._GenerateEquations() self.assertEqual('SUP_LAB/2', mar.EquationBlock['SUP_CA_HH'].RHS()) self.assertEqual('SUP_LAB-SUP_CA_HH', kill_spaces(mar.EquationBlock['SUP_US_HH2'].RHS())) self.assertEqual('CA_LAB__SUP_CA_HH', hh.EquationBlock['SUP_LAB'].RHS()) self.assertIn('SUP_LAB', hh.EquationBlock['F'].RHS()) self.assertEqual('CA_LAB__SUP_US_HH2', hh2.EquationBlock['SUP_CA_LAB'].RHS()) self.assertIn('SUP_CA_LAB', hh2.EquationBlock['F'].RHS())
def __init__(self): self.Model = Model() self.ModelName = '' self.TimeSeriesHolder = self.Model.EquationSolver.TimeSeries self.TimeAxisVariable = 'k' self.MinWidth = 800 self.MinHeight = 600 self.LogDir = '' self.SourceOptions = ('Time Series', 'Initial Steady State', 'Convergence Trace') self.LastSource = '' self.TimeSeriesWidget = None self.TimeAxisMinimum = None self.TimeStart = None self.TimeRange = None
def test_all(self): mod = Model() can = Country(mod, 'Eh', 'Canada') gov = ConsolidatedGovernment(can, 'GOV', 'Government') hou = Household(can, 'HH', 'Household', .5) hou2 = Household(can, 'HH2', 'Household2', .5) mm = MoneyMarket(can) mod._GenerateFullSectorCodes() mod._GenerateEquations() # Supply = Demand self.assertEqual('GOV__SUP_MON', mm.EquationBlock['SUP_MON'].RHS()) # Demand = Demand of two sectors self.assertEqual('HH__DEM_MON+HH2__DEM_MON', mm.EquationBlock['DEM_MON'].RHS().replace(' ', '')) # At the sector level, demand = F self.assertEqual('HH__F', hou.EquationBlock['DEM_MON'].RHS()) self.assertEqual('HH2__F', hou2.EquationBlock['DEM_MON'].RHS())
def main(): # The next line of code sets the name of the output files based on the code file's name. # This means that if you paste this code into a new file, get a new log name. sfc_models.register_standard_logs('output', __file__) # Create model, which holds all entities mod = Model() # Create first country - Canada. (This model only has one country.) can = Country(mod, 'CA', 'Canada') # Create sectors gov = ConsolidatedGovernment(can, 'GOV', 'Government') hh = Household(can, 'HH', 'Household') # A literally non-profit business sector bus = FixedMarginBusiness(can, 'BUS', 'Business Sector') # Create the linkages between sectors - tax flow, markets - labour ('LAB'), goods ('GOOD') tax = TaxFlow(can, 'TF', 'TaxFlow', .2) labour = Market(can, 'LAB', 'Labour market') goods = Market(can, 'GOOD', 'Goods market') # Add the financial markets # GOV -> issuing sector mm = MoneyMarket(can, issuer_short_code='GOV') dep = DepositMarket(can, issuer_short_code='GOV') # -------------------------------------------- # Financial asset demand equations # Need the full variable name for 'F' in household hh_F = hh.GetVariableName('F') hh.AddVariable('DEM_MON', 'Demand for Money', '0.5 * ' + hh_F) hh.AddVariable('DEM_DEP', 'Demand for deposits', '0.5 * ' + hh_F) # ----------------------------------------------------------------- # Need to set the exogenous variables # Government demand for Goods ("G" in economist symbology) mod.AddExogenous('GOV', 'DEM_GOOD', '[20.,] * 105') mod.AddExogenous('DEP', 'r', '[0.0,] * 5 + [0.04]*100') mod.AddInitialCondition('HH', 'F', 80.) mod.main() mod.TimeSeriesSupressTimeZero = True mod.TimeSeriesCutoff = 20 Quick2DPlot(mod.GetTimeSeries('t'), mod.GetTimeSeries('GOOD__SUP_GOOD'), 'Goods supplied (national production Y)') Quick2DPlot(mod.GetTimeSeries('t'), mod.GetTimeSeries('HH__F'), 'Household Financial Assets (F)')
def test_HasNoF(self): mod = Model() country = Country(mod, 'code', 'name') sec = Sector(country, 'Code', 'Name', has_F=False) self.assertNotIn('F', sec.GetVariables())
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. """ # Imports # This next line looks bizarre, but is needed for backwards compatibility with Python 2.7. from __future__ import print_function import sfc_models from sfc_models.models import Model, Country from sfc_models.sector import Sector sfc_models.register_standard_logs(output_dir='output', base_file_name=__file__) mod = Model() can = Country(mod, 'CA', 'Canada') # has_F=False: turns off creation of financial asset variables. sector_yy = Sector(can, 'YY', has_F=False) sector_yy.AddVariable('W', 'Variable W <constant>', '4.0') sector_yy.AddVariable('Y', 'Variable Y - depends on local variable', '2*W') sector_xx = Sector(can, 'XX', has_F=False) variable_name = sector_yy.GetVariableName('Y') # format: inserts variable_name where {0} is eqn = '{0} + 2.0'.format(variable_name) sector_xx.AddVariable('X', 'Variable x; depends on other sector', eqn) # Bind the model; solve eqns = mod.main() print(eqns)
def test_AddTerm_KeyError(self): mod = Model() us = Country(mod, 'US', 'USA! USA!') s = Sector(us, 'SEC', 'Desc') with self.assertRaises(KeyError): s.AddTermToEquation('SUP', 'x')
def test_Market_handling(self): mod = Model() ext = ExternalSector(mod) ca = Country(mod, 'CA', 'Canada', currency='CAD') us = Country(mod, 'US', 'United States', currency='USD') # gov_us.AddVariable('T', 'Government Taxes', '0.') gov_ca = Sector(ca, 'GOV', 'Gummint') gov_ca.AddVariable('DEM_GOOD', 'desc', '20.') market = Market(ca, 'GOOD', 'Market') supplier_ca = Sector(ca, 'BUS', 'Canada supplier') supplier_us = Sector(us, 'BUS', 'US Supplier') # Set supply so that CAD$10 is paid to each supplier. market.AddSupplier(supplier_ca) market.AddSupplier(supplier_us, '10.') # Set CAD = 2, so 2 USD = 1 CAD (USD is weaker.) mod.AddExogenous('EXT_XR', 'CAD', '[2.0,]*3') mod.EquationSolver.MaxTime = 1 mod.main() mod.TimeSeriesSupressTimeZero = True # The business sector nets USD$20 self.assertEqual([20.], mod.GetTimeSeries('US_BUS__F')) # The USD market is unbalanced; shortage of 20 USD self.assertEqual([-20.], mod.GetTimeSeries('EXT_FX__NET_USD')) # The CAD market is unbalanced; excess of 10 CAD self.assertEqual([10.], mod.GetTimeSeries('EXT_FX__NET_CAD')) # The supply in the US sector is USD $20 self.assertEqual([20.], mod.GetTimeSeries('US_BUS__SUP_CA_GOOD')) # THe supply on the Canadian side is CAD $10 self.assertEqual([10.], mod.GetTimeSeries('CA_GOOD__SUP_US_BUS'))
def test_SetExogenous(self): mod = Model() us = Country(mod, 'US', 'USA') s = Sector(us, 'HH', 'Household') s.SetExogenous('varname', 'val') self.assertEqual([(s, 'varname', 'val'), ], mod.Exogenous)
def test_ctor_chain(self): mod = Model() country = Country(mod, 'US', 'USA! USA!') household = Sector(country, 'HH', 'Household') self.assertEqual(household.Parent.Code, 'US') self.assertEqual(household.Parent.Parent.Code, '')
def main(): # The next line of code sets the name of the output files based on the code file's name. # This means that if you paste this code into a new file, get a new log name. sfc_models.register_standard_logs('output', __file__) # Create model, which holds all entities mod = Model() # Create first country - Canada. can = Country(mod, 'CA', 'Canada') # Create sectors gov = ConsolidatedGovernment(can, 'GOV', 'Government') hh = Household(can, 'HH', 'Household') # A literally non-profit business sector bus = FixedMarginBusiness(can, 'BUS', 'Business Sector') # Create the linkages between sectors - tax flow, markets - labour ('LAB'), goods ('GOOD') tax = TaxFlow(can, 'TF', 'TaxFlow', .2) labour = Market(can, 'LAB', 'Labour market') goods = Market(can, 'GOOD', 'Goods market') # Create a second country, with non-zero profits # This is a very error-prone way of building the model; if we repeat code blocks, they should be in # a function. # Create United States - Almost identical to Canada. us = Country(mod, 'US', 'United States') # Create sectors gov2 = ConsolidatedGovernment(us, 'GOV', 'Government') hh2 = Household(us, 'HH', 'Household') # ********** Profit margin of 10% ***************** bus2 = FixedMarginBusiness(us, 'BUS', 'Business Sector', profit_margin=.1) # Create the linkages between sectors - tax flow, markets - labour ('LAB'), goods ('GOOD') tax2 = TaxFlow(us, 'TF', 'TaxFlow', .2) labor2 = Market(us, 'LAB', 'Labor market') goods2 = Market(us, 'GOOD', 'Goods market') # ***************************************************************** # Need to set the exogenous variable - Government demand for Goods ("G" in economist symbology) # Since we have a two country model, we need to specify the full sector code, which includes the country code. mod.AddExogenous('CA_GOV', 'DEM_GOOD', '[20.,] * 105') mod.AddExogenous('US_GOV', 'DEM_GOOD', '[20.,] * 105') # Do the main work of building and solving the model mod.main() CUT = 25 t = mod.GetTimeSeries('t', cutoff=CUT) Y_CA = mod.GetTimeSeries('CA_GOOD__SUP_GOOD', cutoff=CUT) Y_US = mod.GetTimeSeries('US_GOOD__SUP_GOOD', cutoff=CUT) p = Quick2DPlot([t, t], [Y_CA, Y_US], 'Output - Y', run_now=False) p.Legend = ['Canada (0% profit)', 'U.S. (10% Profit)'] p.DoPlot() F_CA = mod.GetTimeSeries('CA_BUS__F', cutoff=CUT) F_US = mod.GetTimeSeries('US_BUS__F', cutoff=CUT) p = Quick2DPlot([t, t], [F_CA, F_US], 'Business Sector Financial Assets (F)', run_now=False) p.Legend = ['Canada (0% profit)', 'U.S. (10% Profit)'] p.DoPlot() BAL_CA = mod.GetTimeSeries('CA_GOV__FISC_BAL', cutoff=CUT) BAL_US = mod.GetTimeSeries('US_GOV__FISC_BAL', cutoff=CUT) p = Quick2DPlot([t, t], [BAL_CA, BAL_US], 'Government Financial Balance', run_now=False) p.Legend = ['Canada (0% profit)', 'U.S. (10% Profit)'] p.DoPlot()
def test_name(self): mod = Model() ca = Country(mod, 'CA') cb = CentralBank(ca, 'CB') self.assertIn('CB', cb.LongName) self.assertIn('CA', cb.LongName)
def test_no_market(self): mod = Model() can = Country(mod, 'Eh', 'Canada') bus = FixedMarginBusiness(can, 'BUS', 'Business') with self.assertRaises(Warning): bus._GenerateEquations()
def test_GenerateTermsLowLevel_3(self): mod = Model() can = Country(mod, 'Eh', 'Canada') mar = Market(can, 'LAB', 'Market') with self.assertRaises(LogicError): mar._GenerateTermsLowLevel('Blam!', 'desc')
def test_GenerateEquations(self): mod = Model() can = Country(mod, 'Eh', 'Canada') gov = Treasury(can, 'GOV', 'Government') gov._GenerateEquations() self.assertEqual(gov.EquationBlock['DEM_GOOD'].RHS(), '0.0')
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. """ # Imports # This next line looks bizarre, but is needed for backwards compatibility with Python 2.7. from __future__ import print_function import sfc_models from sfc_models.models import Model, Country from sfc_models.sector_definitions import Household, FixedMarginBusiness, Market sfc_models.register_standard_logs(output_dir='output', base_file_name=__file__) mod = Model() can = Country(mod, 'CA', 'Canada') household = Household(can, 'HH', 'Household Sector') business = FixedMarginBusiness(can, 'BUS', 'Business Sector') market = Market(can, 'GOOD', 'Goods Market') mod.main()
def test_GenerateIncomeEquations(self): mod = Model() us = Country(mod, 'US', 'USA') s = Sector(us, 'HH', 'Household') self.assertEqual('LAG_F', s.EquationBlock['F'].RHS()) self.assertEqual('F(k-1)', s.EquationBlock['LAG_F'].RHS())