Ejemplo n.º 1
0
    def __init__(self):

        self.prices = [[INIT_PRICES[i] for i in range(N_GOODS)]
                       for j in range(N_CITIES)]
        self.prices_ema9 = [[INIT_PRICES[i] for i in range(N_GOODS)]
                            for j in range(N_CITIES)]
        self.prices_ema21 = [[INIT_PRICES[i] for i in range(N_GOODS)]
                             for j in range(N_CITIES)]

        self.ask = [[0 for i in range(N_GOODS)] for j in range(N_CITIES)]
        self.bid = [[0 for i in range(N_GOODS)] for j in range(N_CITIES)]

        self.trends = [[0 for i in range(N_GOODS)] for j in range(N_CITIES)]

        # compute how much fraction can be bought, sold
        self.ask_ratios = [[0 for i in range(N_GOODS)]
                           for j in range(N_CITIES)]
        self.bid_ratios = [[0 for i in range(N_GOODS)]
                           for j in range(N_CITIES)]

        self.ref_salary = [INIT_SALARY for i in range(N_CITIES)]
        self.ref_productivity = [PRODUCTIVITIES[i] for i in range(N_GOODS)]

        # ranking of products
        self.ranks = [[0 for i in range(N_GOODS)] for j in range(N_CITIES)]

        # internal calendar
        self.calendar = Calendar()
Ejemplo n.º 2
0
    def __init__(self):

        self.cities = [City(i) for i in range(N_CITIES)]

        self.goodMarket = GoodMarket()
        self.forexMarket = ForexMarket()

        self.calendar = Calendar()
Ejemplo n.º 3
0
    def __init__(self):

        self.prices = [[1.0 for i in range(N_CITIES)] for j in range(N_CITIES)]
        self.prices_ema9 = [[1.0 for i in range(N_CITIES)] for j in range(N_CITIES)]
        self.prices_ema21 = [[1.0 for i in range(N_CITIES)] for j in range(N_CITIES)]

        self.ask = [[0 for i in range(N_CITIES)] for j in range(N_CITIES)]
        self.bid = [[0 for i in range(N_CITIES)] for j in range(N_CITIES)]

        self.trends = [[0 for i in range(N_CITIES)] for j in range(N_CITIES)]

        # compute how much fraction can be bought, sold
        self.ask_ratios = [[0 for i in range(N_CITIES)] for j in range(N_CITIES)]
        self.bid_ratios = [[0 for i in range(N_CITIES)] for j in range(N_CITIES)]

        # internal calendar
        self.calendar = Calendar()
Ejemplo n.º 4
0
    def __init__(self, city_id, firm_id, product):

        self.city_id = city_id
        self.firm_id = firm_id
        self.product = product

        self.risk_beta = uniform(0, 2)

        self.cash = [0 for i in range(N_CITIES)]

        self.salary_budget = [0 for i in range(N_CITIES)]
        self.purchase_budget = [0 for i in range(N_CITIES)]
        self.employ_budget = [0 for i in range(N_CITIES)]
        self.invest_budget = [0 for i in range(N_CITIES)]
        self.debt = [0 for i in range(N_CITIES)]

        # initial cash
        self.salary_budget[city_id] = INIT_FIRM_CASH

        self.employees = INIT_EMPLOYEES
        self.salary = INIT_SALARY

        self.productivity = PRODUCTIVITIES[self.product]

        self.ask_orders = {}
        self.bid_orders = {}

        self.ingredients = []
        for i in range(N_GOODS):
            if INGREDIENTS[self.product][i] > 0:
                self.ingredients.append((i, INGREDIENTS[self.product][i]))
                self.ask_orders[i] = {}

        self.bid_orders[self.product] = {}

        self.inventory = [0 for i in range(N_GOODS)]
        for ingredient in self.ingredients:
            self.inventory[ingredient[
                0]] = self.employees * self.productivity * ingredient[1]

        self.change_prod = False
        self.only_domestic_sales = True

        self.calendar = Calendar()

        self.employ_date = randint(1, 20)
Ejemplo n.º 5
0
    def __init__(self, city_id):

        self.city_id = city_id

        self.citizens = INIT_CITIZENS
        self.employed = INIT_CITIZENS

        # instantiate and populate the firms
        idx = 0
        self.firms = []
        for i in range(N_GOODS):
            for j in range(INIT_FIRMS[i]):
                self.firms.append(Firm(self.city_id, idx, i))
                idx += 1

        self.cash = [0 for i in range(N_CITIES)]
        self.cash[self.city_id] = INIT_CITY_CASH

        self.liability = [0 for i in range(N_CITIES)]

        self.markup = BASE_MARKUP
        self.ref_salary = INIT_SALARY

        self.budget = 0

        self.budget_ratio = [BUDGET_RATIO[i] for i in range(N_GOODS)]

        self.reserve = [0 for i in range(N_CITIES)]
        self.debt = [0 for i in range(N_CITIES)]

        self.ask_order = {}
        for i in range(N_GOODS):
            if BUDGET_RATIO[i] > 0:
                self.ask_order[i] = {}

        # internal calendar
        self.calendar = Calendar()
Ejemplo n.º 6
0
class World():

    def __init__(self):

        self.cities = [City(i) for i in range(N_CITIES)]

        self.goodMarket = GoodMarket()
        self.forexMarket = ForexMarket()

        self.calendar = Calendar()

    def evolve(self):

        '''
        evolve one day in the world, which includes all the activities
        of all agents in a cycle

        return None
        '''

        global_ask_order = [[0 for i in range(N_GOODS)] for j in range(N_CITIES)]
        global_bid_order = [[0 for i in range(N_GOODS)] for j in range(N_CITIES)]

        for city in self.cities:
            city.firms_decide_budget(self.goodMarket.prices, self.goodMarket.trends)

        for city in self.cities:
            city.firms_make_products()

        for city in self.cities:
            ask_order = city.firms_get_ask_orders()

            for i in range(N_CITIES):
                for j in range(N_GOODS):
                    global_ask_order[i][j] += ask_order[i][j]

        for city in self.cities:
            bid_order = city.firms_get_bid_orders(self.goodMarket.prices, self.forexMarket.prices)

            for i in range(N_CITIES):
                for j in range(N_GOODS):
                    global_bid_order[i][j] += bid_order[i][j]

        for city in self.cities:
            order = city.decide_purchase(self.goodMarket.prices)

            for k, v in order.items():
                global_ask_order[v["city"]][k] += v["amount"]

        self.goodMarket.update_ask_transactions(global_ask_order)
        self.goodMarket.update_bid_transactions(global_bid_order)
        ask_ratios, bid_ratios = self.goodMarket.update_price()

        for city in self.cities:
            city.process_transactions(ask_ratios, bid_ratios, self.goodMarket.prices)

        # decide forex transactions

        # decide investment

        # decide employment 
        for city in self.cities:
            city.firms_decide_employ()

        # city logistics

        # miscellaneous
        for city in self.cities:
            city.advance_day()

        self.goodMarket.advance_day()
        self.forexMarket.advance_day()
        self.calendar.advance_day()

    def output_price(self, f_price_hist):
        f_price_hist.write("{},{},{},{},{},{}\n".format(
            self.calendar.year, self.calendar.month, self.calendar.day,
            self.goodMarket.prices[0][WATER],self.goodMarket.prices[0][WHEAT],self.goodMarket.prices[0][BREAD]
        ))
Ejemplo n.º 7
0
class ForexMarket():


    def __init__(self):

        self.prices = [[1.0 for i in range(N_CITIES)] for j in range(N_CITIES)]
        self.prices_ema9 = [[1.0 for i in range(N_CITIES)] for j in range(N_CITIES)]
        self.prices_ema21 = [[1.0 for i in range(N_CITIES)] for j in range(N_CITIES)]

        self.ask = [[0 for i in range(N_CITIES)] for j in range(N_CITIES)]
        self.bid = [[0 for i in range(N_CITIES)] for j in range(N_CITIES)]

        self.trends = [[0 for i in range(N_CITIES)] for j in range(N_CITIES)]

        # compute how much fraction can be bought, sold
        self.ask_ratios = [[0 for i in range(N_CITIES)] for j in range(N_CITIES)]
        self.bid_ratios = [[0 for i in range(N_CITIES)] for j in range(N_CITIES)]

        # internal calendar
        self.calendar = Calendar()

    def update_ask_transactions(self, transactions):

        '''
        collect and record all ask orders

        transaction : list => a tuple contains
            1. city_id of the firm
            2. firm_id of the firm
            3. city_id where the product is sold
            4. the forex (id) to be bought
            5. amount

        return None
        '''

        # transaction contain 
        # [0-2] self.city_id, self.firm_id, self.city_id
        # [3-4] forex_index, amount

        for i in range(N_CITIES):
            for j in range(N_CITIES):
                self.ask[i][j] = 0

        for trans in transactions:
            self.ask[trans[2]][trans[3]] += trans[4]

    def update_bid_transactions(self, transactions):

        '''
        collect and record all ask orders

        transaction : list => a tuple contains
            1. city_id of the firm
            2. firm_id of the firm
            3. city_id where the product is sold
            4. the forex (id) to be sold
            5. amount

        return None
        '''

        # transaction contain 
        # [0-2] self.city_id, self.firm_id, self.city_id
        # [3-4] good_index, amount

        for i in range(N_CITIES):
            for j in range(N_CITIES):
                self.bid[i][j] = 0

        for trans in transactions:
            self.bid[trans[2]][trans[3]] += trans[4]

    def update_price(self):

        '''
        update the product prices based on non-equilibrium pricing
        based on the demand and supply of that round    

        return 
            self.ask_ratios: list => the fraction to be bought 
            self.bid_ratios: list => the fraction to be sold
        '''

        for i in range(N_CITIES):
            for j in range(N_CITIES):

                self.prices[i][j] *= exp((self.ask[i][j] - self.bid[i][j]) / (self.ask[i][j] + self.bid[i][j] + 1))

                if self.ask[i][j] > self.bid[i][j]:
                    self.ask_ratios[i][j] = self.bid[i][j] / self.ask[i][j]
                    self.bid_ratios[i][j] = 1
                elif self.ask[i][j] < self.bid[i][j]:
                    self.ask_ratios[i][j] = 1
                    self.bid_ratios[i][j] = self.ask[i][j] / self.bid[i][j]
                else:
                    self.ask_ratios[i][j] = 1
                    self.bid_ratios[i][j] = 1

                self.prices_ema9[i][j] = 0.2 * self.prices[i][j] + 0.8 * self.prices_ema9[i][j]
                self.prices_ema21[i][j] = 0.099 * self.prices[i][j] + 0.901 * self.prices_ema21[i][j]

                if self.prices_ema9[i][j] > self.prices_ema21[i][j]:
                    self.trends[i][j] = 1
                elif self.prices_ema9[i][j] > self.prices_ema21[i][j]:
                    self.trends[i][j] = -1

        return self.ask_ratios, self.bid_ratios

    def advance_day(self):

        '''
        advance to the next day
        
        return None
        '''

        self.calendar.advance_day()
Ejemplo n.º 8
0
class City():
    def __init__(self, city_id):

        self.city_id = city_id

        self.citizens = INIT_CITIZENS
        self.employed = INIT_CITIZENS

        # instantiate and populate the firms
        idx = 0
        self.firms = []
        for i in range(N_GOODS):
            for j in range(INIT_FIRMS[i]):
                self.firms.append(Firm(self.city_id, idx, i))
                idx += 1

        self.cash = [0 for i in range(N_CITIES)]
        self.cash[self.city_id] = INIT_CITY_CASH

        self.liability = [0 for i in range(N_CITIES)]

        self.markup = BASE_MARKUP
        self.ref_salary = INIT_SALARY

        self.budget = 0

        self.budget_ratio = [BUDGET_RATIO[i] for i in range(N_GOODS)]

        self.reserve = [0 for i in range(N_CITIES)]
        self.debt = [0 for i in range(N_CITIES)]

        self.ask_order = {}
        for i in range(N_GOODS):
            if BUDGET_RATIO[i] > 0:
                self.ask_order[i] = {}

        # internal calendar
        self.calendar = Calendar()

    def firms_get_ask_orders(self):
        '''
        get from firm the ask orders for their purchase
        and add them up for the total demand 

        return firms_ask: dict => key = [city][item], value = amount
        '''

        firms_ask = [[0 for i in range(N_GOODS)] for j in range(N_CITIES)]

        for firm in self.firms:
            firm_orders = firm.decide_prod_ask_order()
            for k, v in firm_orders.items():
                firms_ask[v["city"]][k] += v["amount"]

        return firms_ask

    def firms_get_bid_orders(self, prices, rates):
        '''
        get from firm the ask orders for their purchase
        and add them up for the total supply 

        return firms_ask: dict => key = [city][item] value=amount
        '''

        firms_bid = [[0 for i in range(N_GOODS)] for j in range(N_CITIES)]

        for firm in self.firms:
            firm_orders = firm.decide_prod_bid_order(prices, rates)
            for k, v in firm_orders.items():
                firms_bid[v["city"]][k] += v["amount"]

        return firms_bid

    def firms_make_products(self):
        '''
        ask all the firms to make the products

        return None
        '''

        for firm in self.firms:
            salary = firm.make_product()
            self.cash[salary[0]] += salary[1]

    def firms_decide_budget(self, prices, trends):
        '''
        ask all the firms to allocate budget for buying 
        ingredients, paying salary, expand and invest

        prices: list => the list containing prices
        from all cities of all products
        trends: list => the list containing whether 
        the product is growing popular

        return None
        '''

        for firm in self.firms:
            firm.allocate_budget(prices, trends)

    def decide_purchase(self, prices: list):
        '''
        the state decide how much new liabilities (new money)
        to support the system and return the the dict for the ask
        order

        prices: list: the list containing all products price in all
        cities
        return ask_order: dict => key = [city][product] value=amount
        '''

        # first print the money
        budget = self.ref_salary * self.citizens
        new_money = budget * self.markup
        #new_money = round(new_money, 2)

        self.liability[self.city_id] += new_money
        self.cash[self.city_id] += new_money
        budget += new_money

        if self.cash[self.city_id] > 0:
            for i in range(N_GOODS):
                if self.budget_ratio[i] > 0:
                    x = int(budget * self.budget_ratio[i] /
                            prices[self.city_id][i])
                    self.ask_order[i]["city"] = self.city_id
                    self.ask_order[i]["amount"] = x

        print("City:{} Ask order:{} New money:{}".format(
            self.city_id, self.ask_order, new_money))
        return self.ask_order

    def process_transactions(self, ask_ratios, bid_ratios, prices):
        '''
        ask all firms to process the payment and delivery (recipient) 
        of the bought and sold products. also resolve the state's 
        purchase order

        ask_ratios: List => how much fraction of good can be received from purchase
        bid_ratios: List => how much fraction of good can be sold in selling
        prices: List => the list containing prices of all products in all cities
        return None
        '''

        for firm in self.firms:
            firm.process_transactions(ask_ratios, bid_ratios, prices)

        for k, v in self.ask_order.items():

            amt = v["amount"] * ask_ratios[v["city"]][k] * prices[v["city"]][k]
            #amt = round(amt, 2)

            self.cash[v["city"]] -= amt

    def population_growth(self):
        '''
        the population grows assuming some simple birth rates from statistics

        return None
        '''

        annual_salary = 252 * self.ref_salary
        self.citizens += self.reserve / annual_salary

    def firms_decide_employ(self):
        '''
        the firm decides how many new employees to be employed
        or how many employees to resign due to shortage of budget

        return None
        '''

        for firm in self.firms:

            if firm.employ_date == self.calendar.day:

                employment = firm.decide_employ()

                if employment:
                    self.reserve[self.city_id] += employment[3]
                    self.debt[self.city_id] += employment[4]
                    self.employed += employment[5]

    def grow_new_firm(self, rank_goods: list):
        '''
        generate new firms with the product selected by how popular the 
        product is 

        return None
        '''

        n_new_firms = int(len(self.firms) * 0.01)

        for i in range(n_new_firms):

            found_job = False
            for j in range(N_GOODS):
                x = random()
                if x < 0.5:
                    self.product = rank_goods[self.city_id][j]
                    job = j
                    found_job = True
                    break

                if not found_job:
                    job = rank_goods[self.city_id][-1]

            self.firms.append(Firm(self.city_id, len(self.firms), job))

    def advance_day(self):
        '''
        advance the calendar day

        return None
        '''

        self.calendar.advance_day()

        for firm in self.firms:
            firm.advance_day()
Ejemplo n.º 9
0
class Firm():
    def __init__(self, city_id, firm_id, product):

        self.city_id = city_id
        self.firm_id = firm_id
        self.product = product

        self.risk_beta = uniform(0, 2)

        self.cash = [0 for i in range(N_CITIES)]

        self.salary_budget = [0 for i in range(N_CITIES)]
        self.purchase_budget = [0 for i in range(N_CITIES)]
        self.employ_budget = [0 for i in range(N_CITIES)]
        self.invest_budget = [0 for i in range(N_CITIES)]
        self.debt = [0 for i in range(N_CITIES)]

        # initial cash
        self.salary_budget[city_id] = INIT_FIRM_CASH

        self.employees = INIT_EMPLOYEES
        self.salary = INIT_SALARY

        self.productivity = PRODUCTIVITIES[self.product]

        self.ask_orders = {}
        self.bid_orders = {}

        self.ingredients = []
        for i in range(N_GOODS):
            if INGREDIENTS[self.product][i] > 0:
                self.ingredients.append((i, INGREDIENTS[self.product][i]))
                self.ask_orders[i] = {}

        self.bid_orders[self.product] = {}

        self.inventory = [0 for i in range(N_GOODS)]
        for ingredient in self.ingredients:
            self.inventory[ingredient[
                0]] = self.employees * self.productivity * ingredient[1]

        self.change_prod = False
        self.only_domestic_sales = True

        self.calendar = Calendar()

        self.employ_date = randint(1, 20)

    def allocate_budget(self, prices, trends):
        '''
        decides how much budget is allocated to (1) buying ingredient
        (2) salary (3) expansion and (4) investment

        prices : List => Containing prices of all products in all cities
        trends : List => Containing trends (if price is rising) of all products
        in all cities

        return None
        '''

        x = max(
            self.employees * self.salary - self.salary_budget[self.city_id], 0)
        #x = round(x, 2)

        self.cash[self.city_id] -= x
        self.salary_budget[self.city_id] += x

        x = 0
        for ingredient in self.ingredients:
            x = self.employees * self.productivity * prices[self.city_id][
                ingredient[0]]
        #x = round(x, 2)

        self.cash[self.city_id] -= x
        self.purchase_budget[self.city_id] += x

        if self.cash[self.city_id] < 0 or (
                self.cash[self.city_id] >= 0
                and trends[self.city_id][self.product] > 0):
            x = self.cash[self.city_id]
            self.cash[self.city_id] -= x
            self.employ_budget[self.city_id] += x
        else:
            x = self.cash[self.city_id]
            self.cash[self.city_id] -= x
            self.invest_budget[self.city_id] += x

        #print("City{}-Firm{} allocate_budget: cash:{} salary:{} purchase:{} employ:{} invest:{}".format(
        #    self.city_id, self.firm_id, self.cash[self.city_id], self.salary_budget[self.city_id],
        #    self.purchase_budget[self.city_id], self.employ_budget[self.city_id], self.invest_budget[self.city_id]
        #))

    def decide_prod_ask_order(self):
        '''
        decide to purchase the ingredient from the market based on the 
        daily production

        return ask_order : Dict => key = [product] subkey = [city, amount]
        '''

        for ingredient in self.ingredients:
            self.ask_orders[ingredient[0]]["city"] = self.city_id
            self.ask_orders[ingredient[0]][
                "amount"] = ingredient[1] * self.employees * self.productivity

        #print("City{}-Firm{} ask_order: {}".format(
        #    self.city_id, self.firm_id, self.ask_orders
        #))

        return self.ask_orders

    def decide_prod_bid_order(self, prices, rates):
        '''
        decide how many products to be sold based on inventory

        prices : List => prices of all products in all cities
        rates : List => exchange rate of all currencies

        return ask_order : Dict => key = [product] subkey = [city, amount]
        '''

        # decide which city to sell the product
        if self.only_domestic_sales:
            city_id = self.city_id

        self.bid_orders[self.product]["city"] = city_id
        self.bid_orders[self.product]["amount"] = self.inventory[self.product]

        #print("City{}-Firm{} bid_order: {}".format(
        #    self.city_id, self.firm_id, self.bid_orders
        #))

        return self.bid_orders

    def process_transactions(self, ask_ratios, bid_ratios, prices):
        '''
        receive transaction result from market (through city) and 
        complete the tranasaction record 

        ask_ratios : List => fraction of received amount of products
        bid_ratios : List => fraction of sold amount of products

        return None
        '''

        for k, v in self.ask_orders.items():

            amt = v["amount"] * ask_ratios[v["city"]][k] * prices[v["city"]][k]
            #amt = round(amt, 2)

            self.inventory[k] += ask_ratios[v["city"]][k] * v["amount"]
            self.purchase_budget[v["city"]] -= amt

        for k, v in self.bid_orders.items():

            amt = v["amount"] * bid_ratios[v["city"]][k] * prices[v["city"]][k]
            #amt = round(amt, 2)

            self.inventory[k] -= ask_ratios[v["city"]][k] * v["amount"]
            self.cash[v["city"]] += amt

        #print("City{}-Firm{} cash:{} inventory:{} Ask:{} Bid:{}".format(
        #    self.city_id, self.firm_id, self.cash[self.city_id], self.inventory, self.ask_orders, self.bid_orders
        #))

    def make_product(self):
        '''
        make the product based on current ingredient inventory and 
        workers available

        return tuple (firm's city id, amount of salary to pay to workers)
        '''

        x = self.employees * self.productivity
        for ingredient in self.ingredients:
            x = min(x, self.inventory[ingredient[0]] / ingredient[1])

        for ingredient in self.ingredients:
            self.inventory[ingredient[0]] -= ingredient[1] * x
        self.inventory[self.product] += x

        salary = self.employees * self.salary
        #salary = round(salary, 2)

        self.salary_budget[self.city_id] -= salary
        return (self.city_id, salary)

    def decide_employ(self):
        '''
        decide employ or send away workers depending on the loan status

        return employment : tuple => 
            (city_id, firm_id, city_to_pay, amount_to_pay, change in debt,
            change in labour workforce)
        '''

        employment = None

        x = self.employees * self.salary * 21
        y = x / (1 + self.risk_beta)

        if self.employ_budget[self.city_id] > y:
            debt = y * self.risk_beta

            self.debt[self.city_id] += debt
            self.employ_budget[self.city_id] -= y

            self.employees += 1

            employment = (self.city_id, self.firm_id, self.city_id, x, debt, 1)

        elif self.employees > 1 and self.employ_budget[
                self.city_id] < -(self.employees - 1) * y:

            unemployed = 1
            payable = (self.employees - 1) * x

            for i in range(self.employees - 1, 1, -1):
                if payable > -self.employ_budget[self.city_id]:
                    break

                unemployed += 1
                payable += (i - 1) * x

            self.employees -= unemployed

            debt_reduction = payable * self.risk_beta / (1 + self.risk_beta)
            self.debt[self.city_id] -= debt_reduction
            self.employ_budget[self.city_id] += payable / (1 + self.risk_beta)

            employment = (self.city_id, self.firm_id, self.city_id, -payable,
                          -debt_reduction, -unemployed)

        #if employment:
        #    print("City{}-Firm{} employ:{} employment:{}".format(
        #        self.city_id, self.firm_id, self.employ_budget[self.city_id], employment
        #    ))

        return employment

    def change_production(self, rank_goods):
        '''
        decide switch to other production line

        rank_goods : List => ranking of the products according to their 
        productivity

        return None
        '''

        if self.change_prod and self.employees == 1:

            cum_prod = 0.5
            switched_job = False

            for i in range(N_GOODS):
                x = random()
                if x < 0.5:

                    job = i
                    self.product = rank_goods[self.city_id][job]
                    switched_job = True
                    break

            if switched_job:

                self.ask_orders.clear()
                self.bid_orders.clear()

                for i in range(self.ingredients):
                    self.ingredients.pop()

                for i in range(N_GOODS):
                    if INGREDIENTS[self.product] > 0:
                        self.ingredients.append((i, INGREDIENTS[self.product]))
                        self.ask_orders[i] = {}

                self.bid_orders[job] = {}

    def advance_day(self):

        self.calendar.advance_day()
Ejemplo n.º 10
0
    def getdockCalendar(self):

        self.calendar = Calendar(self)
Ejemplo n.º 11
0
class GoodMarket():
    def __init__(self):

        self.prices = [[INIT_PRICES[i] for i in range(N_GOODS)]
                       for j in range(N_CITIES)]
        self.prices_ema9 = [[INIT_PRICES[i] for i in range(N_GOODS)]
                            for j in range(N_CITIES)]
        self.prices_ema21 = [[INIT_PRICES[i] for i in range(N_GOODS)]
                             for j in range(N_CITIES)]

        self.ask = [[0 for i in range(N_GOODS)] for j in range(N_CITIES)]
        self.bid = [[0 for i in range(N_GOODS)] for j in range(N_CITIES)]

        self.trends = [[0 for i in range(N_GOODS)] for j in range(N_CITIES)]

        # compute how much fraction can be bought, sold
        self.ask_ratios = [[0 for i in range(N_GOODS)]
                           for j in range(N_CITIES)]
        self.bid_ratios = [[0 for i in range(N_GOODS)]
                           for j in range(N_CITIES)]

        self.ref_salary = [INIT_SALARY for i in range(N_CITIES)]
        self.ref_productivity = [PRODUCTIVITIES[i] for i in range(N_GOODS)]

        # ranking of products
        self.ranks = [[0 for i in range(N_GOODS)] for j in range(N_CITIES)]

        # internal calendar
        self.calendar = Calendar()

    def update_ask_transactions(self, transactions):
        '''
        collect and record all ask orders

        transaction : list => a tuple contains
            1. city_id of the firm
            2. firm_id of the firm
            3. city_id where the product is sold
            4. the product (id) to be sold
            5. amount

        return None
        '''

        # transaction contain
        # [0-2] self.city_id, self.firm_id, self.city_id
        # [3-4] good_index, amount

        for i in range(N_CITIES):
            for j in range(N_GOODS):
                self.ask[i][j] = transactions[i][j]

    def update_bid_transactions(self, transactions):
        '''
        collect and record all bid orders

        transaction : list => a tuple contains
            1. city_id of the firm
            2. firm_id of the firm
            3. city_id where the product is sold
            4. the product (id) to be sold
            5. amount

        return None
        '''

        # transaction contain
        # [0-2] self.city_id, self.firm_id, self.city_id
        # [3-4] good_index, amount

        for i in range(N_CITIES):
            for j in range(N_GOODS):
                self.bid[i][j] = transactions[i][j]

    def update_price(self):
        '''
        update the product prices based on non-equilibrium pricing
        based on the demand and supply of that round    

        return 
            self.ask_ratios: list => the fraction to be bought 
            self.bid_ratios: list => the fraction to be sold
        '''

        for i in range(N_CITIES):
            for j in range(N_GOODS):

                self.prices[i][j] *= exp(0.05 *
                                         (self.ask[i][j] - self.bid[i][j]) /
                                         (self.ask[i][j] + self.bid[i][j] + 1))
                #self.prices[i][j] = round(self.prices[i][j], 2)

                if self.ask[i][j] > self.bid[i][j]:
                    self.ask_ratios[i][j] = self.bid[i][j] / self.ask[i][j]
                    self.bid_ratios[i][j] = 1
                elif self.ask[i][j] < self.bid[i][j]:
                    self.ask_ratios[i][j] = 1
                    self.bid_ratios[i][j] = self.ask[i][j] / self.bid[i][j]
                else:
                    self.ask_ratios[i][j] = 1
                    self.bid_ratios[i][j] = 1

                self.prices_ema9[i][
                    j] = 0.2 * self.prices[i][j] + 0.8 * self.prices_ema9[i][j]
                self.prices_ema21[i][j] = 0.099 * self.prices[i][
                    j] + 0.901 * self.prices_ema21[i][j]

                if self.prices_ema9[i][j] > self.prices_ema21[i][j]:
                    self.trends[i][j] = 1
                elif self.prices_ema9[i][j] > self.prices_ema21[i][j]:
                    self.trends[i][j] = -1

        print("Updated price:{} ask:{} bid{}".format(self.prices, self.ask,
                                                     self.bid))

        return self.ask_ratios, self.bid_ratios

    def rank_goods(self):
        '''
        order the product according to their profitability
        i.e. how much profit for selling one item

        return None
        '''

        # compute the market mark up
        costs = [[
            self.ref_salary[j] / self.ref_productivity[i]
            for i in range(N_GOODS)
        ] for j in range(N_CITIES)]

        for i in range(N_CITIES):
            for j1 in range(N_GOODS):
                for j2 in range(N_GOODS):
                    costs[i][j1] += costs[i][j2] * INGREDIENTS[j1][j2]

        markup = [[self.price[i][j] / costs[i][j] for j in range(N_GOODS)]
                  for i in range(N_CITIES)]

        for i in range(N_CITIES):
            ranks = np.argsort(np.array(self.costs[i]))[::-1]
            for j in range(N_GOODS):
                self.rank_goods[i][j] = ranks[j]

    def advance_day(self):
        '''
        advance to the next day
        
        return None
        '''

        self.calendar.advance_day()