def endow_labour(self, environment, time): # We make sure household get their labour endowment per step for household in environment.households: # First, we set a control variable that makes sure we have exactly # one transaction with "manhours", though this should in general # be the case, this should always run through the second if check = 0 for tranx in household.accounts: if tranx.type_ == "manhours": check = check + 1 # We check how many transactions with manhours are there for the household # If there are no "manhours" transactions then we create one and add it to the household's accounts if check == 0: # The amount is equal to the parameter read from the config of the household amount = household.labour # We create the transaction transaction = Transaction() # We add the appropriate values to the transaction transaction.this_transaction("manhours", "", household.identifier, household.identifier, amount, 0, 0, -1) # It's important to add the transaction using the method # from Transaction class and not manually transaction.add_transaction(environment) else: # If we have more than one "mahhours" transaction we raise an error raise LookupError("Labour transactions for a household haven't been properly removed.") logging.info(" labour endowed on step: %s", time)
class TransactionTests(TestCase): def setUp(self): self.transaction = Transaction(PUBLIC_KEY, 'receiver', 5) def test_init(self): self.assertEqual(self.transaction.sender, PUBLIC_KEY) self.assertEqual(self.transaction.receiver, 'receiver') self.assertEqual(self.transaction.amount, 5) def test_dict(self): transaction_dict = { 'sender': PUBLIC_KEY, 'receiver': 'receiver', 'amount': 5 } self.assertEqual(self.transaction.dict, transaction_dict) def test_verify_sig_passes(self): self.assertTrue(self.transaction.verify_signature(PRIVATE_KEY)) def test_verify_sig_fails(self): rng = Random.new().read priv_key = RSA.generate(1024, rng) rand_private_key = hexlify( priv_key.exportKey(format='DER')).decode('utf8') self.assertFalse(self.transaction.verify_signature(rand_private_key))
def add_transaction(self, type_, asset, from_id, to_id, amount, interest, maturity, time_of_default): from src.transaction import Transaction transaction = Transaction() transaction.this_transaction(type_, asset, from_id, to_id, amount, interest, maturity, time_of_default) self.accounts.append(transaction) del transaction # append() above does make a copy so we may delete for garbage collection
def add_transaction(self, type_, asset, from_id, to_id, amount, interest, maturity, time_of_default, environment): from src.transaction import Transaction transaction = Transaction() transaction.add_transaction(type_, asset, from_id, to_id, amount, interest, maturity, time_of_default, environment)
def make_deposits(self, environment, time): for household in environment.households: cash = 0.0 # total of cash available for the household control_deposits = 0 # checking if the household already has deposits # We calculate the available cash for tranx in household.accounts: if tranx.type_ == "cash": cash = cash + tranx.amount tranx.amount = 0 # And the number of existing deposits if tranx.type_ == "deposits": control_deposits = control_deposits + 1 # And move all available cash to deposits at the end of the step # If there are no deposits we create one in a bank # The bank is chosen randomly if control_deposits == 0: # We choose a bank randomly random_bank = random.choice(environment.banks) # Create a transaction transaction = Transaction() # Add the appropriate values to the transaction transaction.this_transaction("deposits", "", household.identifier, random_bank, amount, random_bank.interest_rate_deposits, 0, -1) # And add the transaction to the books (do it through function/not manually) transaction.add_transaction(environment) # If there are previous deposits we expand them linearly else: for tranx in household.accounts: if tranx.type_ == "deposits": # We add the remaining cash to the existing deposits # in equal proportions # Perhaps this can be done proportionate with regards # to the value of these deposits, but it's minor at this point tranx.amount = tranx.amount + (cash/control_deposits) logging.info(" deposits made on step: %s", time)
def transaction__get_time_of_default(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 text = "This test checks transaction.get_time_of_default \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 transaction__get_time_of_default in run: %s', environment_directory + identifier + ".xml") # Construct household filename environment = Environment(environment_directory, identifier) # # TESTING # print("Creating a transaction") transaction = Transaction() transaction.time_of_default = 1 print("Time of default: ") print(transaction.get_time_of_default())
def transfer_required_deposits(self): transaction = Transaction() value = round(float(self.r * self.get_account("D")), 4) transaction.this_transaction("rD", self.identifier, -3, value, self.rb, 0, -1) self.accounts.append(transaction) return -1.0 * value
def transfer_required_deposits(self): from src.transaction import Transaction transaction = Transaction() value = round(float(self.parameters["r"]*self.get_account("D")), 4) transaction.this_transaction("rD", self.identifier, -3, value, self.parameters["rb"], 0, -1) self.accounts.append(transaction) return -1.0*value
def transaction__add_transaction(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 text = "This test checks transaction.add_transaction \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 transaction__add_transaction 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 # print("Creating a transaction") transaction = Transaction() print("Assigning values") transaction.this_transaction("type", "asset", "test_household", "test_firm", 1, 2, 3, 4) print("Adding the transaction to the books") transaction.add_transaction(environment) print("The transaction:") print(transaction) print("The firm:") print(environment.get_agent_by_id("test_firm")) print("The household:") print(environment.get_agent_by_id("test_household"))
def initialize_standard_bank(self, bank, environment): from src.transaction import Transaction bank.identifier = "standard_bank_id" # deposits - we get the first household from the list of households # if there are no households it will be a blank which is fine for testing amount = 250.0 transaction = Transaction() transaction.this_transaction("deposits", "", environment.households[0:1][0], bank.identifier, amount, bank.interest_rate_deposits, 0, -1) # environment.households[0:1][0] is only for testing purposes DO NOT USE IN PRODUCTION # what it does is is takes the first household in environment, but if there are no # households (which happens in testing) it doesn't break down bank.accounts.append(transaction) # money - cash and equivalents amount = 100.0 transaction = Transaction() transaction.this_transaction("cash", "", bank.identifier, bank.identifier, amount, 0, 0, -1) bank.accounts.append(transaction) # loans - we get the first firm from the list of firms # if there are no firms it will be a blank which is fine for testing amount = 150.0 transaction = Transaction() transaction.this_transaction("loans", "", bank.identifier, environment.firms[0:1][0], amount, bank.interest_rate_loans, 0, -1) # environment.firms[0:1][0] is only for testing purposes DO NOT USE IN PRODUCTION # what it does is is takes the first firm in environment, but if there are no # firms (which happens in testing) it doesn't break down bank.accounts.append(transaction)
def initialize_standard_household(self, household, environment): from src.transaction import Transaction household.identifier = "standard_household_id" # identifier household.parameters["labour"] = 24.00 # labour to sell per step household.parameters["propensity_to_save"] = 0.40 # propensity to save # percentage of income household wants to save as deposits # deposits - we get the first bank from the list of banks # if there are no banks it will be a blank which is fine for testing amount = 200.0 transaction = Transaction() transaction.this_transaction("deposits", "", household.identifier, environment.banks[0:1][0], amount, environment.banks[0:1][0].interest_rate_deposits, 0, -1) # environment.banks[0:1][0] is only for testing purposes DO NOT USE IN PRODUCTION # what it does is is takes the first bank in environment, but if there are no # banks (which happens in testing) it doesn't break down household.accounts.append(transaction) # money - cash and equivalents amount = 50.0 transaction = Transaction() transaction.this_transaction("cash", "", household.identifier, household.identifier, amount, 0, 0, -1) household.accounts.append(transaction) # manhours - labour to sell amount = 250.0 transaction = Transaction() transaction.this_transaction("manhours", "", household.identifier, household.identifier, amount, 0, 0, -1) household.accounts.append(transaction)
def initialize_standard_firm(self, firm, environment): from src.transaction import Transaction firm.identifier = "standard_firm_id" # identifier firm.parameters["productivity"] = 1.20 # how much goods do we get from 1 unit of labour # loans - we get the first bank from the list of banks # if there are no banks it will be a blank which is fine for testing amount = 250.0 transaction = Transaction() transaction.this_transaction("loans", "", environment.banks[0:1][0], firm.identifier, amount, environment.banks[0:1][0].interest_rate_loans, 0, -1) # environment.banks[0:1][0] is only for testing purposes DO NOT USE IN PRODUCTION # what it does is is takes the first bank in environment, but if there are no # banks (which happens in testing) it doesn't break down firm.accounts.append(transaction) # money - cash and equivalents amount = 200.0 transaction = Transaction() transaction.this_transaction("cash", "", firm.identifier, firm.identifier, amount, 0, 0, -1) firm.accounts.append(transaction) # goods - unique production amount = 50.0 transaction = Transaction() transaction.this_transaction("goods", "", firm.identifier, firm.identifier, amount, 0, 0, -1) firm.accounts.append(transaction)
def init_repo(self): self.__repo.add_item(Transaction(2, 1909, 'in', 'freelancing')) self.__repo.add_item(Transaction(24, 178, 'out', 'food')) self.__repo.add_item(Transaction(1, 1200, 'out', 'rent')) self.__repo.add_item(Transaction(14, 54, 'out', 'food')) self.__repo.add_item(Transaction(14, 55023, 'in', 'salary')) self.__repo.add_item(Transaction(16, 550, 'in', 'freelancing')) self.__repo.add_item(Transaction(23, 1200, 'out', 'project')) self.__repo.add_item(Transaction(2, 230, 'out', 'food')) self.__repo.add_item(Transaction(16, 176, 'out', 'food')) self.__repo.add_item(Transaction(5, 188, 'out', 'food'))
def test_format_cardholder_name(self): cardholder_name = 'LEONARDODAVINCI' cardholder_name_w_spaces = 'LEONARDO DA VINCI' result = '304c454f4e4152444f444156494e4349' self.assertEqual(Transaction.format_cardholder_name(cardholder_name), result) self.assertEqual( Transaction.format_cardholder_name(cardholder_name_w_spaces), result)
def transfer_excess_reserves(self): availableVolume = self.Q plannedVolume = self.gamma * (1.0 - self.lamb) * self.V transactionVolume = round(min(plannedVolume, availableVolume), 4) self.Q = round(self.Q - transactionVolume, 4) if self.Q < 0.0: logging.info("ERROR: Q negative in transfer_excess_reserves") transaction = Transaction() transaction.this_transaction("E", self.identifier, -3, transactionVolume, self.rb, 0, -1) self.accounts.append(transaction) del transaction
def get_data_pairs(self, file_path): transaction = Transaction( self.data_reader.get_stock_info(stock_file_path=file_path)) turnover = transaction.get_return(self.time_frame_size_y) avg_delta_in_bid_and_ask = transaction.get_average_delta_bid_ask_size( 'all', self.time_frame_size_x) volume_init_by_buy_and_sell = transaction.get_volume_init_by_buy_and_sell( 'all', self.time_frame_size_x) result = [turnover ] + avg_delta_in_bid_and_ask + volume_init_by_buy_and_sell return pd.concat(result, axis=1).iloc[:min(map(len, result))]
def transfer_excess_reserves(self): from src.transaction import Transaction availableVolume = self.parameters["Q"] plannedVolume = self.parameters["gamma"]*(1.0-self.parameters["lamb"])*self.parameters["V"] transactionVolume = round(min(plannedVolume, availableVolume), 4) self.parameters["Q"] = round(self.parameters["Q"] - transactionVolume, 4) if (self.parameters["Q"] < 0.0): logging.info("ERROR: Q negative in transfer_excess_reserves") transaction = Transaction() transaction.this_transaction("E", self.identifier, -3, transactionVolume, self.parameters["rb"], 0, -1) self.accounts.append(transaction) del transaction
def test_get_max(): repo = Repository() repo.add_item(Transaction(2, 1909, 'in', 'freelancing')) repo.add_item(Transaction(2, 178, 'out', 'food')) repo.add_item(Transaction(1, 1200, 'out', 'rent')) repo.add_item(Transaction(14, 54, 'out', 'food')) repo.add_item(Transaction(14, 55023, 'in', 'salary')) repo.add_item(Transaction(14, 550, 'in', 'freelancing')) repo.add_item(Transaction(23, 1200, 'out', 'project')) repo.add_item(Transaction(2, 230, 'out', 'food')) repo.add_item(Transaction(16, 176, 'out', 'food')) repo.add_item(Transaction(5, 188, 'out', 'food')) assert get_max(repo, 'in', 14).get_money_amount() == 55023 assert get_max(repo, 'out', 2).get_money_amount() == 230
def main(): path = os.getcwd() print(path) try: print('trying to read') os.chdir(path + '/blk') with open('blkchain.pkl', 'rb') as fp: chain = pickle.load(fp) fp.close() except: check = int(input("Are you miner or wallet :")) if check: print('Miner/Wallet started') else: print('Creating genesis') number_of_candidates = int(input("Enter number of candidates :")) trs = [] for i in range(number_of_candidates): Name = input("Enter name :") age = input("Enter Age :") #usr = User(name=Name, age=age, publickey=sha256(Name.encode() + str(age).encode()).hexdigest(), privatekey=sha256(Name.encode() + str(age).encode()).hexdigest(), candidate=True) ts = Transaction(sha256(Name.encode() + str(age).encode()).hexdigest(), sha256(Name.encode() + str(age).encode()).hexdigest(), 0, name=Name) trs.append(ts) chain = Blockchain() chain.initialize_genesis(trs) os.mkdir('blk') os.chdir(path + '/blk') with open('blkchain.pkl', 'wb') as fp: pickle.dump(chain, fp) fp.close()
def sell(self, symbol, amount): stock_price = self.get_stock_current_price(symbol) if stock_price * self.holdings.get(symbol, 0) < amount: raise Exception('Not enough holding of {}!'.format(symbol)) self.holdings[symbol] = self.holdings[symbol] - amount / stock_price self.cash += amount self.transactions.append(Transaction("SELL", symbol, amount))
def replace_transaction(self, args): """ Replace the amount of a transaction with a given value. replace <day> <type> <description> with <value> """ if len(args) != 5: raise clisys.InvalidArgumentCount if args[3] != 'with': raise clisys.InvalidArgument(args[3]) try: day = int(args[0]) except ValueError: raise clisys.InvalidArgument(args[0]) type = args[1] description = args[2] try: value = int(args[4]) except ValueError: raise clisys.InvalidArgument(args[4]) self.__repo.replace_item( lambda t: t.get_day() == day and t.get_type() == type and t. get_description() == description, Transaction(day, value, type, description))
class TestTransactionType(TestTransaction): def test_is_debit_true(self): self.assertTrue(self.transaction.is_debit()) def test_is_debite_false(self): self.transaction = Transaction(-200, self.date_object) self.assertFalse(self.transaction.is_debit())
def test_get_balance(): repo = Repository() repo.add_item(Transaction(2, 1909, 'in', 'freelancing')) repo.add_item(Transaction(24, 178, 'out', 'food')) repo.add_item(Transaction(1, 1200, 'out', 'rent')) repo.add_item(Transaction(14, 54, 'out', 'food')) repo.add_item(Transaction(14, 55023, 'in', 'salary')) repo.add_item(Transaction(16, 550, 'in', 'freelancing')) repo.add_item(Transaction(23, 1200, 'out', 'project')) repo.add_item(Transaction(2, 230, 'out', 'food')) repo.add_item(Transaction(16, 176, 'out', 'food')) repo.add_item(Transaction(5, 188, 'out', 'food')) assert get_balance(repo, 2) == 479 assert get_balance(repo, 5) == 291
def test_proto(): reward_key = Key.generate_private_key() proto1 = Protocol([], GENESIS_BLOCK, 1337) proto2 = Protocol([("127.0.0.1", 1337)], GENESIS_BLOCK, 1338) miner1 = Miner(proto1, reward_key) miner2 = Miner(proto2, reward_key) miner2.start_mining() miner1.start_mining() try: sleep(5) target_key = Key.generate_private_key() chain = miner1.chainbuilder.primary_block_chain reward_trans = chain.blocks[20].transactions[0] trans_in = TransactionInput(reward_trans.get_hash(), 0) trans_targ = TransactionTarget(target_key, reward_trans.targets[0].amount) trans = Transaction([trans_in], [trans_targ], datetime.utcnow()) trans.sign([reward_key]) assert trans.verify(chain, set()), "transaction should be valid" proto1.received('transaction', trans.to_json_compatible(), None) print("============Transaction=============") sleep(10) chain_len1 = len(miner1.chainbuilder.primary_block_chain.blocks) chain_len2 = len(miner2.chainbuilder.primary_block_chain.blocks) print("Length of chain of miner 1: {}".format(chain_len1)) print("Length of chain of miner 2: {}".format(chain_len2)) finally: miner1.shutdown() miner2.shutdown() assert max(chain_len1, chain_len2) * 90 // 100 < min( chain_len1, chain_len2), "chain lengths are VERY different" chain1 = miner1.chainbuilder.primary_block_chain hashes1 = [b.hash for b in chain1.blocks[:chain_len1 * 90 // 100]] hashes2 = [ b.hash for b in miner2.chainbuilder.primary_block_chain.blocks[:chain_len1 * 90 // 100] ] assert hashes1 == hashes2, "first 90% of chains should be identical" assert not trans.verify( miner1.chainbuilder.primary_block_chain, set()), "inserted transaction should be spent and therefore invalid" assert TransactionInput( trans.get_hash(), 0) in chain1.unspent_coins, "someone spent our coins?"
def buy(self, symbol, amount): stock_price = self.get_stock_current_price(symbol) if self.cash < amount: raise Exception('Not enough money!') self.holdings[symbol] = self.holdings.get(symbol, 0) + amount / stock_price self.cash -= amount self.transactions.append(Transaction("BUY", symbol, amount))
def execute_transaction(self, username: str, shopping_cart, payment_method: str, payment_details, address: DeliveryAddress, account_number: int): if not self.check_availability_of_products(shopping_cart): return MessageResponse( False, 1, "Not all the products are available in this amount") TransactionManagement.transaction_counter += 1 transaction = Transaction(self.transaction_counter, shopping_cart['products'], username, payment_method, payment_details, address, account_number, shopping_cart['store_number']) cart = ShoppingCart(shopping_cart["store_number"], shopping_cart['products']) # until here yet transaction.total_price = cart.calculate_price() if self.payment_system.charge(username, payment_details[0], payment_details[1], payment_details[2], payment_details[3], payment_details[4]) == 'declined': return MessageResponse(False, 1, "payment problem") transaction.update_payment_status() if self.delivery_system.delivery(transaction.products, address) == 'undelivered': return MessageResponse(False, 1, 'delivery problem, payment were cancelled') transaction.update_delivery_status() self.transactions.append(transaction) self.remove_products_from_store(shopping_cart) return MessageResponse( transaction, 1, 'succeed transaction' + str(transaction.transaction_id))
def test_transaction_constructor(): test_transaction = Transaction("fromAddress", "toAddress", 5, 123, "id", "signature") assert (test_transaction.to_address == "toAddress" and test_transaction.from_address == "fromAddress" and test_transaction.amount == 5 and test_transaction.timestamp == 123 and test_transaction.id == "id" and test_transaction.signature == "signature")
def test_format_text_data(self): sales_count = 13 sales_sum = 12341.55 refund_count = 3 refund_sum = 3253.12 result = '013000001234155003000000325312' self.assertEqual( Transaction.format_text_data(sales_count, sales_sum, refund_count, refund_sum), result)
def _read_transactions_from_csv_file(self, path_to_csv_file): transactions = [] with open(path_to_csv_file) as fin: csv_reader = csv.DictReader(fin) for row in csv_reader: transactions.append( Transaction(date=row[self.KEY_TRANSACTION_DATE], description=row[self.KEY_DESCRIPTION], amount=float(row[self.KEY_AMOUNT]))) return transactions
def do_update(self, environment, time): # As a first step, we accrue all interest over the transactions # Thus, important to notice to keep 0 as interest by default # Unless transaction should carry interest self.accrue_interests(environment, time) # The households sell labour to firms self.sell_labour(environment, time) # The firms sell goods to households self.consume_rationed(environment, time) # We net deposits and loans self.net_loans_deposits(environment, time) # We remove the perishable transactions self.remove_perishable(environment, time) # And add capital to balance the books self.capitalise(environment, time) # Investing of the banks self.invest(environment, time) # Purging accounts at every step just in case transaction = Transaction() transaction.purge_accounts(environment)
def do_update(self, environment, time): # As a first step, we accrue all interest over the transactions # Thus, important to notice to keep 0 as interest by default # Unless transaction should carry interest # DON'T DO INTERESTS SO FAR, DO ONCE THE REST WORKS self.accrue_interests(environment, time) # Then agents get their labour endowment for the step (e.g. work hours to spend) # For now we don't need to keep track of labour left as there is no queue # self.endow_labour(environment, time) # The households sell labour to firms self.sell_labour(environment, time) # The firms sell goods to households self.consume_rationed(environment, time) # We net deposits and loans self.net_loans_deposits(environment, time) # We remove goods and labour (perishable) and are left with capital self.net_labour_goods(environment, time) # Purging accounts at every step just in case transaction = Transaction() transaction.purge_accounts(environment)
def network__get_transactions(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.network import Network text = "This test checks network.get_transactions \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 network__get_transactions in run: %s', environment_directory + identifier + ".xml") # Construct household filename environment = Environment(environment_directory, identifier) # # TESTING # print(nx.info(environment.network.get_transactions())) print("Adding a transaction") transaction = Transaction() transaction.add_transaction("type", "asset", "bank_test_config_id", "bank_test_config_id_two", 1, 2, 3, 4, environment) print(nx.info(environment.network.get_transactions()))
def get_last_transaction(self): if not len(self): raise EmptyTransactionLogException() def parse_timestamp(x): return datetime.datetime.strptime(x, '%Y-%m-%d %H:%M:%S.%f') sorted_transaction_log = sorted( self, key=lambda x: parse_timestamp(x['timestamp']), reverse=True) last_transaction = sorted_transaction_log[0]['transactionJson'] return Transaction(last_transaction)
def test_pad(self): strings = [ '1', '12', '123', '1234', '12345', '123456', '1234567', '12345678', '123456789', '1234567890', '12345678901', '123456789012' ] desired_lengths = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] results = [ ['1'], ['01', '12'], ['001', '012', '123'], ['0001', '0012', '0123', '1234'], [ # 5 '00001', '00012', '00123', '01234', '12345' ], [ # 6 '000001', '000012', '000123', '001234', '012345', '123456' ], [ # 7 '0000001', '0000012', '0000123', '0001234', '0012345', '0123456', '1234567' ], [ # 8 '00000001', '00000012', '00000123', '00001234', '00012345', '00123456', '01234567', '12345678' ], [ # 9 '000000001', '000000012', '000000123', '000001234', '000012345', '000123456', '001234567', '012345678', '123456789' ], [ # 10 '0000000001', '0000000012', '0000000123', '0000001234', '0000012345', '0000123456', '0001234567', '0012345678', '0123456789', '1234567890' ], [ # 11 '00000000001', '00000000012', '00000000123', '00000001234', '00000012345', '00000123456', '00001234567', '00012345678', '00123456789', '01234567890', '12345678901' ], [ # 12 '000000000001', '000000000012', '000000000123', '000000001234', '000000012345', '000000123456', '000001234567', '000012345678', '000123456789', '001234567890', '012345678901', '123456789012' ], ] for i, length in enumerate(desired_lengths): for j in range(length): string = strings[j] result = Transaction.pad(string, length) self.assertEqual(result, results[i][j])
def find_incoming_utxos(block_hash, transactions, isGenesis=False): """ Iterates through all the outputs and looks for any directed to user's wallet. If found, save to the utxo pool :return: """ myAddress = SHA256.new(get_public_key("string").encode()).hexdigest() conf = Configuration() for tnx_id, tnx_info in transactions.items(): # deserialize transaction tnx_payload = tnx_info tnx_payload["transaction_id"] = tnx_id tnx = Transaction(payload=tnx_payload) for index in range(len(tnx.outputs)): if tnx.outputs[index]["address"] == myAddress and not isGenesis: save_utxo(tnx.get_transaction_id(), index, block_hash, tnx.outputs[index]["amount"]) conf.add_balance(tnx.outputs[index]["amount"]) elif tnx.outputs[index]["address"] == myAddress and isGenesis: save_utxo(tnx.get_transaction_id(), -1, block_hash, tnx.outputs[index]["amount"]) conf.add_balance(tnx.outputs[index]["amount"])
class TransactionTest(unittest.TestCase): def setUp(self): transaction_json = {'contractID': 'contract_id', 'outputs': ['1']} self.transaction = Transaction(transaction_json) def test_extract_chainspace_objects(self): chainspace_objects = self.transaction.extract_chainspace_objects() self.assertEquals(len(chainspace_objects), 1) self.assertIsInstance(chainspace_objects[0], ChainspaceObject) self.assertEquals(chainspace_objects[0], '1') self.assertIsNotNone(chainspace_objects[0].object_id)
def new_transaction(self, type_, asset, from_, to, amount, interest, maturity, time_of_default): from src.transaction import Transaction transaction = Transaction() transaction.this_transaction(type_, asset, from_, to, amount, interest, maturity, time_of_default) transaction.add_transaction(self)
def endow_labour(self, environment, time): # We make sure household get their labour endowment per step for household in environment.households: # First, we set a control variable that makes sure we have exactly # one transaction with "manhours", though this should in general # be the case, this should always run through the second if check = 0 for tranx in household.accounts: if tranx.type_ == "manhours": check = check + 1 # We check how many transactions with manhours are there for the household # If there are no "manhours" transactions then we create one and add it to the household's accounts if check == 0: # The amount is equal to the parameter read from the config of the household amount = household.labour # We create the transaction transaction = Transaction() # We add the appropriate values to the transaction transaction.this_transaction("manhours", "", household.identifier, household.identifier, amount, 0, 0, -1) # It's important to add the transaction using the method # from Transaction class and not manually transaction.add_transaction(environment) else: # If we have more than one "mahhours" transaction we raise an error raise LookupError( "Labour transactions for a household haven't been properly removed." ) logging.info(" labour endowed on step: %s", time)
def create_transaction(recipient, amount): """ creates a new transaction and add it to verified_transactions.json :param recipient: public address of the recipient :param amount: the amount of abc to be sent :return: None """ # TODO: Send a success message to client conf = Configuration() try: tx = Transaction() tx.add_output(recipient, amount) tx.unlock_inputs(get_private_key(), get_public_key("string")) save_verified_transaction(tx.get_transaction_id(), tx.get_data()) conf.subtract_balance(tx.sum_of_outputs()) except ValueError as e: # Will raise if insufficient utxos are found raise ValueError("INSUFFICIENT FUNDS")
def produce(self, environment, time): # We take all the labour and turn it into goods for firm in environment.firms: # We do it for every firm production_factors = 0 # Here, we count how much labour the firm has for tranx in firm.accounts: if tranx.type_ == "manhours": # We move the labour to production as a production factor # First, we move it to production factors used below # Then we will remove it from the books production_factors = production_factors + tranx.amount # Amount produced is labour * productivity in this simple model amount = production_factors * firm.productivity # Create a transaction transaction = Transaction() # Add the appropriate values to the transaction transaction.this_transaction("goods", "", firm.identifier, firm.identifier, amount, 0, 0, -1) # And add the transaction to the books (do it through function/not manually) transaction.add_transaction(environment) # Finally, we remove all the labour that was used in production # from the books of the firms self.remove_labour_firms(environment, time) logging.info(" goods produced on step: %s", time)
def transfer_investments(self, environment): from random import Random from src.transaction import Transaction random = Random() currentVolume = 0.0 optimalVolume = 0.0 plannedVolume = 0.0 availableVolume = 0.0 transactionVolume = 0.0 transaction = Transaction() # calculate the optimal investment volume and compare to current volume self.calculate_optimal_investment_volume(environment) optimalVolume = round(float(self.parameters["gamma"]*self.parameters["lamb"]*self.parameters["V"]), 4) currentVolume = round(self.get_account("I"), 4) # add new transactions of average size plannedVolume = currentVolume + optimalVolume availableVolume = self.parameters["lamb"]*self.parameters["Q"] # we can only spend a fraction of the available Q transactionVolume = min(plannedVolume, availableVolume) while ((transactionVolume >= self.parameters["averageTransactionSize"]) and (self.parameters["averageTransactionSize"] > 0.0)): transactionVolume = round(transactionVolume - self.parameters["averageTransactionSize"], 5) # reduce remaining transactionVolume self.parameters["Q"] = self.parameters["Q"] - self.parameters["averageTransactionSize"] # reduce available liquidity # account for different maturities of investments maturity = int(round(random.random()*environment.static_parameters["firmLoanMaturity"], 1)) # this is done very roughly and implies loans are up to 3 years # and determine whether the loan will default if (random.random() >= environment.static_parameters["successProbabilityFirms"]): # the loan defaults: determine timeOfDefault timeOfDefault = int(round(random.random()*maturity)) else: timeOfDefault = -1 # and add transaction to the stack transaction = Transaction() transaction.this_transaction("I", self.identifier, -2, self.parameters["averageTransactionSize"], self.parameters["rhoReal"], maturity, timeOfDefault) self.accounts.append(transaction) del transaction transactionVolume = round(transactionVolume, 5) # finally, add the remaining transaction to the stack if the transactionVolume was positive in the first place if (transactionVolume > 0.0): self.parameters["Q"] = round(self.parameters["Q"] - transactionVolume, 4) # account for different maturities of investments maturity = int(round(random.random()*environment.static_parameters["firmLoanMaturity"], 1)) # this is done very roughly and implies loans are up to 3 years # and determine whether the loan will default if (random.random() >= environment.static_parameters["successProbabilityFirms"]): # the loan defaults: determine timeOfDefault timeOfDefault = int(round(random.random()*maturity)) else: timeOfDefault = -1 transaction = Transaction() transaction.this_transaction("I", self.identifier, -2, transactionVolume, self.parameters["rhoReal"], maturity, timeOfDefault) self.accounts.append(transaction) del transaction
def initialize_transactions(self, environment): from src.transaction import Transaction from random import Random random = Random() value = 0.0 # first, calculate number of transactions for investments numTransactions = int(round(self.parameters["assetNumber"] / self.parameters["numBanks"])) if (numTransactions == 0): # we want some error message if there are two few assets in the economy logging.info(" ERROR: number of assets in the economy has to be at least half the number of banks") # now, calculate value of each transaction and note that the *product* of all individual transactions # is supposed to have precision 4. Hence, each individual transaction should have precision 5 value = round(float(self.parameters["gamma"]*self.parameters["lamb"]*self.parameters["V"] / numTransactions), 5) # finally, put them on the transaction stack for i in range(numTransactions): transaction = Transaction() # # account for different maturities # maturity = int(round(random.random()*environment.static_parameters["firmLoanMaturity"], 1)) # maturity is between 0 and firmLoanMaturity # and determine whether the loan will default if (random.random() >= environment.static_parameters["successProbabilityFirms"]): # TODO this is superfluous, we could get rid of this doubling # the loan defaults: determine timeOfDefault timeOfDefault = int(round(random.random()*maturity)) else: timeOfDefault = -1 # then, generate the transaction, append it to the accounts, and delete it from memory transaction.this_transaction("I", self.identifier, -2, value, self.parameters["rhoReal"], maturity, timeOfDefault) self.accounts.append(transaction) del transaction # store averageTransactionSize self.parameters["averageTransactionSize"] = value # then, calculate excess reserves value = round(float(self.parameters["gamma"]*(1.0-self.parameters["lamb"])*self.parameters["V"]), 4) transaction = Transaction() transaction.this_transaction("E", self.identifier, -3, value, self.parameters["rb"], 0, -1) self.accounts.append(transaction) del transaction # on the liabilities side, banks are endowed with banking capital # (see comments in get_initial_banking_capital() for further details) value = round(float(self.get_initial_banking_capital(environment.static_parameters["requiredCapitalRatio"])), 4) transaction = Transaction() transaction.this_transaction("BC", self.identifier, self.identifier, value, 0.0, 0, -1) self.accounts.append(transaction) del transaction # now, transfer deposits from households to banks value = round(float(self.parameters["gamma"]*self.parameters["V"]-self.get_account("BC")), 4) transaction = Transaction() transaction.this_transaction("D", -1, self.identifier, value, self.parameters["rd"], 0, -1) self.accounts.append(transaction) del transaction # as well as required deposits to the central bank value = round(float(self.parameters["r"]*self.get_account("D")), 4) transaction = Transaction() transaction.this_transaction("rD", self.identifier, -3, value, self.parameters["rb"], 0, -1) self.accounts.append(transaction) del transaction # finally, determine central bank loans value = round(float(self.get_account("I") + self.get_account("E") + self.get_account("rD") - self.get_account("D") - self.get_account("BC")), 4) transaction = Transaction() transaction.this_transaction("LC", self.identifier, -3, value, self.parameters["rb"], 0, -1) self.accounts.append(transaction) del transaction
def add_transaction(self, type, fromID, toID, value, interest, maturity, timeOfDefault): from src.transaction import Transaction transaction = Transaction() transaction.this_transaction(type, fromID, toID, value, interest, maturity, timeOfDefault) self.accounts.append(transaction) del transaction
def consume(self, environment, time): # We want the consumption to be done in random pairs # So we need to randomise the households and the firms # We start with the households and create a list of order integers # the size of the number of households itrange_hh = list(range(0, int(environment.num_households))) # Then we shuffle the list random.shuffle(itrange_hh) # And use it to loop over the households randomly for h in itrange_hh: # Since we don't loop directly over households # We assign the correct household in this run over the loop household = environment.households[h] wealth = 0.0 # total of deposits and cash available for the household cash = 0.0 # total of cash available for the household # We calculate the above two values for tranx in household.accounts: # We add all deposits and all cash to the wealth if tranx.type_ == "deposits" or tranx.type_ == "cash": wealth = wealth + tranx.amount # But only cash to the available cash if tranx.type_ == "cash": cash = cash + tranx.amount # We consume the percentage of wealth determined by # the propensity to save, cash first to_consume = wealth * (1 - household.propensity_to_save) # Now we randomise firms and create a list of order integers # the size of the number of households itrange = list(range(0, int(environment.num_firms))) # Then we shuffle the list random.shuffle(itrange) # For each firm in random order for i in itrange: # For every transaction on that firm's books # We make a proxy for the cash that firm should obtain # for whatever good they've sold to the household firm = environment.firms[i] firm_cash = 0.0 for tranx in firm.accounts: # If the transaction contains goods if tranx.type_ == "goods": # We go through the household's accounts for tranx_h in household.accounts: # And look for cash if tranx_h.type_ == "cash": # We can buy for minimum of the cash and goods # in question amount_proxy = min(tranx.amount, tranx_h.amount, to_consume) # And remove the appropriate amount of cash tranx_h.amount = tranx_h.amount - amount_proxy # Lower the amount household wants to consume to_consume = to_consume - amount_proxy # And remove the goods from firm's account tranx.amount = tranx.amount - amount_proxy # And we note the cash to be added to the firm firm_cash = firm_cash + amount_proxy for tranx_h in household.accounts: # And look for deposits if tranx_h.type_ == "deposits": # We can buy for minimum of the deposits and goods # in question amount_proxy = min(tranx.amount, tranx_h.amount, to_consume) # And remove the appropriate amount of deposits tranx_h.amount = tranx_h.amount - amount_proxy # Lower the amount household wants to consume to_consume = to_consume - amount_proxy # And remove the goods from firm's account tranx.amount = tranx.amount - amount_proxy # And we note the cash to be added to the firm firm_cash = firm_cash + amount_proxy # Add cash for sold items to the firm cash_number = 0 # We calculate how many cash account the firm has for tranx in firm.accounts: if tranx.type_ == "cash": cash_number = cash_number + 1 # If the firm doesn't have any cash accounts we create a new one if cash_number == 0: # Create a transaction transaction = Transaction() # Add the appropriate values to the transaction transaction.this_transaction("cash", "", firm.identifier, firm.identifier, firm_cash, 0, 0, -1) # And add the transaction to the books (do it through function/not manually) transaction.add_transaction(environment) # If the firm has previous cash transactions we add the cash from sales proportionately else: # We find all cash transactions for tranx in firm.accounts: if tranx.type_ == "cash": # And add the sales proceeds proportionately tranx.amount = tranx.amount + (firm_cash / cash_number) # The sales above may have rendered some transactions worthless # So we need to purge all accounts to make sure everything is in order transaction = Transaction() transaction.purge_accounts(environment) # Finally, we remove the goods which weren't sold from firms' accounts # As they are perishable self.remove_goods_firms(environment, time) logging.info(" goods consumed on step: %s", time)
def sell_labour(self, environment, time): # We want the sell to be done in random pairs # So we need to randomise the households and the firms # We start with the firms and create a list of order integers # the size of the number of firms itrange = list(range(0, int(environment.num_firms))) # Then we shuffle the list random.shuffle(itrange) # And use it to loop over the firms randomly for i in itrange: # Since we don't loop directly over firms # We assign the correct firm in this run over the loop firm = environment.firms[i] # We calculate the amount of cash firm has to buy labour to_buy = 0.0 # We go through the firm's transactions for tranx in firm.accounts: # If we find cash transaction if tranx.type_ == "cash": # We add the cash to the amount of labour the firm # wants to buy, we assume 1 unit of labour costs 1 unit of cash to_buy = to_buy + tranx.amount # Now we randomise households and create a list of order integers # the size of the number of households itrange_hh = list(range(0, int(environment.num_households))) # Then we shuffle the list random.shuffle(itrange_hh) # For each household in random order for h in itrange_hh: # Since we don't loop directly over households # We assign the correct household in this run over the loop household = environment.households[h] household_cash = 0.0 # We go through household's accounts for tranx in household.accounts: # And find transactions with labour if tranx.type_ == "manhours": # We will sell them for cash # So we look through firm's accounts for tranx_f in firm.accounts: # And find cash transactions if tranx_f.type_ == "cash": # We can only buy the lowest amount from the cash the firm # has, the labour the household has, and however many units # they want to buy amount_proxy = min(tranx.amount, tranx_f.amount, to_buy) # Then we remove the appropriate amount of cash from the firm tranx_f.amount = tranx_f.amount - amount_proxy # Lower the amount firm wants to buy to_buy = to_buy - amount_proxy # And remove the goods from household's account tranx.amount = tranx.amount - amount_proxy # And we note the cash to be added to the household household_cash = household_cash + amount_proxy # Create a transaction transaction = Transaction() # Add the appropriate values to the transaction transaction.this_transaction("manhours", "", firm.identifier, firm.identifier, amount_proxy, 0, 0, -1) # And add the transaction to the books (do it through function/not manually) transaction.add_transaction(environment) # Add cash for sold items to the household cash_number = 0 # We calculate how many cash account the household has for tranx in household.accounts: if tranx.type_ == "cash": cash_number = cash_number + 1 # If there are no cash transactions on the household's books # We create a new one and put the proceeds there if cash_number == 0: # Create a transaction transaction = Transaction() # Add the appropriate values to the transaction transaction.this_transaction("cash", "", household.identifier, household.identifier, household_cash, 0, 0, -1) # And add the transaction to the books (do it through function/not manually) transaction.add_transaction(environment) # If the household has previous cash transactions we add the cash from sales proportionately else: # We find all cash transactions for tranx in household.accounts: if tranx.type_ == "cash": # And add the sales proceeds proportionately tranx.amount = tranx.amount + (household_cash / cash_number) # The sales above may have rendered some transactions worthless # So we need to purge all accounts to make sure everything is in order transaction = Transaction() transaction.purge_accounts(environment) logging.info(" labour sold to firms on step: %s", time)
def initialize_standard_bank(self): from src.transaction import Transaction self.parameters["identifier"] = "0" # identifier self.parameters["V"] = 250.0 # planned optimal portfolio volume of the bank self.parameters["lamb"] = 0.5 # planned optimal portfolio structure of the bank self.parameters["rb"] = 0.02 # refinancing costs of the bank -> tbd in environment self.parameters["rd"] = 0.01 # interest rate on deposits self.parameters["r"] = 0.05 # required reserve rate -> tbd in environment self.parameters["pReal"] = 0.9 # probability of credit success self.parameters["rhoReal"] = 0.03 # interest charged on risky investment self.parameters["xi"] = 1.0 # scaling parameter in CRRA self.parameters["theta"] = 1.5 # risk aversion parameter of bank self.parameters["gamma"] = 0.8 # fraction of interbank loans in overall volume self.parameters["Q"] = 0.0 # the current liquidity position of the bank # set 0.0 as standard, but after calculate_liquidity_demand we will return the indicated values self.parameters["Ip"] = 0.0 # the planned optimal investment; (gamma * lamb * V) = (0.8 * 0.5 * 250.0) = 100.0 self.parameters["Ep"] = 0.0 # the planned excess reserves; (gamma * (1-lamb) * V) = (0.8 * 0.5 * 250.0) = 100.0 self.parameters["Lp"] = 0.0 # the planned interbank loans; Q - ((Ip-I) + (Ep-E)) = 90.0 self.parameters["assetNumber"] = 6.0 # number of assets available to bank self.parameters["numBanks"] = 3.0 # number of banks in the economy # first, calculate number of transactions for investments numTransactions = int(round(self.parameters["assetNumber"] / self.parameters["numBanks"])) # # ASSETS # # finally, put them on the transaction stack for i in range(numTransactions): transaction = Transaction() value = 100.0 maturity = 50.0 timeOfDefault = -1 transaction.this_transaction("I", self.identifier, -2, value, self.parameters["rhoReal"], maturity, timeOfDefault) self.accounts.append(transaction) del transaction # excess reserves value = 90.0 transaction = Transaction() transaction.this_transaction("E", self.identifier, -3, value, self.parameters["rb"], 0, -1) self.accounts.append(transaction) del transaction # required deposits to the central bank value = 10.0 transaction = Transaction() transaction.this_transaction("rD", self.identifier, -3, value, self.parameters["rb"], 0, -1) self.accounts.append(transaction) del transaction # # LIABILITIES # # banking capital value = 40.0 transaction = Transaction() transaction.this_transaction("BC", self.identifier, self.identifier, value, 0.0, 0, -1) self.accounts.append(transaction) del transaction # deposits value = 250.0 transaction = Transaction() transaction.this_transaction("D", -1, self.identifier, value, self.parameters["rd"], 0, -1) self.accounts.append(transaction) del transaction # central bank loans value = 10.0 transaction = Transaction() transaction.this_transaction("LC", -3, self.identifier, value, self.parameters["rb"], 0, -1) self.accounts.append(transaction) del transaction
def add_transaction(self, type_, asset, from_id, to_id, amount, interest, maturity, time_of_default, environment): from src.transaction import Transaction transaction = Transaction() transaction.this_transaction(type_, asset, from_id, to_id, amount, interest, maturity, time_of_default) transaction.add_transaction(environment)
def initialize_standard_bank(self, bank, environment): from src.transaction import Transaction bank.identifier = "standard_bank_id" # deposits - we get the first household from the list of households # if there are no households it will be a blank which is fine for testing amount = 250.0 transaction = Transaction() transaction.this_transaction( "deposits", "", environment.households[0].identifier, bank.identifier, amount, bank.interest_rate_deposits, 0, -1, ) # environment.households[0] is only for testing purposes DO NOT USE IN PRODUCTION transaction.add_transaction(environment) # money - cash and equivalents amount = 100.0 transaction = Transaction() transaction.this_transaction("cash", "", bank.identifier, bank.identifier, amount, 0, 0, -1) transaction.add_transaction(environment) # loans - we get the first firm from the list of firms # if there are no firms it will be a blank which is fine for testing amount = 150.0 transaction = Transaction() transaction.this_transaction( "loans", "", bank.identifier, environment.firms[0].identifier, amount, bank.interest_rate_loans, 0, -1 ) # environment.firms[0] is only for testing purposes DO NOT USE IN PRODUCTION transaction.add_transaction(environment)