def test_precision(): """ Отладка проблемы с потерей точности при расчётах финансового результата. """ test_case = test_trades_precision() res: dict = prepare_trades_report(test_case, ExchangeRatesRUB()).to_dict() assert [x.amount for x in res['total_rub'].values()] == [ Decimal( '-51586.552320' ), # Расход: (80.62 * 10 * 63.9091) + (0.1 * 10 * 63.0359) = 51586.55232₽ Decimal( '52258.4492595587200' ), # Доход: (81.82 * 10 * 63.9490) - (0.101812674 * 10 * 63.4720) = 52258.4492595587200₽ ] assert [x.amount for x in res['profit_rub'].values()] == [ Decimal('0'), Decimal( '671.8969395587200' ), # Финансовый результат: 52258.4492595587200 - 51586.552320 = 671.896939559₽ ]
def test_exchange_rates_rub(trade_date: datetime, currency: Currency, expect_rate: Money): try: p = ExchangeRatesRUB(year_from=2015, cache_dir=None) except ConnectionError as ex: pytest.skip(f'connection error: {ex}') return rate = p.get_rate(currency, trade_date) assert rate == expect_rate, f'{trade_date}: {rate} != {expect_rate}'
def test_simple_fees_no_verbose(): fees = [ Fee(date=datetime.datetime(2020, 1, 30, 0, 0), amount=Money(0.01, Currency.USD), description='Other Fees'), Fee(date=datetime.datetime(2020, 1, 30, 0, 0), amount=Money(-0.01, Currency.USD), description='Other Fees'), ] cbr_client = ExchangeRatesRUB() res: dict = prepare_fees_report(fees, cbr_client, False).to_dict() assert res['rate'] == {} assert res['amount_rub'] == {}
def main(): parser = argparse.ArgumentParser() parser.add_argument('--activity-reports-dir', type=str, required=True, help='directory with InteractiveBrokers .csv activity reports') parser.add_argument('--confirmation-reports-dir', type=str, required=True, help='directory with InteractiveBrokers .csv confirmation reports') parser.add_argument('--cache-dir', type=str, default='.', help='directory for caching (CBR RUB exchange rates)') parser.add_argument('--years', type=lambda x: [int(v.strip()) for v in x.split(',')], default=[], help='comma separated years for final report, omit for all') args = parser.parse_args() if os.path.abspath(args.activity_reports_dir) == os.path.abspath(args.confirmation_reports_dir): print('--activity-reports-dir and --confirmation-reports-dir MUST be different directories') return p = InteractiveBrokersReportParser() activity_reports = csvs_in_dir(args.activity_reports_dir) confirmation_reports = csvs_in_dir(args.confirmation_reports_dir) for apath in activity_reports: print(f'[*] Activity report {apath}') for cpath in confirmation_reports: print(f'[*] Confirmation report {cpath}') print('========' * 8) print('') p.parse_csv( activity_csvs=activity_reports, trade_confirmation_csvs=confirmation_reports, ) trades = p.trades() dividends = p.dividends() if not trades: print('no trades found') return first_year = min(trades[0].datetime.year, dividends[0].date.year) if dividends else trades[0].datetime.year cbrates_df = ExchangeRatesRUB(year_from=first_year, cache_dir=args.cache_dir).dataframe() dividends_report = prepare_dividends_report(dividends, cbrates_df) if dividends else None portfolio, finished_trades = analyze_trades_fifo(trades) if finished_trades: finished_trades_df = pandas.DataFrame(finished_trades, columns=finished_trades[0]._fields) # noqa: WPS437 trades_report = prepare_trades_report(finished_trades_df, cbrates_df) else: trades_report = None show_report(trades_report, dividends_report, portfolio, args.years)
def test_exchange_rates_rub(): test_cases = [ (datetime(2015, 1, 15), Money('66.0983', Currency.RUB)), (datetime(2015, 3, 7), Money('59.9938', Currency.RUB)), (datetime(2015, 3, 8), Money('59.9938', Currency.RUB)), (datetime(2020, 3, 31), Money('77.7325', Currency.RUB)), ] try: p = ExchangeRatesRUB(year_from=2015, cache_dir=None) except ConnectionError as ex: pytest.skip(f'connection error: {ex}') return for tc in test_cases: rate = p.get_rate(tc[0]) assert rate == tc[1], f'{tc[0]}: {rate} != {tc[1]}'
def test_convert_to_rub(): client_usd = ExchangeRatesRUB() rate_date = datetime(2020, 3, 31) expected_rate = client_usd.get_rate(Currency.USD, rate_date) assert expected_rate.amount == Decimal('77.7325') test_usd = Money(10.98, Currency.USD) res = client_usd.convert_to_rub(test_usd, rate_date) assert res.amount == Decimal('853.50285') assert res.currency == Currency.RUB test_rub = Money(Decimal('858.3066'), Currency.RUB) res = client_usd.convert_to_rub(test_rub, rate_date) assert res.amount == Decimal('858.3066') assert res.currency == Currency.RUB
def test_simple_trades(): ticker = Ticker(symbol='VT', kind=TickerKind.Stock) trades = [ FinishedTrade(N=1, ticker=ticker, trade_date=datetime.datetime(2020, 1, 30, 0, 0), settle_date=datetime.datetime(2020, 2, 3, 0, 0), quantity=7, price=Money(80.62, Currency.USD), fee_per_piece=Money(-0.123375, Currency.USD)), FinishedTrade(N=1, ticker=ticker, trade_date=datetime.datetime(2020, 1, 31, 0, 0), settle_date=datetime.datetime(2020, 2, 4, 0, 0), quantity=-7, price=Money(81.82, Currency.USD), fee_per_piece=Money('-0.1309628571428571428571428571', Currency.USD)), FinishedTrade(N=2, ticker=ticker, trade_date=datetime.datetime(2020, 1, 30, 0, 0), settle_date=datetime.datetime(2020, 2, 3, 0, 0), quantity=1, price=Money(80.62, Currency.USD), fee_per_piece=Money('-0.123375', Currency.USD)), FinishedTrade(N=2, ticker=ticker, trade_date=datetime.datetime(2020, 1, 31, 0, 0), settle_date=datetime.datetime(2020, 2, 4, 0, 0), quantity=9, price=Money(80.62, Currency.USD), fee_per_piece=Money(-0.1, Currency.USD)), FinishedTrade(N=2, ticker=ticker, trade_date=datetime.datetime(2020, 2, 10, 0, 0), settle_date=datetime.datetime(2020, 2, 12, 0, 0), quantity=-10, price=Money(81.82, Currency.USD), fee_per_piece=Money('-0.101812674', Currency.USD)), ] cbr_client = ExchangeRatesRUB() res: dict = prepare_trades_report(trades, cbr_client).to_dict() assert res['settle_rate'] == { 0: Money(63.1385, Currency.RUB), 1: Money(63.9091, Currency.RUB), 2: Money(63.1385, Currency.RUB), 3: Money(63.9091, Currency.RUB), 4: Money(63.9490, Currency.RUB) } assert res['fee_rate'] == { 0: Money(62.3934, Currency.RUB), 1: Money(63.0359, Currency.RUB), 2: Money(62.3934, Currency.RUB), 3: Money(63.0359, Currency.RUB), 4: Money(63.4720, Currency.RUB) } assert res['fee'] == { 0: Money('-0.863625', Currency.USD), 1: Money('-0.9167399999999999999999999997', Currency.USD), 2: Money('-0.123375', Currency.USD), 3: Money('-0.9', Currency.USD), 4: Money('-1.018126740', Currency.USD) } assert res['total'] == { 0: Money('-565.203625', Currency.USD), 1: Money('571.82326', Currency.USD), 2: Money('-80.743375', Currency.USD), 3: Money('-726.48', Currency.USD), 4: Money('817.181873260', Currency.USD) } assert res['total_rub'] == { 0: Money('-35685.465590075', Currency.RUB), 1: Money('36545.510403034', Currency.RUB), 2: Money('-5097.923655725', Currency.RUB), 3: Money('-46427.897088', Currency.RUB), 4: Money('52258.44925955872', Currency.RUB) } assert res['profit_rub'] == { 0: Money(0, Currency.RUB), 1: Money('860.044812959', Currency.RUB), 2: Money(0, Currency.RUB), 3: Money(0, Currency.RUB), 4: Money('732.62851583372', Currency.RUB) }