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_state
numeric, the state of charge at the beginning of the settlement period for optimal arbitrage.
discharge
numeric, the proportion of the settlement period that the battery should discharge for optimal arbitrage.
charge
numeric, the proportion of the settlement period that the battery should charge for optimal arbitrage.
opt_arb
numeric, income during settlement period for optimal arbitrage.
deg_cost
numeric, 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