|
2 | 2 | import unittest
|
3 | 3 |
|
4 | 4 | from fava_portfolio_returns.returns.twr import TWR
|
| 5 | +from fava_portfolio_returns.test.test import BEANGROW_CONFIG_CORP_CASH_FLOWS |
5 | 6 | from fava_portfolio_returns.test.test import BEANGROW_CONFIG_CORPAB
|
6 | 7 | from fava_portfolio_returns.test.test import approx2
|
7 | 8 | from fava_portfolio_returns.test.test import load_portfolio_file
|
@@ -54,3 +55,99 @@ def test_series_savings_plan(self):
|
54 | 55 | (datetime.date(2020, 3, 1), 1.0),
|
55 | 56 | (datetime.date(2020, 4, 1), 1.5),
|
56 | 57 | ]
|
| 58 | + |
| 59 | + def test_twr_with_changing_target_currency(self): |
| 60 | + portfolio_str = """ |
| 61 | +plugin "beancount.plugins.auto_accounts" |
| 62 | +plugin "beancount.plugins.implicit_prices" |
| 63 | +
|
| 64 | +2020-01-01 commodity CORP |
| 65 | + name: "Example Stock" |
| 66 | +
|
| 67 | +2020-01-01 commodity CURRENCY_BASE |
| 68 | +2020-01-01 commodity CURRENCY_TARGET |
| 69 | +
|
| 70 | +2020-01-01 price CURRENCY_BASE 2 CURRENCY_TARGET |
| 71 | +
|
| 72 | +2020-01-01 * "Buy 100 CORP @ 2 CURRENCY_BASE" |
| 73 | + Assets:Cash -200.00 CURRENCY_BASE |
| 74 | + Assets:CORP:SingleCashFlow 100 CORP {2 CURRENCY_BASE} |
| 75 | +
|
| 76 | +2020-01-01 * "Buy 50 CORP @ 2 CURRENCY_BASE" |
| 77 | + Assets:Cash -100.00 CURRENCY_BASE |
| 78 | + Assets:CORP:MultipleCashFlows 50 CORP {2 CURRENCY_BASE} |
| 79 | +
|
| 80 | +2020-01-04 price CURRENCY_BASE 3 CURRENCY_TARGET |
| 81 | +2020-02-01 price CORP 3 CURRENCY_BASE |
| 82 | +
|
| 83 | +2020-01-04 price CURRENCY_BASE 4 CURRENCY_TARGET |
| 84 | +
|
| 85 | +2020-03-01 * "Buy 50 CORP @ 3 CURRENCY_BASE" |
| 86 | + Assets:Cash -150.00 CURRENCY_BASE |
| 87 | + Assets:CORP:MultipleCashFlows 50 CORP {3 CURRENCY_BASE} |
| 88 | +
|
| 89 | +2020-03-03 price CURRENCY_BASE 1.5 CURRENCY_TARGET |
| 90 | +
|
| 91 | +2020-03-15 price CORP 1.5 CURRENCY_BASE |
| 92 | +
|
| 93 | +2020-03-20 price CURRENCY_BASE 2 CURRENCY_TARGET |
| 94 | + """ |
| 95 | + p_single = load_portfolio_str( |
| 96 | + portfolio_str, |
| 97 | + BEANGROW_CONFIG_CORP_CASH_FLOWS, |
| 98 | + investment_filter=["a:Assets:CORP:SingleCashFlow"], |
| 99 | + ) |
| 100 | + p_multiple = load_portfolio_str( |
| 101 | + portfolio_str, |
| 102 | + BEANGROW_CONFIG_CORP_CASH_FLOWS, |
| 103 | + investment_filter=["a:Assets:CORP:MultipleCashFlows"], |
| 104 | + ) |
| 105 | + |
| 106 | + p_single.target_currency = "CURRENCY_BASE" |
| 107 | + returns_single_base = TWR().series(p_single, datetime.date(2020, 1, 1), datetime.date(2020, 4, 1)) |
| 108 | + assert returns_single_base == [ |
| 109 | + (datetime.date(2020, 1, 1), 0.0), |
| 110 | + (datetime.date(2020, 2, 1), 0.5), |
| 111 | + (datetime.date(2020, 3, 1), 0.5), |
| 112 | + (datetime.date(2020, 3, 15), -0.25), |
| 113 | + ] |
| 114 | + |
| 115 | + p_single.target_currency = "CURRENCY_TARGET" |
| 116 | + returns_single_target = TWR().series(p_single, datetime.date(2020, 1, 1), datetime.date(2020, 4, 1)) |
| 117 | + # Note more data points because the currency conversion dates are involved as well |
| 118 | + assert returns_single_target == [ |
| 119 | + (datetime.date(2020, 1, 1), 0.0), |
| 120 | + (datetime.date(2020, 1, 4), 1.0), |
| 121 | + (datetime.date(2020, 2, 1), 2.0), |
| 122 | + (datetime.date(2020, 3, 1), 2.0), |
| 123 | + (datetime.date(2020, 3, 3), 0.125), |
| 124 | + (datetime.date(2020, 3, 15), -0.4375), |
| 125 | + # Note that as the conversion rate between currencies returns to original, the TWR becomes the same as with |
| 126 | + # CURRENCY_BASE |
| 127 | + (datetime.date(2020, 3, 20), -0.25), |
| 128 | + ] |
| 129 | + |
| 130 | + p_multiple.target_currency = "CURRENCY_BASE" |
| 131 | + returns_multiple_base = TWR().series(p_multiple, datetime.date(2020, 1, 1), datetime.date(2020, 4, 1)) |
| 132 | + # results should be identical to p_single.target_currency = "CURRENCY_BASE" case because of the TWR definition |
| 133 | + assert returns_multiple_base == [ |
| 134 | + (datetime.date(2020, 1, 1), 0.0), |
| 135 | + (datetime.date(2020, 2, 1), 0.5), |
| 136 | + (datetime.date(2020, 3, 1), 0.5), |
| 137 | + (datetime.date(2020, 3, 15), -0.25), |
| 138 | + ] |
| 139 | + |
| 140 | + p_multiple.target_currency = "CURRENCY_TARGET" |
| 141 | + returns_multiple_target = TWR().series(p_multiple, datetime.date(2020, 1, 1), datetime.date(2020, 4, 1)) |
| 142 | + # results should be identical to p_single.target_currency = "CURRENCY_TARGET" case because of the TWR definition |
| 143 | + assert returns_multiple_target == [ |
| 144 | + (datetime.date(2020, 1, 1), 0.0), |
| 145 | + (datetime.date(2020, 1, 4), 1.0), |
| 146 | + (datetime.date(2020, 2, 1), 2.0), |
| 147 | + (datetime.date(2020, 3, 1), 2.0), |
| 148 | + (datetime.date(2020, 3, 3), 0.125), |
| 149 | + (datetime.date(2020, 3, 15), -0.4375), |
| 150 | + # Note that as the conversion rate between currencies returns to original, the TWR becomes the same as with |
| 151 | + # CURRENCY_BASE |
| 152 | + (datetime.date(2020, 3, 20), -0.25), |
| 153 | + ] |
0 commit comments