Skip to content

Commit 12e1d11

Browse files
committed
add neg rev to results and rename vpi/vpf to vpl/vpi
1 parent 4c560b7 commit 12e1d11

File tree

1 file changed

+49
-44
lines changed

1 file changed

+49
-44
lines changed

src/results.jl

+49-44
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ Columns in summary output include:
4747
4. `data_type`, which is forecast or actual (data)
4848
5. `lookahead` of the simulation in minutes
4949
6. `revenue`, which is the total annual revenue of the simulated device in AUD
50-
7. `mean_rel_gap`, which is the mean relative gap across all decision times
50+
7. `negative_revenue`, which is the total annual negative revenue (i.e. losses) of the simulated device in AUD
51+
8. `mean_rel_gap`, which is the mean relative gap across all decision times
5152
5253
# Arguments
5354
@@ -64,6 +65,7 @@ function _summarise_simulations(
6465
data::Dict{String,Any}, formulation::String, energy_capacity::Float64
6566
)
6667
revenues = Float64[]
68+
negative_revenues = Float64[]
6769
bess_powers = Float64[]
6870
data_types = String[]
6971
lookaheads = Int64[]
@@ -74,10 +76,12 @@ function _summarise_simulations(
7476
lookahead_df = df[df.lookahead_minutes .== lookahead, :]
7577
lookahead_df = lookahead_df[lookahead_df.status .== "binding", :]
7678
revenue = sum(lookahead_df.revenue)
79+
negative_revenue = sum(lookahead_df[lookahead_df.revenue .< 0.0, :revenue])
7780
average_gap = mean(unique(lookahead_df, "decision_time").relative_gap)
7881
bess_power = string(match(r"([0-9\.]*)MW", split(key, "/")[2]).captures[])
7982
data_type = split(key, "/")[1]
8083
push!(revenues, float(revenue))
84+
push!(negative_revenues, negative_revenue)
8185
push!(lookaheads, lookahead)
8286
push!(average_gaps, average_gap)
8387
push!(bess_powers, parse(Float64, bess_power))
@@ -91,6 +95,7 @@ function _summarise_simulations(
9195
:data_type => data_types,
9296
:lookahead => string.(lookaheads),
9397
:revenue => revenues,
98+
:negative_revenue => negative_revenues,
9499
:mean_rel_gap => average_gaps,
95100
)
96101
summary_data = sort(summary_data, "power_capacity")
@@ -100,18 +105,18 @@ function _summarise_simulations(
100105
end
101106

102107
@doc raw"""
103-
Calculates values of perfect information and foresight as absolute values (in AUD) and as
108+
Calculates values of perfect lookahead and information as absolute values (in AUD) and as
104109
a percentage of perfect foresight revenue.
105110
106-
**Value of perfect information**: What is the additional benefit (revenue) that a participant
111+
**Value of perfect lookahead**: What is the additional benefit (revenue) that a participant
107112
could gain if they were to know exactly what the market prices will be in the *lookahead
108113
horizon*.
109-
* ``VPI = \textrm{Revenue}_\textrm{Actual Data Simulation} - \textrm{Revenue}_\textrm{Forecast Data Simulation}``
114+
* ``VPL = \textrm{Revenue}_\textrm{Actual Data Simulation} - \textrm{Revenue}_\textrm{Forecast Data Simulation}``
110115
111-
**Value of perfect foresight**: What is the additional benefit (revenue) that a participant
112-
could gain if they were to know exactly what the market prices will be *over the entire
113-
year*
114-
* ``VPF = \textrm{Revenue}_\textrm{Perfect Foresight} - \textrm{Revenue}_\textrm{Forecast Data Simulation}``
116+
**Value of perfect information**: What is the additional benefit (revenue) that a
117+
participant could gain if they were to know exactly what the market prices will be
118+
*over the entire year*
119+
* ``VPI = \textrm{Revenue}_\textrm{Perfect Foresight} - \textrm{Revenue}_\textrm{Forecast Data Simulation}``
115120
116121
N.B. This function assumes that the input `df` only has data that corresponds to a device
117122
of a particular `energy_capacity`.
@@ -122,12 +127,12 @@ of a particular `energy_capacity`.
122127
123128
# Returns
124129
125-
`DataFrame` with absolute values of perfect information and foresight, and the same values
130+
`DataFrame` with absolute values of perfect lookahead and information, and the same values
126131
as a percentage of perfect foresight revenue.
127132
"""
128-
function calculate_vpi_vpf(df::DataFrame)
129-
(v_pi_abs, v_pf_abs) = (Float64[], Float64[])
130-
(v_pi_percentage, v_pf_percentage) = (Float64[], Float64[])
133+
function calculate_vpl_vpi(df::DataFrame)
134+
(v_pl_abs, v_pi_abs) = (Float64[], Float64[])
135+
(v_pl_percentage, v_pi_percentage) = (Float64[], Float64[])
131136
(power_caps, data) = (Float64[], String[])
132137
actual_caps = unique(df[df.data_type .== "actual", :power_capacity])
133138
forecast_caps = unique(df[df.data_type .== "forecast", :power_capacity])
@@ -139,45 +144,45 @@ function calculate_vpi_vpf(df::DataFrame)
139144
cap_mask = df.power_capacity .== cap
140145
actual_mask = df.data_type .== "actual"
141146
forecast_mask = df.data_type .== "forecast"
142-
pf_rev = df[
147+
pi_rev = df[
143148
cap_mask .& forecast_mask .& (df.lookahead .== "Perfect Foresight"),
144149
:revenue,
145150
]
146-
pi_rev = df[cap_mask .& actual_mask .& lk_mask, :revenue]
151+
pl_rev = df[cap_mask .& actual_mask .& lk_mask, :revenue]
152+
v_pl = pl_rev - df[cap_mask .& forecast_mask .& lk_mask, :revenue]
147153
v_pi = pi_rev - df[cap_mask .& forecast_mask .& lk_mask, :revenue]
148-
v_pf = pf_rev - df[cap_mask .& forecast_mask .& lk_mask, :revenue]
149-
v_pi_percentage_pf = @. v_pi / pf_rev * 100
150-
v_pf_percentage_pf = @. v_pf / pf_rev * 100
154+
v_pl_percentage_pi = @. v_pl / pi_rev * 100
155+
v_pi_percentage_pi = @. v_pi / pi_rev * 100
151156
push!(power_caps, cap)
152157
push!(data, lookahead)
158+
push!(v_pl_abs, v_pl[])
153159
push!(v_pi_abs, v_pi[])
154-
push!(v_pf_abs, v_pf[])
155-
push!(v_pi_percentage, v_pi_percentage_pf[])
156-
push!(v_pf_percentage, v_pf_percentage_pf[])
160+
push!(v_pl_percentage, v_pl_percentage_pi[])
161+
push!(v_pi_percentage, v_pi_percentage_pi[])
157162
end
158163
end
159164
return DataFrame(
160165
:formulation => fill(unique(df.formulation)[], length(power_caps)),
161166
:energy_capacity => fill(unique(df.energy_capacity)[], length(power_caps)),
162167
:power_capacity => power_caps,
163168
:lookahead => data,
169+
:vpl_abs => v_pl_abs,
164170
:vpi_abs => v_pi_abs,
165-
:vpf_abs => v_pf_abs,
171+
:vpl_per => v_pl_percentage,
166172
:vpi_per => v_pi_percentage,
167-
:vpf_per => v_pf_percentage,
168173
)
169174
end
170175

171176
"""
172177
Summarises results for each simulated formulation and then calculates values of perfect
173-
information and foresight.
178+
lookahead and information.
174179
175180
For each state, this function cycles through each simulated formulation and:
176181
177182
1. Calculates summary results (i.e. annual revenue and mean relative gap)
178-
2. Calculates the value of perfect information and value of perfect foresight
183+
2. Calculates the value of perfect lookahead and value of perfect information
179184
180-
For a single state, the VPIs and VPFs across simulated formulations are then released
185+
For a single state, the VPLs and VPIs across simulated formulations are then released
181186
information a JLD2 file in the `results` folder, along with summary results for each
182187
simulated formulation.
183188
@@ -186,11 +191,11 @@ simulated formulation.
186191
187192
# Returns
188193
189-
`Dict` mapping each state to `DataFrame` with VPI and VPF for each formulation and
194+
`Dict` mapping each state to `DataFrame` with VPL and VPI for each formulation and
190195
lookahead.
191196
"""
192-
function calculate_summaries_and_vpi_vpf_across_scenarios(sim_folder::String)
193-
function _calculate_summary_vpi_vpf_for_formulation(
197+
function calculate_summaries_and_vpl_vpi_across_scenarios(sim_folder::String)
198+
function _calculate_summary_vpl_vpi_for_formulation(
194199
sim_folder::String,
195200
formulation::String,
196201
file::String,
@@ -201,31 +206,31 @@ function calculate_summaries_and_vpi_vpf_across_scenarios(sim_folder::String)
201206
data = load(joinpath(results_path, file))
202207
@info "Calculating summary information for $state $formulation"
203208
summary = _summarise_simulations(data, formulation, energy)
204-
@info "Calculating VPI and VPF for $state $formulation"
205-
return summary, calculate_vpi_vpf(summary)
209+
@info "Calculating VPL and VPI for $state $formulation"
210+
return summary, calculate_vpl_vpi(summary)
206211
end
207212

208213
save_path = joinpath("results", "data")
209214
if !isdir(save_path)
210215
mkpath(save_path)
211216
end
212217
categorisation = _categorise_simulation_results(sim_folder)
213-
states_vpi_vpf = Dict{String,DataFrame}()
218+
states_vpl_vpi = Dict{String,DataFrame}()
214219
for state in keys(categorisation)
215220
summary_data = Dict{String,DataFrame}()
216-
vpi_vpf_data = DataFrame[]
221+
vpl_vpi_data = DataFrame[]
217222
formulation_results = categorisation[state]
218223
for (formulation, results) in pairs(formulation_results)
219224
if length(results) == 1
220225
file = results[]
221226
energy = parse(
222227
Float64, match(r"[A-Z]{2,3}_([0-9\.]*)MWh_.*", file).captures[]
223228
)
224-
(summary, vpi_vpf) = _calculate_summary_vpi_vpf_for_formulation(
229+
(summary, vpl_vpi) = _calculate_summary_vpl_vpi_for_formulation(
225230
sim_folder, formulation, file, energy, state
226231
)
227-
vpi_vpf[!, :param] = fill(missing, size(vpi_vpf, 1))
228-
push!(vpi_vpf_data, vpi_vpf)
232+
vpl_vpi[!, :param] = fill(missing, size(vpl_vpi, 1))
233+
push!(vpl_vpi_data, vpl_vpi)
229234
summary_data["$(formulation)"] = summary
230235
else
231236
for file in results
@@ -234,11 +239,11 @@ function calculate_summaries_and_vpi_vpf_across_scenarios(sim_folder::String)
234239
)
235240
energy = parse(Float64, energy_param_capture.captures[1])
236241
param = string(energy_param_capture.captures[2])
237-
(summary, vpi_vpf) = _calculate_summary_vpi_vpf_for_formulation(
242+
(summary, vpl_vpi) = _calculate_summary_vpl_vpi_for_formulation(
238243
sim_folder, formulation, file, energy, state
239244
)
240-
vpi_vpf[!, :param] = fill(param, size(vpi_vpf, 1))
241-
push!(vpi_vpf_data, vpi_vpf)
245+
vpl_vpi[!, :param] = fill(param, size(vpl_vpi, 1))
246+
push!(vpl_vpi_data, vpl_vpi)
242247
summary_data["$(formulation)/$(param)"] = summary
243248
end
244249
end
@@ -249,12 +254,12 @@ function calculate_summaries_and_vpi_vpf_across_scenarios(sim_folder::String)
249254
f[key] = value
250255
end
251256
end
252-
state_vpi_vpf = vcat(vpi_vpf_data...)
253-
@info "Saving VPI and VPF data for $state"
254-
jldopen(joinpath(save_path, "vpi_vpf.jld2"), "w"; compress=true) do f
255-
f["$(state)"] = state_vpi_vpf
257+
state_vpl_vpi = vcat(vpl_vpi_data...)
258+
@info "Saving VPL and VPI data for $state"
259+
jldopen(joinpath(save_path, "vpl_vpi.jld2"), "w"; compress=true) do f
260+
f["$(state)"] = state_vpl_vpi
256261
end
257-
states_vpi_vpf[state] = state_vpi_vpf
262+
states_vpl_vpi[state] = state_vpl_vpi
258263
end
259-
return states_vpi_vpf
264+
return states_vpl_vpi
260265
end

0 commit comments

Comments
 (0)