def market__tatonnement(self, args): import os from src.bank import Bank from src.household import Household from src.firm import Firm from src.environment import Environment from src.transaction import Transaction from src.market import Market text = "This test checks market.tatonnement \n" self.print_info(text) # # INITIALIZATION # environment_directory = str(args[0]) identifier = str(args[1]) log_directory = str(args[2]) # Configure logging parameters so we get output while the program runs logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO) logging.info('START logging for test market__tatonnement in run: %s', environment_directory + identifier + ".xml") # Construct household filename environment = Environment(environment_directory, identifier) # generate a bank bank = Bank() bank.identifier = "test_bank" environment.banks.append(bank) # generate a firm firm = Firm() firm.identifier = "test_firm" environment.firms.append(firm) # generate a household household = Household() household.identifier = "test_household" environment.households.append(household) # # TESTING # sellers = [] for agent in environment.households: sellers.append([agent, agent.supply_of_labour]) buyers = [] for agent in environment.firms: buyers.append([agent, agent.demand_for_labour]) starting_price = 0.0 price = 0.0 market = Market("market") price = market.tatonnement(sellers, buyers, starting_price, 0.00000001, 0.01, 1.1) print("Price found through tatonnement:") print(price)
def test_sell_fit_buyers(self): m = Market() c = m.companies[0] m.trade_queue[c][OrderType.BUY][110].append(Order(c, 110, 5, OrderType.BUY)) m.trade_queue[c][OrderType.BUY][120].append(Order(c, 120, 25, OrderType.BUY)) m.sell(c, 100, 30) self.assertEqual(len(m.trade_queue[c][OrderType.SELL][100]), 0) self.assertEqual(len(m.trade_queue[c][OrderType.BUY][110]), 0) self.assertEqual(len(m.trade_queue[c][OrderType.BUY][120]), 0)
def test_sell_but_queued(self): m = Market() c = m.companies[0] m.sell(c, 100, 1) self.assertEqual(len(m.trade_queue[c][OrderType.SELL][100]), 1) order = m.trade_queue[c][OrderType.SELL][100][0] self.assertEqual(order.price, 100) self.assertEqual(order.amount, 1)
def test_buy_fit_sellers(self): m = Market() c = m.companies[0] m.trade_queue[c][OrderType.SELL][90].append(Order(c, 90, 5, OrderType.SELL)) m.trade_queue[c][OrderType.SELL][80].append(Order(c, 80, 25, OrderType.SELL)) m.buy(c, 100, 30) self.assertEqual(len(m.trade_queue[c][OrderType.BUY][100]), 0) self.assertEqual(len(m.trade_queue[c][OrderType.SELL][90]), 0) self.assertEqual(len(m.trade_queue[c][OrderType.SELL][80]), 0)
def market__rationing_proportional(self, args): import os from src.bank import Bank from src.household import Household from src.firm import Firm from src.environment import Environment from src.transaction import Transaction from src.market import Market text = "This test checks market.rationing_proportional \n" self.print_info(text) # # INITIALIZATION # environment_directory = str(args[0]) identifier = str(args[1]) log_directory = str(args[2]) # Configure logging parameters so we get output while the program runs logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO) logging.info( 'START logging for test market__rationing_proportional in run: %s', environment_directory + identifier + ".xml") # Construct household filename environment = Environment(environment_directory, identifier) # generate a bank bank = Bank() bank.identifier = "test_bank" environment.banks.append(bank) # generate a firm firm = Firm() firm.identifier = "test_firm" environment.firms.append(firm) # generate a household household = Household() household.identifier = "test_household" environment.households.append(household) # # TESTING # market = Market("market") rationed = market.rationing_proportional([["agent1", 5], ["agent2", 7], ["agent3", -3], ["agent4", -4]]) print("Pairs found through proportional rationing:") print(rationed)
def market__set_amplification(self, args): import os from src.bank import Bank from src.household import Household from src.firm import Firm from src.environment import Environment from src.transaction import Transaction from src.market import Market text = "This test checks market.set_amplification \n" self.print_info(text) # # INITIALIZATION # environment_directory = str(args[0]) identifier = str(args[1]) log_directory = str(args[2]) # Configure logging parameters so we get output while the program runs logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO) logging.info('START logging for test market__set_amplification in run: %s', environment_directory + identifier + ".xml") # Construct household filename environment = Environment(environment_directory, identifier) # generate a bank bank = Bank() bank.identifier = "test_bank" environment.banks.append(bank) # generate a firm firm = Firm() firm.identifier = "test_firm" environment.firms.append(firm) # generate a household household = Household() household.identifier = "test_household" environment.households.append(household) # # TESTING # market = Market("market_id") print("Market's amplification:") print(market.get_amplification()) print("Changing amplification") market.set_amplification(0.55) print("Market's amplification:") print(market.get_amplification())
def test_sell_when_less_buyers(self): m = Market() c = m.companies[0] m.trade_queue[c][OrderType.BUY][110].append(Order(c, 110, 5, OrderType.BUY)) m.sell(c, 100, 30) self.assertEqual(len(m.trade_queue[c][OrderType.BUY][110]), 0) self.assertEqual(len(m.trade_queue[c][OrderType.SELL][100]), 1) order = m.trade_queue[c][OrderType.SELL][100][0] self.assertEqual(order.price, 100) self.assertEqual(order.amount, 25)
def market__rationing_proportional(self, args): import os from src.bank import Bank from src.household import Household from src.firm import Firm from src.environment import Environment from src.transaction import Transaction from src.market import Market text = "This test checks market.rationing_proportional \n" self.print_info(text) # # INITIALIZATION # environment_directory = str(args[0]) identifier = str(args[1]) log_directory = str(args[2]) # Configure logging parameters so we get output while the program runs logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO) logging.info('START logging for test market__rationing_proportional in run: %s', environment_directory + identifier + ".xml") # Construct household filename environment = Environment(environment_directory, identifier) # generate a bank bank = Bank() bank.identifier = "test_bank" environment.banks.append(bank) # generate a firm firm = Firm() firm.identifier = "test_firm" environment.firms.append(firm) # generate a household household = Household() household.identifier = "test_household" environment.households.append(household) # # TESTING # market = Market("market") rationed = market.rationing_proportional([["agent1", 5], ["agent2", 7], ["agent3", -3], ["agent4", -4]]) print("Pairs found through proportional rationing:") print(rationed)
def test_buy_when_more_sellers(self): m = Market() c = m.companies[0] m.trade_queue[c][OrderType.SELL][90].append(Order(c, 90, 5, OrderType.SELL)) m.trade_queue[c][OrderType.SELL][80].append(Order(c, 80, 125, OrderType.SELL)) m.buy(c, 100, 30) self.assertEqual(len(m.trade_queue[c][OrderType.BUY][100]), 0) self.assertEqual(len(m.trade_queue[c][OrderType.SELL][90]), 0) self.assertEqual(len(m.trade_queue[c][OrderType.SELL][80]), 1) left_sell_order = m.trade_queue[c][OrderType.SELL][80][0] self.assertEqual(left_sell_order.amount, 100) self.assertEqual(left_sell_order.price, 80)
def market__set_amplification(self, args): import os from src.bank import Bank from src.household import Household from src.firm import Firm from src.environment import Environment from src.transaction import Transaction from src.market import Market text = "This test checks market.set_amplification \n" self.print_info(text) # # INITIALIZATION # environment_directory = str(args[0]) identifier = str(args[1]) log_directory = str(args[2]) # Configure logging parameters so we get output while the program runs logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO) logging.info( 'START logging for test market__set_amplification in run: %s', environment_directory + identifier + ".xml") # Construct household filename environment = Environment(environment_directory, identifier) # generate a bank bank = Bank() bank.identifier = "test_bank" environment.banks.append(bank) # generate a firm firm = Firm() firm.identifier = "test_firm" environment.firms.append(firm) # generate a household household = Household() household.identifier = "test_household" environment.households.append(household) # # TESTING # market = Market("market_id") print("Market's amplification:") print(market.get_amplification()) print("Changing amplification") market.set_amplification(0.55) print("Market's amplification:") print(market.get_amplification())
def test_initial_company(self): m = Market() self.assertEqual(len(m.companies), 1)
def market__rationing_abstract(self, args): import os from src.bank import Bank from src.household import Household from src.firm import Firm from src.environment import Environment from src.transaction import Transaction from src.market import Market text = "This test checks market.rationing_abstract \n" self.print_info(text) # # INITIALIZATION # environment_directory = str(args[0]) identifier = str(args[1]) log_directory = str(args[2]) # Configure logging parameters so we get output while the program runs logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO) logging.info( 'START logging for test market__rationing_abstract in run: %s', environment_directory + identifier + ".xml") # Construct household filename environment = Environment(environment_directory, identifier) # generate a bank bank = Bank() bank.identifier = "test_bank" environment.banks.append(bank) # generate a firm firm = Firm() firm.identifier = "test_firm" environment.firms.append(firm) # generate a household household = Household() household.identifier = "test_household" environment.households.append(household) # # TESTING # def matching_agents_basic(agent_one, agent_two): import difflib seq = difflib.SequenceMatcher(a=agent_one.lower(), b=agent_two.lower()) return seq.ratio() def matching_agents_basic_inv(agent_one, agent_two): import difflib seq = difflib.SequenceMatcher(a=agent_one.lower(), b=agent_two.lower()) return 1 - seq.quick_ratio() def allow_match_basic(agent_one, agent_two): return True def allow_match_basic(agent_one, agent_two): if ((agent_one == 'aaaaaa' and agent_two == 'aaaabb') or (agent_one == 'aaaabb' and agent_two == 'aaaaaa')): return False else: return True market = Market("market") rationed = market.rationing_abstract( [["aaaaaa", 5], ["bbbbbb", 7], ["aaaabb", -3], ["aabbbb", -4]], matching_agents_basic, allow_match_basic) print( "Pairs found through abstract rationing prioritising similar names:" ) print(rationed) rationed = market.rationing_abstract( [["aaaaaa", 5], ["bbbbbb", 7], ["aaaabb", -3], ["aabbbb", -4]], matching_agents_basic_inv, allow_match_basic) print( "Pairs found through abstract rationing prioritising dissimilar names:" ) print(rationed) rationed = market.rationing_abstract( [["aaaaaa", 5], ["bbbbbb", 7], ["aaaabb", -3], ["aabbbb", -4]], matching_agents_basic_inv, allow_match_basic) print( "Pairs found through abstract rationing prioritising similar names with 'aaaaaa'>'aaaabb' not allowed:" ) print(rationed)
def consume_rationed(self, environment, time): # We want the consumption to be done in random pairs # We use rationing from market clearing class to do that # Price is static for this example, otherwise we can't use rationing # and need some other market clearing price = 10.0 environment.variable_parameters["price_of_goods"] = price # We need a list of agents and their demand or supply # Supply is denoted with positive float, demand with negative float for_rationing = [] # Firms give us their supply, we assume that since the goods are # perishable their supply is all they have in stock from src.helper import Helper helper = Helper() for firm in environment.firms: # amount = round(helper.leontief([firm.get_account("labour")], [1/firm.productivity]), 0) amount = helper.cobb_douglas( firm.get_account("labour"), firm.get_account("capital"), firm.total_factor_productivity, firm.labour_elasticity, firm.capital_elasticity) * price for_rationing.append([firm, amount]) # Households give use their demand, we assume that they want to # consume the part of their wealth (cash and deposits) that they # do not want to save (determined through propensity to save) # We denote demand in units of the goods, so we divide the cash # households want to spend by price to get the demand for household in environment.households: demand = 0.0 # demand = -round(((household.get_account("deposits") * (1 - household.propensity_to_save)) / price), 0) demand = -((household.get_account("deposits") * (1 - household.propensity_to_save)) / price) # demand = -household.get_account("deposits")/price for_rationing.append([household, demand]) # We import the market clearing class # Put the appropriate settings, i.e. # tolerance of error, resolution of search # and amplification for exponential search # This does not matter for rationing # But in principle we need to initialize # with these values market = Market("market") # And we find the rationing, ie the amounts # of goods sold between pairs of agents # TESTING THE ABSTRACT RATIONING # The matching function means that all pairs will have the same priority def matching_agents_basic(agent_one, agent_two): return 1.0 # The below function means that all pairs are allowed def allow_match_basic(agent_one, agent_two): return True # We find the actual trades rationed = market.rationing_abstract(for_rationing, matching_agents_basic, allow_match_basic) # Then we go through the rationing # and move the goods and cash appropriately for ration in rationed: # # A (from) L (to) # bank loan deposit # household goods loan # firm deposit goods # environment.new_transaction("goods", "", ration[1].identifier, ration[0].identifier, ration[2], 0, 0, -1) random_bank = random.choice(environment.banks) environment.new_transaction("deposits", "", ration[0].identifier, random_bank.identifier, ration[2] * price, random_bank.interest_rate_deposits, 0, -1) environment.new_transaction("loans", "", random_bank.identifier, ration[1].identifier, ration[2] * price, random_bank.interest_rate_loans, 0, -1) # We print the action of selling to the screen print( "{}s sold {}d units of goods at a price {}f to {}s at time {}d." .format(ration[0].identifier, ration[2], price, ration[1].identifier, time)) logging.info(" goods consumed on step: %s", time)
def sell_labour(self, environment, time): # First we find the market equilibrium price # Important to note that this currently does # not depend on the wealth of the buyers # That is their demand may be higher than # what they can actually buy, which may be ok # We set the values necessary for tatonnement # The list of sellers and their supply functions sellers = [] for agent in environment.households: sellers.append([agent, agent.supply_of_labour_solow]) # And the list of buyers and their demand functions buyers = [] for agent in environment.firms: buyers.append([agent, agent.demand_for_labour_solow]) # We may start the search for price at some specific point # Here we pass 0, which means it'll start looking at a # random point between 0 and 10 starting_price = 0.0 # We initialize the price price = 0.0 # Put the appropriate settings, i.e. desired identifier market = Market("market") # And we find the market price of labour # given supply and demand of the agents # and tolerance of error, resolution of search # and amplification factor for exponential search price = market.tatonnement(sellers, buyers, starting_price, 0.00000000001, 0.01, 1.1) environment.variable_parameters["price_of_labour"] = price # now we use rationing to find the actual transactions between agents for_rationing = [] for household in environment.households: for_rationing.append( [household, household.supply_of_labour_solow(price)]) for firm in environment.firms: for_rationing.append([firm, -firm.demand_for_labour_solow(price)]) # And we find the rationing, ie the amounts # of goods sold between pairs of agents rationed = market.rationing(for_rationing) # # A (from) L (to) # bank loan deposit # household deposit labour # firm labour loan # for ration in rationed: # The labour is an asset (production factor) for the firm # and a liability (promise to work) for the household environment.new_transaction("labour", "", ration[1].identifier, ration[0].identifier, ration[2], 0, 0, -1) random_bank = random.choice(environment.banks) # Deposit is a liability of the bank # and an asset of the household environment.new_transaction("deposits", "", ration[0].identifier, random_bank.identifier, ration[2] * price, random_bank.interest_rate_deposits, 0, -1) # Loan is an asset of the bank # and a liability of the firm environment.new_transaction("loans", "", random_bank.identifier, ration[1].identifier, ration[2] * price, random_bank.interest_rate_loans, 0, -1) # We print the action of selling to the screen print( "{}s sold {}d units of labour at a price {}f to {}s at time {}d." .format(ration[0].identifier, ration[2], price, ration[1].identifier, time)) logging.info(" labour sold to firms on step: %s", time)
def market__rationing_abstract(self, args): import os from src.bank import Bank from src.household import Household from src.firm import Firm from src.environment import Environment from src.transaction import Transaction from src.market import Market text = "This test checks market.rationing_abstract \n" self.print_info(text) # # INITIALIZATION # environment_directory = str(args[0]) identifier = str(args[1]) log_directory = str(args[2]) # Configure logging parameters so we get output while the program runs logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %H:%M:%S', filename=log_directory + identifier + ".log", level=logging.INFO) logging.info('START logging for test market__rationing_abstract in run: %s', environment_directory + identifier + ".xml") # Construct household filename environment = Environment(environment_directory, identifier) # generate a bank bank = Bank() bank.identifier = "test_bank" environment.banks.append(bank) # generate a firm firm = Firm() firm.identifier = "test_firm" environment.firms.append(firm) # generate a household household = Household() household.identifier = "test_household" environment.households.append(household) # # TESTING # def matching_agents_basic(agent_one, agent_two): import difflib seq = difflib.SequenceMatcher(a=agent_one.lower(), b=agent_two.lower()) return seq.ratio() def matching_agents_basic_inv(agent_one, agent_two): import difflib seq = difflib.SequenceMatcher(a=agent_one.lower(), b=agent_two.lower()) return 1-seq.quick_ratio() def allow_match_basic(agent_one, agent_two): return True def allow_match_basic(agent_one, agent_two): if ((agent_one == 'aaaaaa' and agent_two == 'aaaabb') or (agent_one == 'aaaabb' and agent_two == 'aaaaaa')): return False else: return True market = Market("market") rationed = market.rationing_abstract([["aaaaaa", 5], ["bbbbbb", 7], ["aaaabb", -3], ["aabbbb", -4]], matching_agents_basic, allow_match_basic) print("Pairs found through abstract rationing prioritising similar names:") print(rationed) rationed = market.rationing_abstract([["aaaaaa", 5], ["bbbbbb", 7], ["aaaabb", -3], ["aabbbb", -4]], matching_agents_basic_inv, allow_match_basic) print("Pairs found through abstract rationing prioritising dissimilar names:") print(rationed) rationed = market.rationing_abstract([["aaaaaa", 5], ["bbbbbb", 7], ["aaaabb", -3], ["aabbbb", -4]], matching_agents_basic_inv, allow_match_basic) print("Pairs found through abstract rationing prioritising similar names with 'aaaaaa'>'aaaabb' not allowed:") print(rationed)