optimise_arbitrage maximises the income from a battery storage
solution by using a linear programming based optimisation.
optimise_arbitrage( data, price_from, exclude_from = NULL, max_charge_from = NULL, min_charge_from = NULL, capacity, c_rate, efficiency = 1, t_period = 0.5, init_charge = 0, deg_cost_per_cycle = 0 )
| data | data frame, with a row for each settlement period and columns for:
|
|---|---|
| price_from | string. Name of column in |
| exclude_from | string. Name of column in |
| max_charge_from | string. Name of column in |
| min_charge_from | string. Name of column in |
| capacity | numeric scalar, battery capacity. |
| c_rate | numeric scalar, battery charge rate. |
| efficiency | numeric scalar, charge/discharge efficiency of battery. |
| t_period | numeric scalar, duration of a settlement period. |
| init_charge | numeric scalar, initial charge on battery. |
| deg_cost_per_cycle | numeric scalar, degradation cost per complete charge/discharge cycle. |
Returns a data.frame with the same data as the data argument,
as well additional data describing the battery operation for optimal
arbitrage income. The battery operation data is:
charge_statenumeric, the state of charge at the beginning of the settlement period for optimal arbitrage.
dischargenumeric, the proportion of the settlement period that the battery should discharge for optimal arbitrage.
chargenumeric, the proportion of the settlement period that the battery should charge for optimal arbitrage.
opt_arbnumeric, income during settlement period for optimal arbitrage.
deg_costnumeric, cost of degradation during settlement period.
The arbitrage market involves charging the battery when the price of electricity is low and discharging when it is high. The amount of energy that the battery can store is limited by its capacity. The charge rate is the battery power normalised by capacity. For example, a battery with a:
Charge rate of 1 will fully charge/discharge in 1 hour.
Charge rate of 2 will fully charge/discharge in 30 minutes.
Charge rate of .5 will fully charge/discharge in 2 hours.
The efficiency of the battery will impact the profitability of charging/discharging since a certain amount of energy is lost as heat during the process with comes at a cost.
The battery degrades as it is used. In this simple model, a degradation
cost per charge/discharge cycle is assumed i.e. deg_cost_per_cycle.
For each settlement period, the cost of degradation is calculated based on
the proportion of a charge/discharge cycle occurring in the period.
Optionally, the exclude_from column of data can be used to
control whether settlement periods should be excluded from arbitrage
optimisation. If the value is TRUE, the settlement period will be
excluded from arbitrage, or FALSE otherwise.
Optionally, the max_charge_from and/or min_charge_from columns
of data can be supplied. If these arguments are not provided, then
for every settlement period, the minimum charge will be zero and the maximum
charge will be the value provided by the capacity argument. If
max_charge_from and/or min_charge_from are set, then values
specify the maximum and minimum charge, respectively, at the beginning of
the corresponding settlement period. Any value that is NA is
default to be zero for the minimum charge and the value provided by the
capacity argument for the maximum charge.
optimise_arbitrage(data = data.frame(price = c(5.0, 5.0, 10.0, 10.0)), price_from = 'price', capacity = 1, c_rate = 1)#> price charge_state discharge charge arb_income deg_cost #> 1 5 0.0 0 1 -2.5 0 #> 2 5 0.5 0 1 -2.5 0 #> 3 10 1.0 1 0 5.0 0 #> 4 10 0.5 1 0 5.0 0optimise_arbitrage(data = data.frame(price = c(5.0, 5.0, 10.0, 10.0)), price_from = 'price', capacity = 1, c_rate = 1, efficiency = .7)#> price charge_state discharge charge arb_income deg_cost #> 1 5 0 0 0 0 0 #> 2 5 0 0 0 0 0 #> 3 10 0 0 0 0 0 #> 4 10 0 0 0 0 0optimise_arbitrage(data = data.frame(price = c(5.0, 5.0, 10.0, 10.0), exclude = c(0, 1, 1, 0)), price_from = 'price', capacity = 1, c_rate = 1, efficiency = .7)#> price exclude charge_state discharge charge arb_income deg_cost #> 1 5 0 0 0 0 0 0 #> 2 5 1 0 0 0 0 0 #> 3 10 1 0 0 0 0 0 #> 4 10 0 0 0 0 0 0optimise_arbitrage(data = data.frame(price = c(5.0, 5.0, 10.0, 10.0), exclude = c(0, 1, 1, 0), max_charge = c(NA, .4, NA, NA), min_charge = c(NA, .2, NA, NA)), price_from = 'price', capacity = 1, c_rate = 1, efficiency = .7)#> price exclude max_charge min_charge charge_state discharge charge arb_income #> 1 5 0 NA NA 0 0 0 0 #> 2 5 1 0.4 0.2 0 0 0 0 #> 3 10 1 NA NA 0 0 0 0 #> 4 10 0 NA NA 0 0 0 0 #> deg_cost #> 1 0 #> 2 0 #> 3 0 #> 4 0optimise_arbitrage(data = data.frame(price = c(5.0, 5.0, 10.0, 10.0)), price_from = 'price', capacity = 1, c_rate = 1, deg_cost_per_cycle = 2.0)#> price charge_state discharge charge arb_income deg_cost #> 1 5 0.0 0 1 -2.5 -0.5 #> 2 5 0.5 0 1 -2.5 -0.5 #> 3 10 1.0 1 0 5.0 -0.5 #> 4 10 0.5 1 0 5.0 -0.5