Ejemplo n.º 1
0
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)
Ejemplo n.º 2
0
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()
Ejemplo n.º 3
0
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
Ejemplo n.º 4
0
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']))
Ejemplo n.º 5
0
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
Ejemplo n.º 6
0
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()
Ejemplo n.º 7
0
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
Ejemplo n.º 8
0
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
Ejemplo n.º 9
0
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
Ejemplo n.º 10
0
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
Ejemplo n.º 11
0
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}
Ejemplo n.º 12
0
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}
Ejemplo n.º 13
0
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,
    )
Ejemplo n.º 14
0
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,
    )
Ejemplo n.º 15
0
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
Ejemplo n.º 16
0
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
Ejemplo n.º 17
0
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,
    )
Ejemplo n.º 18
0
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)
Ejemplo n.º 19
0
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)
Ejemplo n.º 20
0
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)
Ejemplo n.º 21
0
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)
Ejemplo n.º 22
0
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']))
Ejemplo n.º 23
0
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)
Ejemplo n.º 24
0
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)
Ejemplo n.º 25
0
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)
Ejemplo n.º 26
0
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)
Ejemplo n.º 27
0
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)
Ejemplo n.º 28
0
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)
Ejemplo n.º 29
0
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()
Ejemplo n.º 30
0
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()
Ejemplo n.º 31
0
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()
Ejemplo n.º 32
0
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()