Operational Performance Standards

Performance Charges

tryCatch(
  expr = {
  ops_data_clean_temp %>%
    dplyr::filter(
      Charges > 0
      ) %>%
    tidyr::drop_na(Charges) %>%
    base::droplevels() %>%
    ggplot2::ggplot(
      ggplot2::aes(x = Period, y = Charges, fill = Group)
      ) + 
    ggplot2::geom_bar(stat = "identity") + 
    ggplot2::theme(
      text = ggplot2::element_text(size = 15)
      ) +
    ggplot2::scale_y_continuous(
      labels = scales::dollar_format(prefix = "£"),
      breaks = scales::pretty_breaks(4)
      ) +
    ggplot2::theme_bw() + 
    ggplot2::scale_fill_manual(values = c("#425563", "#05C3DE", "#005F83", "#00A499", "#FFAA4D", "#F9E547", "#8866BC")) +
    ggplot2::labs(
      title = "Performance Charges by OPS Group",
      subtitle = "Breakdown by month and standard grouping",
      caption = "Source: MOSL",
      fill = "OPS Group"
      ) +
    ggplot2::ylab("") + ggplot2::xlab("")
  }, error = function(e){}
)
OPS_grouping <- dplyr::tibble(
  "Metering" = c("OPS B1a", "OPS B3a", "OPS B3b", "OPS B5a", rep("", 4)),
  "Supply Check" = c("OPS C1a", "OPS C1b", "OPS C2a", "OPS C3a", "OPS C4a", "OPS C4b", "OPS C5a", "OPS C6a"),
  "Complaints" = c("OPS F5a", "OPS F5b", rep("", 6)),
  "Trade Effluent" = c("OPS G2a", "OPS G4a", "OPS G4b", rep("", 5)),
  "Allowances" = c("OPS H1a", rep("", 7)),
  "Disconnection/ Reconnection" = c("OPS I1a", "OPS I1b", "OPS I8a", "OPS I8b", rep("", 4))
  )

OPS_grouping %>% 
  kableExtra::kable(
    format = "latex", 
    caption = "Details of OPS groupings",
    linesep = "",
    format.args = list(big.mark = ","),
    booktabs = TRUE,
    align = "c"
    ) %>%
  kableExtra::kable_styling(
    font_size = 10,
    latex_options = c(
      "repeat_header",
      "HOLD_position",
      "striped",
      position = "center", 
      full_width = FALSE
      )
    ) %>%
  kableExtra::row_spec(0, bold = TRUE) %>%
  kableExtra::column_spec(1:ncol(OPS_grouping), width = "2.4cm")
# Creating table of charges by OPS ---------------- 

tryCatch(
  expr = {
  ops_data_clean_temp %>%
    dplyr::filter(
      Period >= data.period %m-% months(11),
      PerformanceMeasure == "Completed",
      Charges > 0
      ) %>%
    base::droplevels() %>%
    dplyr::select(Period, Standard, Charges) %>%
    dplyr::mutate(
      Period = format(Period, "%Y-%m"),
      Charges = tidyr::replace_na(Charges, 0)
      ) %>% 
    tidyr::drop_na(Charges) %>%
    base::droplevels() %>%
    tidyr::spread(Standard, Charges) %>%
    dplyr::mutate(Total = rowSums(dplyr::select(., -Period), na.rm = TRUE)) %>%
    dplyr::mutate_if(~ any(is.na(.)), ~ ifelse(is.na(.), 0, .)) %>%
    dplyr::mutate_if(is.numeric, scales::dollar_format(prefix = "£")) %>%
    tidyr::gather("Standard", "Charges", -Period) %>%
    tidyr::spread(Period, Charges) %>%
    kableExtra::kable(
      format = "latex", 
      caption = "Breakdown of Charges by Standard", 
      linesep = "",
      format.args = list(big.mark = ","),
      booktabs = TRUE,
      align = "c"
      ) %>%
    kableExtra::kable_styling(
      font_size = 10,
      latex_options = c(
        "repeat_header",
        "HOLD_position",
        "striped",
        position = "center", 
        full_width = FALSE,
        "scale_down"
        )
      ) %>%
    kableExtra::row_spec(0, bold = TRUE)
  }, error = function(e){}
)

Performance Overview

As of r format(data.period, "%B-%Y"), MOSL were monitoring r SHORT.NAME's performance against r nrow(perf_status_ops_temp) standards. The performance of Trading Parties against these standards is measured according to:

tryCatch(
  expr = {
  agg_perf <- ops_aggregate_perf %>%
    dplyr::filter(Trading.Party.ID == TRADING.PARTY) %>%
    dplyr::select(Period, PerformanceMeasure, Agg_Perf_roll) %>%
    dplyr::rename(GroupPerf = Agg_Perf_roll) %>%
    dplyr::mutate(Group = "Aggregate Performance")

  ops_data_clean_temp %>%
    dplyr::group_by(Period, PerformanceMeasure, Group) %>%
    dplyr::summarise(
      GroupPerf = stats::weighted.mean(Performance, TaskVolume)
      ) %>%
    dplyr::ungroup() %>%
    dplyr::group_by(PerformanceMeasure, Group) %>%
    dplyr::mutate(
      GroupPerf = zoo::rollapply(GroupPerf, 6, mean, align = "right", fill = NA)
      ) %>%
    dplyr::ungroup() %>%
    base::rbind(., agg_perf) %>%
    tidyr::drop_na(GroupPerf) %>%
    droplevels() %>%
    tidyr::drop_na() %>%
    ggplot2::ggplot() + 
    ggplot2::geom_line(
      ggplot2::aes(
        x = Period, 
        y = GroupPerf, 
        colour = Group,
        linetype = Group
        )
      ) +
    ggplot2::geom_point(
      ggplot2::aes(
        x = Period, 
        y = GroupPerf,
        colour = Group,
        fill = Group,
        shape = Group
        )
      ) +
    ggplot2::theme(
      legend.title = ggplot2::element_blank(),
      text = ggplot2::element_text(size = 15)
      ) +
    ggplot2::scale_y_continuous(
      labels = scales::percent_format(accuracy = 1),
      breaks = scales::pretty_breaks(4)
      ) +
    ggplot2::theme_bw() + 
    ggplot2::scale_colour_manual(
      values = c("#425563", "#05C3DE", "#005F83", "#00A499", "#FFAA4D", "#F9E547", "#8866BC")
      ) +
    ggplot2::scale_fill_manual(
      values = c("#425563", "#05C3DE", "#005F83", "#00A499", "#FFAA4D", "#F9E547", "#8866BC")
      ) +
    ggplot2::labs(
      title = paste0("Completed and Outstanding Tasks OPS Performance: ", SHORT.NAME),
      subtitle = "Breakdown by month and OPS standard grouping",
      caption = "Note: Aggregate performance corresponds to the 6-month average of aggregate OPS performance\nSource: MOSL"
      ) +
    ggplot2::ylab("") + ggplot2::xlab("") +
    ggplot2::facet_wrap(~PerformanceMeasure)
  }, error = function(e){}
)


tryCatch(
  expr = {
  ops_data_clean_temp %>% 
    dplyr::filter(
      Period >= max(ops_data_clean_temp$Period) %m-% months(11),
      PerformanceMeasure == "Completed",
      TaskVolume > 0
      ) %>%
    tidyr::drop_na(TaskVolume) %>%
    base::droplevels() %>%
    dplyr::mutate(
      Performance = scales::percent(Performance, accuracy = 1),
      Period = format(Period, "%Y-%m")
      ) %>%
    dplyr::select(
      Period, Standard, Performance
      ) %>%
    tidyr::drop_na(Performance) %>%
    base::droplevels() %>%
    tidyr::spread(key = Period, value = Performance) %>%
    kableExtra::kable(
      format = "latex", 
      caption = "OPS On Time Completed Tasks by Month",
      linesep = "",
      format.args = list(big.mark = ","),
      booktabs = TRUE,
      align = "c"
      ) %>%
    kableExtra::kable_styling(
      font_size = 10,
      latex_options = c(
        "repeat_header",
        "HOLD_position",
        "striped",
        position = "center", 
        full_width = FALSE,
        "scale_down"
        )
      ) %>%
    kableExtra::row_spec(0, bold = TRUE)
  }, error = function(e){}
)


tryCatch(
  expr = {
  ops_data_clean_temp %>% 
    dplyr::filter(
      Period >= max(ops_data_clean_temp$Period) %m-% months(11),
      PerformanceMeasure == "Outstanding",
      TaskVolume > 0
      ) %>%
    tidyr::drop_na(TaskVolume) %>%
    base::droplevels() %>%
    dplyr::mutate(
      Performance = scales::percent(Performance, accuracy = 1),
      Period = format(Period, "%Y-%m")
      ) %>%
    dplyr::select(
      Period, Standard, Performance
      ) %>%
    tidyr::drop_na(Performance) %>%
    base::droplevels() %>%
    tidyr::spread(key = Period, value = Performance) %>%
    kableExtra::kable(
      format = "latex", 
      caption = "OPS Outstanding Tasks Within Time by Month",
      linesep = "",
      format.args = list(big.mark = ","),
      booktabs = TRUE,
      align = "c"
      ) %>%
    kableExtra::kable_styling(
      font_size = 10,
      latex_options = c(
        "repeat_header",
        "HOLD_position",
        "striped",
        position = "center", 
        full_width = FALSE,
        "scale_down"
        )
      ) %>%
    kableExtra::row_spec(0, bold = TRUE)
  }, error = function(e){}
)
ops_perf_comp <- ops_aggregate_perf_temp %>%
  dplyr::filter(PerformanceMeasure == "Completed")

ops_perf_outs <- ops_aggregate_perf_temp %>%
  dplyr::filter(PerformanceMeasure == "Outstanding")

r SHORT.NAME's 6-month aggregate OPS performance for completed tasks is r scales::percent(ops_perf_comp$Agg_Perf_roll, accuracy = 1), which currently ranks as:

tryCatch(
  expr = {
  ops_aggregate_perf %>%
    dplyr::filter(
      Period == data.period,
      PerformanceMeasure == "Completed"
      ) %>%
    ggplot2::ggplot() +
    ggplot2::geom_bar(
      ggplot2::aes(
        x = reorder(ShortName, -rank_league), 
        y = Agg_Perf_roll,
        fill = dplyr::if_else(Trading.Party.ID == TRADING.PARTY, "highlight", "normal")
        ), 
      stat = "identity",
      show.legend = FALSE) +
    ggplot2::scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
    ggplot2::scale_fill_manual(values = c("#425563", "azure3")) +
    ggplot2::coord_flip() +
    ggplot2::theme_bw() + 
    ggplot2::theme(text = ggplot2::element_text(size = 15)) +
    ggplot2::labs(
      title = "Peer Comparison Tables: Operational Performance Standards (Completed)",
      subtitle = "Six-month rolling aggregate performance",
      caption = "Source: MOSL", x = "", y = ""
      ) +
    ggplot2::facet_wrap(~LeagueGroup, scales = "free", ncol = 2)
  }, 
  error = function(e){}
)

r SHORT.NAME's 6-month aggregate OPS performance for outstanding tasks is r scales::percent(ops_perf_outs$Agg_Perf_roll, accuracy = 1), which currently ranks as:

tryCatch(
  expr = {
  ops_aggregate_perf %>%
    dplyr::filter(
      Period == data.period,
      PerformanceMeasure == "Outstanding"
      ) %>%
    ggplot2::ggplot() +
    ggplot2::geom_bar(
      ggplot2::aes(
        x = reorder(ShortName, -rank_league), 
        y = Agg_Perf_roll,
        fill = dplyr::if_else(Trading.Party.ID == TRADING.PARTY, "highlight", "normal")
        ), 
      stat = "identity",
      show.legend = FALSE) +
    ggplot2::scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
    ggplot2::scale_fill_manual(values = c("#425563", "azure3")) +
    ggplot2::coord_flip() +
    ggplot2::theme_bw() + 
    ggplot2::theme(text = ggplot2::element_text(size = 15)) +
    ggplot2::labs(
      title = "Peer Comparison Tables: Operational Performance Standards (Outstanding)",
      subtitle = "Six-month rolling aggregate performance",
      caption = "Source: MOSL", x = "", y = ""
      ) +
    ggplot2::facet_wrap(~LeagueGroup, scales = "free_y", ncol = 2)
  }, 
  error = function(e){}
)

The current status of r SHORT.NAME's performance against each standard and performance measure as of r format(data.period, "%B-%Y") is summarised in the table(s) below.

``` {r message = FALSE, echo = FALSE, error = FALSE, warning = FALSE, results = "asis"}

for (MEASURE in unique(perf_status_ops_temp$PerformanceMeasure)) {

tryCatch( expr = { perf_status_ops_temp %>% dplyr::filter(PerformanceMeasure == MEASURE) %>% dplyr::select(Standard, SecondaryCategory, TaskVolume, Performance, Status, Action) %>% dplyr::mutate( Status = tidyr::replace_na(Status, ""), TaskVolume = scales::comma(TaskVolume, accuracy = 1), Performance = scales::percent(Performance, accuracy = 1) ) %>% kableExtra::kable( format = "latex", caption = paste0("Current Status of OPS (", MEASURE, ")"), linesep = "", booktabs = TRUE, col.names = c("OPS", "Category", "Task\nVolume", "Performance", "Rectification\nStatus", "MOSL\nAction") ) %>% kableExtra::kable_styling( latex_options = c( "repeat_header", "HOLD_position", "striped", position = "center", full_width = FALSE, "scale_down" ) ) %>% kableExtra::row_spec(0, bold = TRUE) %>% print()

cat("\n")

}, error = function(e){} )

}

See Appendix for an explanation of how MOSL evaluates Trading Party performance against the standards.

```r

tryCatch(
  expr = {
  perf_status_ops_temp %>%
    ggplot2::ggplot() +
    ggrepel::geom_label_repel(
      ggplot2::aes(
        x = rolling.sd,
        y = rolling.mean,
        label = Standard,
        fill= Group
        ), alpha = 0.8
      ) +
    ggplot2::scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
    ggplot2::scale_x_reverse(labels = scales::percent_format(accuracy = 1)) +
    ggplot2::theme_bw() +
    ggplot2::scale_fill_manual(
      values = c("#425563", "#05C3DE", "#005F83", "#00A499", "#FFAA4D", "#F9E547", "#8866BC")
      ) +
    ggplot2::theme(
      text = ggplot2::element_text(size = 15)
      ) +
    ggplot2::labs(
      title = paste0("OPS Performance Rating and Consistency as of ", format(as.Date(data.period), '%B %Y')),
      subtitle = "Rolling 6-month mean and standard deviation of OPS performance",
      caption = "Source: MOSL"
      ) +
    ggplot2::ylab("Performance") + ggplot2::xlab("Consistency") +
    ggplot2::facet_wrap(~ PerformanceMeasure)
  }, error = function(e){}
)

Detailed Analysis

ops_list <- unique(as.character(perf_status_ops$Standard[perf_status_ops$Trading.Party.ID == TRADING.PARTY & perf_status_ops$TaskVolume > 0]))

res <- lapply(ops_list, function (OPS_CHUNK) {

  knitr::knit_child(
    "pfm_report_ops_template.Rmd", envir = environment(), quiet = TRUE
    )
  }
  )

cat(unlist(res), sep = "\n")


Market Aggregates

metrics.list <- c("MarketMean", "MarketTaskVolume")

for (METRIC in metrics.list) {

  for (MEASURE in unique(ops_summary$PerformanceMeasure)) {

    ops_summary %>% 
      dplyr::filter(
        PerformanceMeasure == MEASURE
        ) %>%
      tidyr::drop_na() %>%
      dplyr::select(
        Period, Standard, METRIC
        ) %>% 
      dplyr::filter(
        Period >= data.period %m-% months(11)
        ) %>% 
      dplyr::mutate(Period = format(Period, "%Y-%m")) %>%
      tidyr::spread(Period, METRIC) %>%
      dplyr::mutate_if(
        is.numeric, 
        ifelse(
          METRIC != "MarketTaskVolume", 
          scales::percent_format(accuracy = 1), 
          scales::number_format(big.mark = ",", accuracy = 1)
          )
        ) %>%
      kableExtra::kable(
        format = "latex", 
        caption = paste0("Market ", base::gsub("Market", x = METRIC, replacement = " "), " (", MEASURE, ")"), 
        linesep = "",
        digits = 1,
        booktabs = TRUE,
        align = "c"
        ) %>%
      kableExtra::kable_styling(
        latex_options = c(
          "repeat_header",
          "HOLD_position",
          "striped",
          "scale_down"
          )
        ) %>%
      kableExtra::row_spec(0, bold = TRUE) %>%
      print()

    cat("\n")

  }

}


austl001/MOSLR documentation built on Aug. 17, 2022, 12:07 a.m.