min_commission_backtest.Rd
Quasi event-based simulation based on target share weights, prices, commissions and interest.
The function is quite opinionated with respect to the data that it expects.
The idea is that user effort is spent in upstream data wrangling, and the
payoff is an extremely efficient backtesting routine, enabling fast
experimentation with parameters such as trade_buffer
and different
commission models.
min_commission_backtest(
prices,
unadjusted_prices,
target_weights,
interest_rates = NULL,
short_borrow_costs = NULL,
trade_buffer = 0,
initial_cash = 10000,
capitalise_profits = FALSE,
commission_fun,
...
)
Matrix of trade prices. Column 1 must be the timestamp or index.
Matrix of unadjusted prices. Column 1 must be the timestamp or index. Used to calculate commission based on actual number of shares traded.
Matrix of target weights. Column 1 must be the timestamp or index.
Matrix of daily interest rates applied to unused cash (positive interest) and borrowed cash (negative interest). If not passed, assumes constant interest rate of zero.
Named vector of annualised short borrow costs as percent. For example, c("TLT" = 0.0025) is equivalent to a short borrow cost of 0.25%pa for TLT. Defaults to zero.
Trade buffer parameter (see details)
Inital cash balance
If TRUE, utilise profits and initial cash balance in determining position sizes. If FALSE, profits accrue as a cash balance and are not reinvested.
Function for determining commissions from prices and trades
Additional arguments passed to commission_fun. For
us_tiered_commission
, this will be max_pct_per_order
(the maximum
commission as a percentage of order value), min_dollars_per_order
(the
minimum commission in dollars of a single order), dollars_per_share
(the
per-share cost in dollars - for IB fixed tier, 0.005 is reasonable).
long dataframe of results consisting of the following columns: ticker: Ticker or Cash date: In YYYY-MM-DD format close: Closing price (adjusted). shares: Number of shares held. exposure: Value of exposure to current ticker or to Cash. share_trades: Number of shares traded, including any positions that were liquidated fully or partially. trade_value: Value of shares traded, including any positions that were liquidated fully or partially. commission: Commissions paid on today's trading, including any liquidated positions. interest: Interest accrued on yesterday's cash balance and settled today. short_borrow: Borrow costs from holding yesterday's short positions through today's close. margin_call: Boolean indicating whether a margin call occurred today. reduced_target_pos: Boolean indicating whether target positions could not be executed due to insufficient margin, and were scaled back accordingly.
target_weights
, prices
, unadjusted_prices
, and interest_rates
should
be date-aligned.
The function will error if these matrixes are of different shape, or have different values in Column 1 (the date or index column). A simple approach to ensuring inputs conform with this requirement is in the vignette.
It is up to the user to lag target_weights
as necessary to ensure that
trades occur at appropriate prices. Specifically, the function assumes that
target_weights
are date-aligned with prices
such that the price at which
you assume you trade into a target weight has the same index value.
interest_rates
are the daily percentage interest rate applied to the cash
balance. It is up to the user to ensure this is in the correct format (for
instance dividing by 100*365 if your raw data is in percent per-anum), and to
apply a broker spread if necessary.
The function assumes a margin requirement of 0.25 the value of the shares held and will liquidate positions if this requirement is not met (ie will simulate a margin call).
The function doesn't consider short borrow costs yet.
if (FALSE) {
results_df <- min_commission_backtest(
prices = backtest_prices,
unadjusted_prices = unadjusted_prices,
target_weights = target_weights,
interest_rates = rates,
trade_buffer = trade_buffer,
initial_cash = initial_cash,
capitalise_profits = FALSE,
commission_fun = us_tiered_commission,
max_pct_per_order = 0.01,
min_dollars_per_order = 1,
dollars_per_share = 0.005
)
}