HFEA stands for HEDGEFUNDIE's Excellent Adventure.
Read from the start: chapter 1 The RuleLeveraged ETFs can lose a large part of their value in a short time.
The public repository on GitHub holds example packages with invented data, a short Python script and the reference output. Running the script reproduces the reference output line by line.
What the repository holds
examples/rebalancing/input.csv: the input with invented prices of both sides and the values per run.examples/rebalancing/recompute.py: the script that computes the rule day by day.examples/rebalancing/output.csv: the reference output of the script.examples/rebalancing/README.md: columns, steps and limits of the package.examples/leverage-model/input.csv: the input with invented index returns, rates and costs.examples/leverage-model/recompute.py: the script that computes the price of a leveraged product day by day.examples/leverage-model/output.csv: the reference output of the script.examples/leverage-model/README.md: columns, steps and limits of the package.
Machine-readable overview: llms.txt.
Run it locally
Python 3 is all it takes; the script uses only the standard library and needs no installation.
git clone https://github.com/Andre0512/letf-strategies.git
cd letf-strategies/examples/rebalancing
python3 recompute.py input.csv > result.csv
diff result.csv output.csv
If diff prints nothing, every line matches. The same lines work in
examples/leverage-model.
The calculation in short
The first block shows the steps of the rule, one trading day after another. The second block shows the leverage model of the second package; the page backtest does not use it.
# Prices are adjusted for splits and distributions.
on the first day: buy both sides at the target weight
for each trading day t:
value = shares stocks * price stocks + shares bonds * price bonds
stock_share = shares stocks * price stocks / value
rule termin (page backtest): the deadlines are fixed dates, the 1st of
every month whose distance from January is a multiple of
MONTHS_APART, so with 3 the 1st of January, April, July and October;
the first deadline is the first date after the first common day,
every further one the next date after the one carried out;
without a price on the date the next common trading day counts
rule termin: rebalance on the day the deadline is reached
rule termin_und_band: deadline MONTHS_APART after the last rebalancing;
rebalance only when deadline and band are reached
(example in the package, the page backtest does not use it)
on rebalancing: new shares of both sides at the target weight
# Leverage model per trading day, not used by the page backtest
days = calendar days since the previous day
gross = 1 + LEVERAGE * daily return of the index
ter = 1 - TER * days / 365
financing = 1 - (LEVERAGE - 1) * (rate + markup) * days / 360
only with LEVERAGE above 1, otherwise financing = 1
price = previous price * gross * ter * financing * further factors
The parameters
The page computes with these values unless someone changes them:
STOCK_WEIGHT = 55 # percent, US version; 50 percent in the EU version
MONTHS_APART = 3 # calendar months between two deadlines
BAND = none # the page rebalances only at the deadline
Your own version can change these values: a distance of 1, 3, 6 or 12 months and a stock weight between 30 and 80 percent.
Data rules
- Trading calendar: The page computes on common trading days of both sides; if a price is missing, the page computes nothing that day. If a deadline falls on a holiday, it moves to the next common trading day.
- Splits and adjustment: Both price series are adjusted for splits and distributions.
- Reconstruction before launch: The page computes only with real prices of the products; there is no reconstruction before launch here.
- Currency: If the currency of a product differs from that of the index, an exchange rate converts it for derived versions.
The columns
The input names per run the rule, the target weight of the stocks, the distance of the dates and the band, plus per trading day the closing prices of both sides. The output holds, among others, these columns:
| Column | Meaning |
|---|---|
run |
number of the run |
rule |
rule of the run: termin or termin_und_band |
date |
day of the row, only days on which both products have a price |
stock_shares |
unit count of the stock side after the trading of the day |
bond_shares |
unit count of the bond side after the trading of the day |
quote_before_percent |
equity share before rebalancing, in percent |
deadline |
deadline that applies after the trading of the day |
band_breached |
whether the distance to the target weight reaches the band |
value_strategy |
value of the strategy, start at 100 |
value_hold |
value without rebalancing, start at 100 |
All columns with unit and time basis are in the README of the package.
Why two packages
rebalancing shows the rule: target weight, dates and band, and which value
curve follows. leverage-model shows the daily reset of the leveraged
products. The backtest on this page uses only real closing prices, without a
reconstruction before the launch.
Why invented data
Index levels and product prices belong to index providers and data vendors; their license does not allow putting them into a public repository. That is why all numbers are invented: a formula with a few set days that show each case once, the date on a weekend and the band. They say nothing about a market or a product. Anyone with their own prices puts them into the same column layout.
What the page computes the same way
With the same closing prices of both products, adjusted for splits and distributions, on days on which both have a price, and from the first common day, the site computes the same value curve. Raw closing prices deviate from every distribution day onwards.
With quarterly rebalancing, the rule uses the first trading day of each quarter (in general: the first trading day of each scheduled month). This is a convention, not a recommendation.
Eight days from the first run of the package, with 60 % equity and dates every three months. The date 1927-01-01 falls on a Saturday, the rebalancing happens on Monday, 1927-01-03, and the next deadline is the date 1927-04-01.
All numbers are invented. Values since the start at 100.
| Date | Equity price | Bond price | Equity share before (%) | Strategy value |
|---|---|---|---|---|
| 1926-12-24 | 111.00 | 43.80 | 60.33 | 116.80 |
| 1926-12-27 | 113.00 | 44.20 | 60.54 | 118.50 |
| 1926-12-28 | 112.50 | 43.50 | 60.81 | 117.44 |
| 1926-12-29 | 111.50 | 43.10 | 60.82 | 116.38 |
| 1926-12-30 | 112.80 | 43.40 | 60.93 | 117.52 |
| 1926-12-31 | 114.00 | 43.90 | 60.91 | 118.81 |
| 1927-01-03 (rebalanced) | 115.00 | 44.50 | 60.79 | 120.08 |
| 1927-01-04 | 115.80 | 44.50 | 60.17 | 120.58 |