def test_account_net_worth_2(account_checking, account_sp500, asset_krw, asset_sp500): AssetValue.create( evaluated_at=parse_date('2016-02-25'), asset=asset_sp500, base_asset=asset_krw, granularity=Granularity.day, close=921.77) AssetValue.create( evaluated_at=parse_date('2016-02-24'), asset=asset_sp500, base_asset=asset_krw, granularity=Granularity.day, close=932.00) AssetValue.create( evaluated_at=parse_date('2016-02-23'), asset=asset_sp500, base_asset=asset_krw, granularity=Granularity.day, close=921.06) AssetValue.create( evaluated_at=parse_date('2016-02-22'), asset=asset_sp500, base_asset=asset_krw, granularity=Granularity.day, close=921.76) with Transaction.create() as t: Record.create( created_at=parse_date('2016-02-25'), transaction=t, account=account_sp500, asset=asset_sp500, quantity=1000) Record.create( created_at=parse_date('2016-02-25'), transaction=t, account=account_checking, asset=asset_krw, quantity=-1000 * 921.77) assert 921770 == account_sp500.net_worth( evaluated_at=parse_date('2016-02-25'), base_asset=asset_krw) assert 921770 == account_sp500.net_worth( evaluated_at=parse_date('2016-03-01'), approximation=True, base_asset=asset_krw)
def import_sp500_records(): """Import S&P500 fund sample data. Expects a tab seprated value document. """ app = create_app(__name__) app.app_context().push() account_checking = Account.get(id=1001) account_sp500 = Account.get(id=7001) asset_krw = Asset.query.filter_by(name='KRW').first() asset_sp500 = Asset.query.filter_by(name='KB S&P500').first() # Expected number of columns expected_col_count = 6 with open('sample-data/sp500.csv') as fin: # Skip the first row (headers) headers = next(fin) col_count = len(headers.split()) if col_count != expected_col_count: raise Exception( 'Expected number of columns = {}, ' 'actual number of columns = {}'.format( expected_col_count, col_count)) for line in fin: cols = line.split('\t') if len(cols) != expected_col_count: continue date = parse_date(cols[0], '%Y.%m.%d') _type = cols[1] quantity_krw, quantity_sp500 = \ [int(extract_numbers(v)) for v in cols[3:5]] log.info(', '.join([c.strip() for c in cols])) if not (_type == '일반입금' or _type == '일반신규'): log.info('Record type \'{}\' will be ignored', _type) continue with Transaction.create() as t: # NOTE: The actual deposit date and the buying date generally # differ by a few days. Need to figure out how to parse this # properly from the raw data. try: Record.create( created_at=date, account=account_checking, asset=asset_krw, quantity=-quantity_krw, transaction=t) except IntegrityError: log.warn('Identical record exists') db.session.rollback() try: Record.create( created_at=date, account=account_sp500, asset=asset_sp500, quantity=quantity_sp500, transaction=t) except IntegrityError: log.warn('Identical record exists') db.session.rollback()
def test_records(account_checking, asset_krw): with Transaction.create() as t: record = Record.create(created_at=parse_date('2016-03-14'), transaction=t, account=account_checking, asset=asset_krw, quantity=1000) # Make sure the record type has been set implictly assert RecordType.deposit == record.type with Transaction.create() as t: record = Record.create(created_at=parse_date('2016-03-14'), transaction=t, account=account_checking, asset=asset_krw, quantity=-2000) # Make sure the record type has been set implictly assert RecordType.withdraw == record.type with Transaction.create() as t: record = Record.create(created_at=parse_date('2016-03-14'), transaction=t, account=account_checking, asset=asset_krw, quantity=3000, type=RecordType.balance_adjustment) # Make sure the record type has been set explicitly assert RecordType.balance_adjustment == record.type
def insert_stock_transfer_record(data: dict, bank_account: object): """Inserts a transfer record between a bank account and a stock account. """ from finance.models import Asset, Record # FIXME: Not a good idea to use a hard coded value asset_krw = Asset.query.filter(Asset.name == 'KRW').first() if data['name'] == '증거금이체': # Transfer from a bank account to a stock account return Record.create( created_at=data['date'], quantity=-data['subtotal'], asset=asset_krw, account=bank_account) elif data['name'] == '매매대금정산': # Transfer from a stock account to a bank account return Record.create( created_at=data['date'], quantity=data['subtotal'], asset=asset_krw, account=bank_account) else: raise ValueError( "Unrecognized transfer type '{}'".format(data['name']))
def test_records(account_checking, asset_krw): with Transaction.create() as t: record = Record.create( created_at=parse_date('2016-03-14'), transaction=t, account=account_checking, asset=asset_krw, quantity=1000) # Make sure the record type has been set implictly assert RecordType.deposit == record.type with Transaction.create() as t: record = Record.create( created_at=parse_date('2016-03-14'), transaction=t, account=account_checking, asset=asset_krw, quantity=-2000) # Make sure the record type has been set implictly assert RecordType.withdraw == record.type with Transaction.create() as t: record = Record.create( created_at=parse_date('2016-03-14'), transaction=t, account=account_checking, asset=asset_krw, quantity=3000, type=RecordType.balance_adjustment) # Make sure the record type has been set explicitly assert RecordType.balance_adjustment == record.type
def test_portfolio(account_hf, asset_hf1, account_checking, asset_krw): portfolio = Portfolio() portfolio.base_asset = asset_krw portfolio.add_accounts(account_hf, account_checking) with Transaction.create() as t: Record.create( created_at=parse_date('2015-12-04'), transaction=t, account=account_checking, asset=asset_krw, quantity=500000) Record.create( created_at=parse_date('2015-12-04'), transaction=t, account=account_checking, asset=asset_krw, quantity=-500000) Record.create( created_at=parse_date('2015-12-04'), transaction=t, account=account_hf, asset=asset_hf1, quantity=1) # The net asset value shall not be available at this point with pytest.raises(AssetValueUnavailableException): net_worth = portfolio.net_worth(evaluated_at=parse_date('2015-12-04'), granularity=Granularity.day) # Initial asset value AssetValue.create( evaluated_at=parse_date('2015-12-04'), asset=asset_hf1, base_asset=asset_krw, granularity=Granularity.day, close=500000) net_worth = portfolio.net_worth(evaluated_at=parse_date('2015-12-04'), granularity=Granularity.day) assert 500000 == net_worth # 1st payment interest, tax, returned = 3923, 740, 30930 with Transaction.create() as t: Record.create( created_at=parse_date('2016-01-08'), transaction=t, account=account_checking, asset=asset_krw, quantity=returned) # Remaining principle value after the 1st payment AssetValue.create( evaluated_at=parse_date('2016-01-08'), asset=asset_hf1, base_asset=asset_krw, granularity=Granularity.day, close=472253) net_worth = portfolio.net_worth(evaluated_at=parse_date('2016-01-08'), granularity=Granularity.day) assert 500000 + (interest - tax) == net_worth # 2nd payment with Transaction.create() as t: Record.create( created_at=parse_date('2016-02-05'), transaction=t, account=account_checking, asset=asset_krw, quantity=25016) # Remaining principle value after the 2nd payment AssetValue.create( evaluated_at=parse_date('2016-02-05'), asset=asset_hf1, base_asset=asset_krw, granularity=Granularity.day, close=450195) db.session.delete(portfolio) db.session.commit()
def test_account_net_worth_4(account_checking, asset_usd): """Ensures Account.net_worth() works with explicit `created_at`.""" Record.create( account=account_checking, asset=asset_usd, quantity=1000, type=RecordType.deposit, created_at=parse_datetime('2018-08-30 23:00:00')) net_worth = account_checking.net_worth( base_asset=asset_usd, evaluated_at=parse_date('2018-08-30')) assert net_worth == 1000
def test_account_net_worth_3(account_checking, asset_usd): """Ensures Account.net_worth() works with implicit `created_at`, which is the current datetime. """ Record.create( account=account_checking, asset=asset_usd, quantity=1000, type=RecordType.deposit) net_worth = account_checking.net_worth( base_asset=asset_usd) assert net_worth == 1000
def test_account_net_worth_4(account_checking, asset_usd): """Ensures Account.net_worth() works with explicit `created_at`.""" Record.create(account=account_checking, asset=asset_usd, quantity=1000, type=RecordType.deposit, created_at=parse_datetime('2018-08-30 23:00:00')) net_worth = account_checking.net_worth( base_asset=asset_usd, evaluated_at=parse_date('2018-08-30')) assert net_worth == 1000
def test_account_net_worth_3(account_checking, asset_usd): """Ensures Account.net_worth() works with implicit `created_at`, which is the current datetime. """ Record.create(account=account_checking, asset=asset_usd, quantity=1000, type=RecordType.deposit) net_worth = account_checking.net_worth(base_asset=asset_usd) assert net_worth == 1000
def test_balance(account_checking, asset_krw, asset_usd): assert account_checking.balance() == {} Record.create(created_at=parse_date('2016-05-01'), account=account_checking, asset=asset_krw, quantity=1000) assert account_checking.balance(parse_date('2016-05-19')) \ == {asset_krw: 1000} Record.create(created_at=parse_date('2016-05-02'), account=account_checking, asset=asset_krw, quantity=-500) assert account_checking.balance(parse_date('2016-05-19')) \ == {asset_krw: 500} Record.create(created_at=parse_date('2016-05-03'), account=account_checking, asset=asset_usd, quantity=25) assert account_checking.balance(parse_date('2016-05-19')) \ == {asset_krw: 500, asset_usd: 25} Record.create(created_at=parse_date('2016-05-04'), account=account_checking, asset=asset_usd, quantity=40, type=RecordType.balance_adjustment) assert account_checking.balance(parse_date('2016-05-19')) \ == {asset_krw: 500, asset_usd: 40}
def test_balance(account_checking, asset_krw, asset_usd): assert account_checking.balance() == {} Record.create( created_at=parse_date('2016-05-01'), account=account_checking, asset=asset_krw, quantity=1000) assert account_checking.balance(parse_date('2016-05-19')) \ == {asset_krw: 1000} Record.create( created_at=parse_date('2016-05-02'), account=account_checking, asset=asset_krw, quantity=-500) assert account_checking.balance(parse_date('2016-05-19')) \ == {asset_krw: 500} Record.create( created_at=parse_date('2016-05-03'), account=account_checking, asset=asset_usd, quantity=25) assert account_checking.balance(parse_date('2016-05-19')) \ == {asset_krw: 500, asset_usd: 25} Record.create( created_at=parse_date('2016-05-04'), account=account_checking, asset=asset_usd, quantity=40, type=RecordType.balance_adjustment) assert account_checking.balance(parse_date('2016-05-19')) \ == {asset_krw: 500, asset_usd: 40}
def insert_stock_trading_record(data: dict, stock_account: object): """Inserts a stock trading (i.e., buying or selling stocks) records.""" from finance.models import Asset, Record if data['category1'].startswith('장내'): code_suffix = '.KS' elif data['category1'].startswith('코스닥'): code_suffix = '.KQ' else: code_suffix = '' raise ValueError( "code_suffix could not be determined with the category '{}'" ''.format(data['category1'])) code = data['code'] + code_suffix asset = Asset.get_by_symbol(code) if asset is None: raise ValueError( "Asset object could not be retrived with code '{}'".format(code)) return Record.create( created_at=data['date'], quantity=data['quantity'], asset=asset, account=stock_account, )
def insert_stock_trading_record(data: dict, stock_account: object): """Inserts a stock trading (i.e., buying or selling stocks) records.""" from finance.models import get_asset_by_stock_code, Record if data['category1'].startswith('장내'): code_suffix = '.KS' elif data['category1'].startswith('코스닥'): code_suffix = '.KQ' else: code_suffix = '' raise ValueError( "code_suffix could not be determined with the category '{}'" ''.format(data['category1'])) code = data['code'] + code_suffix asset = get_asset_by_stock_code(code) if asset is None: raise ValueError( "Asset object could not be retrived with code '{}'".format(code)) return Record.create( created_at=data['date'], quantity=data['quantity'], asset=asset, account=stock_account, )
def test_record_created_at(account_checking, asset_krw): record = Record.create( account=account_checking, asset=asset_krw, quantity=1000, type=RecordType.deposit) # `created_at` must be set as the time at which the record created assert record.created_at
def test_record_created_at(account_checking, asset_krw): record = Record.create(account=account_checking, asset=asset_krw, quantity=1000, type=RecordType.deposit) # `created_at` must be set as the time at which the record created assert record.created_at
def make_single_record_transaction(created_at, account, asset, quantity): """Creates a single record transaction (e.g., a deposit)""" return Record.create( account_id=account.id, asset_id=asset.id, created_at=created_at, quantity=quantity, )
def test_account_net_worth_2(account_checking, account_sp500, asset_krw, asset_sp500): AssetValue.create(evaluated_at=parse_date('2016-02-25'), asset=asset_sp500, base_asset=asset_krw, granularity=Granularity.day, close=921.77) AssetValue.create(evaluated_at=parse_date('2016-02-24'), asset=asset_sp500, base_asset=asset_krw, granularity=Granularity.day, close=932.00) AssetValue.create(evaluated_at=parse_date('2016-02-23'), asset=asset_sp500, base_asset=asset_krw, granularity=Granularity.day, close=921.06) AssetValue.create(evaluated_at=parse_date('2016-02-22'), asset=asset_sp500, base_asset=asset_krw, granularity=Granularity.day, close=921.76) with Transaction.create() as t: Record.create(created_at=parse_date('2016-02-25'), transaction=t, account=account_sp500, asset=asset_sp500, quantity=1000) Record.create(created_at=parse_date('2016-02-25'), transaction=t, account=account_checking, asset=asset_krw, quantity=-1000 * 921.77) assert 921770 == account_sp500.net_worth( evaluated_at=parse_date('2016-02-25'), base_asset=asset_krw) assert 921770 == account_sp500.net_worth( evaluated_at=parse_date('2016-03-01'), approximation=True, base_asset=asset_krw)
def make_double_record_transaction( created_at, account, asset_from, quantity_from, asset_to, quantity_to ): """Creates a double record transaction (e.g., a buy order of stocks)""" with Transaction.create() as t: record1 = Record.create( transaction=t, account_id=account.id, asset_id=asset_from.id, created_at=created_at, quantity=quantity_from, ) record2 = Record.create( transaction=t, account_id=account.id, asset_id=asset_to.id, created_at=created_at, quantity=quantity_to, ) return (record1, record2)
def import_8percent_data(parsed_data, account_checking, account_8p, asset_krw): from finance.models import Asset, AssetValue, Record, Transaction assert account_checking assert account_8p assert asset_krw asset_8p = Asset.create(name=parsed_data['name']) remaining_value = parsed_data['amount'] started_at = parsed_data['started_at'] with Transaction.create() as t: Record.create( created_at=started_at, transaction=t, account=account_checking, asset=asset_krw, quantity=-remaining_value) Record.create( created_at=started_at, transaction=t, account=account_8p, asset=asset_8p, quantity=1) AssetValue.create( evaluated_at=started_at, asset=asset_8p, target_asset=asset_krw, granularity='1day', close=remaining_value) for record in parsed_data['records']: date, principle, interest, tax, fees = record returned = principle + interest - (tax + fees) remaining_value -= principle with Transaction.create() as t: Record.create( created_at=date, transaction=t, account=account_checking, asset=asset_krw, quantity=returned) AssetValue.create( evaluated_at=date, asset=asset_8p, target_asset=asset_krw, granularity='1day', close=remaining_value)
def insert_record(row, account, asset, transaction): """ (type, created_at, cateory, quantity) """ from finance.models import Record type, created_at, category, quantity = [x.strip() for x in row.split(',')] type = parse_nullable_str(type) created_at = make_date(created_at) category = parse_nullable_str(category) quantity = parse_decimal(quantity) return Record.create( account=account, asset=asset, transaction=transaction, type=type, created_at=created_at, category=category, quantity=quantity)
def insert_stock_transfer_record(data: dict, bank_account: object): """Inserts a transfer record between a bank account and a stock account. """ from finance.models import Asset, Record # FIXME: Not a good idea to use a hard coded value asset_krw = Asset.query.filter(Asset.name == 'KRW').first() if data['name'] == '증거금이체': # Transfer from a bank account to a stock account return Record.create(created_at=data['date'], quantity=-data['subtotal'], asset=asset_krw, account=bank_account) elif data['name'] == '매매대금정산': # Transfer from a stock account to a bank account return Record.create(created_at=data['date'], quantity=data['subtotal'], asset=asset_krw, account=bank_account) else: raise ValueError("Unrecognized transfer type '{}'".format( data['name']))
def test_account_net_worth_1(account_checking, asset_krw): assert 0 == account_checking.net_worth( evaluated_at=parse_date('2016-01-01'), base_asset=asset_krw) assert 0 == account_checking.net_worth( evaluated_at=parse_date('2016-01-02'), base_asset=asset_krw) assert 0 == account_checking.net_worth( evaluated_at=parse_date('2016-01-03'), base_asset=asset_krw) assert 0 == account_checking.net_worth( evaluated_at=parse_date('2016-01-04'), base_asset=asset_krw) with Transaction.create() as t: Record.create(created_at=parse_date('2016-01-01'), transaction=t, account=account_checking, asset=asset_krw, quantity=1000) assert 1000 == account_checking.net_worth( evaluated_at=parse_date('2016-01-01'), base_asset=asset_krw) assert 1000 == account_checking.net_worth( evaluated_at=parse_date('2016-01-02'), base_asset=asset_krw) assert 1000 == account_checking.net_worth( evaluated_at=parse_date('2016-01-03'), base_asset=asset_krw) assert 1000 == account_checking.net_worth( evaluated_at=parse_date('2016-01-04'), base_asset=asset_krw) with Transaction.create() as t: Record.create(created_at=parse_date('2016-01-02'), transaction=t, account=account_checking, asset=asset_krw, quantity=2000) assert 1000 == account_checking.net_worth( evaluated_at=parse_date('2016-01-01'), base_asset=asset_krw) assert 3000 == account_checking.net_worth( evaluated_at=parse_date('2016-01-02'), base_asset=asset_krw) assert 3000 == account_checking.net_worth( evaluated_at=parse_date('2016-01-03'), base_asset=asset_krw) assert 3000 == account_checking.net_worth( evaluated_at=parse_date('2016-01-04'), base_asset=asset_krw) with Transaction.create() as t: Record.create(created_at=parse_date('2016-01-03'), transaction=t, account=account_checking, asset=asset_krw, quantity=-1500) assert 1000 == account_checking.net_worth( evaluated_at=parse_date('2016-01-01'), base_asset=asset_krw) assert 3000 == account_checking.net_worth( evaluated_at=parse_date('2016-01-02'), base_asset=asset_krw) assert 1500 == account_checking.net_worth( evaluated_at=parse_date('2016-01-03'), base_asset=asset_krw) assert 1500 == account_checking.net_worth( evaluated_at=parse_date('2016-01-04'), base_asset=asset_krw)
def insert_record(row, account, asset, transaction): """ (type, created_at, cateory, quantity) """ from finance.models import Record type, created_at, category, quantity = [x.strip() for x in row.split(',')] type = parse_nullable_str(type) created_at = parse_date(created_at) category = parse_nullable_str(category) quantity = parse_decimal(quantity) return Record.create(account=account, asset=asset, transaction=transaction, type=type, created_at=created_at, category=category, quantity=quantity)
def test_net_worth_without_asset_value(request, account_sp500, asset_krw, asset_sp500): asset_values = AssetValue.query.filter_by(asset=asset_sp500) for asset_value in asset_values: db.session.delete(asset_value) db.session.commit() record = Record.create( created_at=parse_date('2016-05-27'), account=account_sp500, asset=asset_sp500, quantity=1000) with pytest.raises(AssetValueUnavailableException): account_sp500.net_worth(parse_date('2016-05-28'), base_asset=asset_krw) def teardown(): db.session.delete(record) db.session.commit() request.addfinalizer(teardown)
def test_account_net_worth_1(account_checking, asset_krw): assert 0 == account_checking.net_worth( evaluated_at=parse_date('2016-01-01'), base_asset=asset_krw) assert 0 == account_checking.net_worth( evaluated_at=parse_date('2016-01-02'), base_asset=asset_krw) assert 0 == account_checking.net_worth( evaluated_at=parse_date('2016-01-03'), base_asset=asset_krw) assert 0 == account_checking.net_worth( evaluated_at=parse_date('2016-01-04'), base_asset=asset_krw) with Transaction.create() as t: Record.create( created_at=parse_date('2016-01-01'), transaction=t, account=account_checking, asset=asset_krw, quantity=1000) assert 1000 == account_checking.net_worth( evaluated_at=parse_date('2016-01-01'), base_asset=asset_krw) assert 1000 == account_checking.net_worth( evaluated_at=parse_date('2016-01-02'), base_asset=asset_krw) assert 1000 == account_checking.net_worth( evaluated_at=parse_date('2016-01-03'), base_asset=asset_krw) assert 1000 == account_checking.net_worth( evaluated_at=parse_date('2016-01-04'), base_asset=asset_krw) with Transaction.create() as t: Record.create( created_at=parse_date('2016-01-02'), transaction=t, account=account_checking, asset=asset_krw, quantity=2000) assert 1000 == account_checking.net_worth( evaluated_at=parse_date('2016-01-01'), base_asset=asset_krw) assert 3000 == account_checking.net_worth( evaluated_at=parse_date('2016-01-02'), base_asset=asset_krw) assert 3000 == account_checking.net_worth( evaluated_at=parse_date('2016-01-03'), base_asset=asset_krw) assert 3000 == account_checking.net_worth( evaluated_at=parse_date('2016-01-04'), base_asset=asset_krw) with Transaction.create() as t: Record.create( created_at=parse_date('2016-01-03'), transaction=t, account=account_checking, asset=asset_krw, quantity=-1500) assert 1000 == account_checking.net_worth( evaluated_at=parse_date('2016-01-01'), base_asset=asset_krw) assert 3000 == account_checking.net_worth( evaluated_at=parse_date('2016-01-02'), base_asset=asset_krw) assert 1500 == account_checking.net_worth( evaluated_at=parse_date('2016-01-03'), base_asset=asset_krw) assert 1500 == account_checking.net_worth( evaluated_at=parse_date('2016-01-04'), base_asset=asset_krw)
def test_net_worth_without_asset_value(request, account_sp500, asset_krw, asset_sp500): asset_values = AssetValue.query.filter_by(asset=asset_sp500) for asset_value in asset_values: db.session.delete(asset_value) db.session.commit() record = Record.create(created_at=parse_date('2016-05-27'), account=account_sp500, asset=asset_sp500, quantity=1000) with pytest.raises(AssetValueUnavailableException): account_sp500.net_worth(parse_date('2016-05-28'), base_asset=asset_krw) def teardown(): db.session.delete(record) db.session.commit() request.addfinalizer(teardown)
def import_8percent_data(parsed_data, account_checking, account_8p, asset_krw): from finance.models import Asset, AssetValue, Record, Transaction assert account_checking assert account_8p assert asset_krw asset_8p = Asset.create(name=parsed_data['name']) remaining_value = parsed_data['amount'] started_at = parsed_data['started_at'] with Transaction.create() as t: Record.create(created_at=started_at, transaction=t, account=account_checking, asset=asset_krw, quantity=-remaining_value) Record.create(created_at=started_at, transaction=t, account=account_8p, asset=asset_8p, quantity=1) AssetValue.create(evaluated_at=started_at, asset=asset_8p, target_asset=asset_krw, granularity='1day', close=remaining_value) for record in parsed_data['records']: date, principle, interest, tax, fees = record returned = principle + interest - (tax + fees) remaining_value -= principle with Transaction.create() as t: Record.create(created_at=date, transaction=t, account=account_checking, asset=asset_krw, quantity=returned) AssetValue.create(evaluated_at=date, asset=asset_8p, target_asset=asset_krw, granularity='1day', close=remaining_value)
def import_sp500_records(): """Import S&P500 fund sample data. Expects a tab seprated value document. """ app = create_app(__name__) app.app_context().push() account_checking = Account.get(id=1001) account_sp500 = Account.get(id=7001) asset_krw = Asset.query.filter_by(name='KRW').first() asset_sp500 = Asset.query.filter_by(name='KB S&P500').first() # Expected number of columns expected_col_count = 6 with open('sample-data/sp500.csv') as fin: # Skip the first row (headers) headers = next(fin) col_count = len(headers.split()) if col_count != expected_col_count: raise Exception('Expected number of columns = {}, ' 'actual number of columns = {}'.format( expected_col_count, col_count)) for line in fin: cols = line.split('\t') if len(cols) != expected_col_count: continue date = parse_date(cols[0], '%Y.%m.%d') _type = cols[1] quantity_krw, quantity_sp500 = \ [int(extract_numbers(v)) for v in cols[3:5]] log.info(', '.join([c.strip() for c in cols])) if not (_type == '일반입금' or _type == '일반신규'): log.info('Record type \'{}\' will be ignored', _type) continue with Transaction.create() as t: # NOTE: The actual deposit date and the buying date generally # differ by a few days. Need to figure out how to parse this # properly from the raw data. try: Record.create(created_at=date, account=account_checking, asset=asset_krw, quantity=-quantity_krw, transaction=t) except IntegrityError: log.warn('Identical record exists') db.session.rollback() try: Record.create(created_at=date, account=account_sp500, asset=asset_sp500, quantity=quantity_sp500, transaction=t) except IntegrityError: log.warn('Identical record exists') db.session.rollback()
def test_portfolio_balance(account_checking, account_savings, account_sp500, asset_krw, asset_sp500): portfolio = Portfolio() portfolio.base_asset = asset_krw portfolio.add_accounts(account_checking, account_savings, account_sp500) assert portfolio.balance(parse_date('2016-05-20')) == {} Record.create(created_at=parse_date('2016-05-01'), account=account_checking, asset=asset_krw, quantity=1500) Record.create(created_at=parse_date('2016-05-01'), account=account_savings, asset=asset_krw, quantity=3000) Record.create(created_at=parse_date('2016-05-01'), account=account_sp500, asset=asset_sp500, quantity=120) assert portfolio.balance(parse_date('2016-05-20')) \ == {asset_krw: 4500, asset_sp500: 120} Record.create(created_at=parse_date('2016-05-02'), account=account_savings, asset=asset_krw, quantity=4000) Record.create(created_at=parse_date('2016-05-03'), account=account_savings, asset=asset_krw, quantity=5000) assert portfolio.balance(parse_date('2016-05-20')) \ == {asset_krw: 13500, asset_sp500: 120} Record.create(created_at=parse_date('2016-05-04'), account=account_savings, asset=asset_krw, quantity=10000, type=RecordType.balance_adjustment) assert portfolio.balance(parse_date('2016-05-20')) \ == {asset_krw: 11500, asset_sp500: 120} db.session.delete(portfolio) db.session.commit()
def test_portfolio(account_hf, asset_hf1, account_checking, asset_krw): portfolio = Portfolio() portfolio.base_asset = asset_krw portfolio.add_accounts(account_hf, account_checking) with Transaction.create() as t: Record.create(created_at=parse_date('2015-12-04'), transaction=t, account=account_checking, asset=asset_krw, quantity=500000) Record.create(created_at=parse_date('2015-12-04'), transaction=t, account=account_checking, asset=asset_krw, quantity=-500000) Record.create(created_at=parse_date('2015-12-04'), transaction=t, account=account_hf, asset=asset_hf1, quantity=1) # The net asset value shall not be available at this point with pytest.raises(AssetValueUnavailableException): net_worth = portfolio.net_worth(evaluated_at=parse_date('2015-12-04'), granularity=Granularity.day) # Initial asset value AssetValue.create(evaluated_at=parse_date('2015-12-04'), asset=asset_hf1, base_asset=asset_krw, granularity=Granularity.day, close=500000) net_worth = portfolio.net_worth(evaluated_at=parse_date('2015-12-04'), granularity=Granularity.day) assert 500000 == net_worth # 1st payment interest, tax, returned = 3923, 740, 30930 with Transaction.create() as t: Record.create(created_at=parse_date('2016-01-08'), transaction=t, account=account_checking, asset=asset_krw, quantity=returned) # Remaining principle value after the 1st payment AssetValue.create(evaluated_at=parse_date('2016-01-08'), asset=asset_hf1, base_asset=asset_krw, granularity=Granularity.day, close=472253) net_worth = portfolio.net_worth(evaluated_at=parse_date('2016-01-08'), granularity=Granularity.day) assert 500000 + (interest - tax) == net_worth # 2nd payment with Transaction.create() as t: Record.create(created_at=parse_date('2016-02-05'), transaction=t, account=account_checking, asset=asset_krw, quantity=25016) # Remaining principle value after the 2nd payment AssetValue.create(evaluated_at=parse_date('2016-02-05'), asset=asset_hf1, base_asset=asset_krw, granularity=Granularity.day, close=450195) db.session.delete(portfolio) db.session.commit()
def test_portfolio_balance(account_checking, account_savings, account_sp500, asset_krw, asset_sp500): portfolio = Portfolio() portfolio.base_asset = asset_krw portfolio.add_accounts(account_checking, account_savings, account_sp500) assert portfolio.balance(parse_date('2016-05-20')) == {} Record.create( created_at=parse_date('2016-05-01'), account=account_checking, asset=asset_krw, quantity=1500) Record.create( created_at=parse_date('2016-05-01'), account=account_savings, asset=asset_krw, quantity=3000) Record.create( created_at=parse_date('2016-05-01'), account=account_sp500, asset=asset_sp500, quantity=120) assert portfolio.balance(parse_date('2016-05-20')) \ == {asset_krw: 4500, asset_sp500: 120} Record.create( created_at=parse_date('2016-05-02'), account=account_savings, asset=asset_krw, quantity=4000) Record.create( created_at=parse_date('2016-05-03'), account=account_savings, asset=asset_krw, quantity=5000) assert portfolio.balance(parse_date('2016-05-20')) \ == {asset_krw: 13500, asset_sp500: 120} Record.create( created_at=parse_date('2016-05-04'), account=account_savings, asset=asset_krw, quantity=10000, type=RecordType.balance_adjustment) assert portfolio.balance(parse_date('2016-05-20')) \ == {asset_krw: 11500, asset_sp500: 120} db.session.delete(portfolio) db.session.commit()