Bu döküman enerji sektöründe analist olarak çalışmaya başlayan veya enerji sektörü için analiz yapmak isteyenlere yönelik olarak R yardımı ile KÜPST cezalarının nasıl hesaplanabileceğini göstermek için hazırlanmıştır. Dökümanda kullanılan veri setleri EPİAŞ Şeffaflık Platformu’ndan alınmıştır.
Bu dökümanda kullanılan kodlar hakkında daha fazla bilgi edinmek ve R’da dplyr
, ggplot2
ve lubridate
gibi paketlerin nasıl kullanabileceğini daha iyi anlamak için R İLE ENERJİ PİYASASI VERİ ANALİZİ EL KİTABI’nı inceleyebilirsiniz. R hakkında kendinizi yeterli hissetmiyorsanız bu dökümanı incelemeden önce yukarıdaki kitabı incelemenizi şiddetle tavsiye ediyoruz.
Bu dökümanda gerekli veri manipülasyonları için dplyr
, tarih ve saatlerle ilgili veri manipülasyonları için lubridate
paketleri kullanılmıştır. Bu paketlerin indirilip yüklenmesi için aşağıdaki adımlar izlenebilir:
1. Gerekli Paketleri İndirmek İçin
install.packages("dplyr")
install.packages("lubridate")
2. Gerekli Paketleri Yüklemek İçin
library(dplyr)
library(lubridate)
Bu dökümanda 2019 yılı PTF (Piyasa Takas Fiyatı), SMF (Sistem Marjinal Fiyatı), GZÜ (Gerçek Zamanlı Üretim) ve KUDÜP (Kesinleştirilmiş Uzlaştırma Dönemi Üretim Planı) değerleri ve örnek santral olarak Bergama RES Enerji Üretim AŞ. ve bu şirkete bağlı Aliağa RES (Rüzgar Enerji Santrali) seçilerek elde edilmiş veri setleri kullanılmıştır.
Bu değişkenlerin ne anlama geldiğinden kısaca bahsetmek gerekirse:
Piyasa Takas Fiyatı (PTF): Gün öncesi piyasasında (GÖP) verilmiş olan teklifler sonucu arz ve talebin kesiştiği noktada meydana gelen fiyat olarak adlandırılabilir.
Sistem Marjinal Fiyatı (SMF): Sistemin enerji açığı ya da fazlası gösterdiği durumlarda Dengeleme Güç Piyasası’nda YAL ve YAT talimatlarına göre net talimat hacmine tekabül eden teklif fiyatı olarak adlandırılabilir.
KUDÜP (Kesinleştirilmiş Uzlaştırma Dönemi Üretim Planı): Gün içi işlemlerden sonra kesinleşmiş üretim tahminidir.
GZÜ (Gerçek Zamanlı Üretim): Gerçek zamanda üretilen enerji miktarıdır.
KÜPST: Saatlik KUDÜP ve gerçekleşen üretim miktarı arasındaki farkın belli bir toleransı geçmesiyle oluşan bir nevi dengesizlik cezasıdır. (Rüzgar Enerji Santralleri için bu tolerans %10’dur.)
Bu veri setlerini indirmek için aşağıdaki yollar izlenebilir:
1. PTF - SMF Verisini İndirmek İçin
ptfsmf <- readRDS(url("https://github.com/barandogru/kupst_cezasi_hesaplama/blob/master/ptfsmf.RDS?raw=true"))
2. KUDÜP Verisini İndirmek İçin
kudup <- readRDS(url("https://github.com/barandogru/kupst_cezasi_hesaplama/blob/master/kudup.RDS?raw=true"))
3. GZÜ Verisini İndirmek İçin
gzu <- readRDS(url("https://github.com/barandogru/kupst_cezasi_hesaplama/blob/master/gzu.RDS?raw=true"))
Bu aşama başarıyla tamamlandığında bir sonraki bölüme geçilebilir.
Bu bölümde ham halde indirilen veri setlerinin nasıl doğru formatlara getirileceği anlatılacaktır. Bu aşamalar daha sonra bu veri setlerinin tek bir veri setinde toplanılabilmesi ve üzerinde çeşitli işlemlerin yapılabilmesi için gerekli işlemlerdir.
İlk olarak PTF - SMF verisi incelenecek olursa tablonun ilk haline göz atmak için,
ptfsmf
## # A tibble: 8,760 x 6
## Tarih PTF SMF `Pozitif Dengesizlik … `Negatif Dengesizlik… `SMF Yön`
## <chr> <chr> <chr> <chr> <chr> <chr>
## 1 01.01.1… 100,38 5,00 4,85 103,39 ↓Enerji F…
## 2 01.01.1… 96,72 95,04 92,19 99,62 ↓Enerji F…
## 3 01.01.1… 81,60 79,60 77,21 84,05 ↓Enerji F…
## 4 01.01.1… 38,58 0,00 0,00 39,74 ↓Enerji F…
## 5 01.01.1… 11,52 0,00 0,00 11,87 ↓Enerji F…
## 6 01.01.1… 11,14 0,00 0,00 11,47 ↓Enerji F…
## 7 01.01.1… 11,14 0,00 0,00 11,47 ↓Enerji F…
## 8 01.01.1… 24,37 0,00 0,00 25,10 ↓Enerji F…
## 9 01.01.1… 34,50 0,00 0,00 35,53 ↓Enerji F…
## 10 01.01.1… 45,21 0,00 0,00 46,57 ↓Enerji F…
## # … with 8,750 more rows
Gerekli değişikliklerin uygulamanmasını sağlayacak kodlar yazılırsa,
colnames(ptfsmf)[4] = "PDF"
colnames(ptfsmf)[5] = "NDF"
ptfsmf <- ptfsmf %>% mutate(Tarih_Yeni = as.POSIXct(ptfsmf$Tarih,format="%d.%m.%y %H:%M", "GMT")) %>%
select(Tarih_Yeni, PTF, SMF) %>%
rename(Tarih = Tarih_Yeni)
ptfsmf[,c(2:3)] <- lapply(ptfsmf[,c(2:3)],function(x) as.numeric(gsub(",", ".", gsub("\\.", "", x))))
Tablonun güncellenmiş haline göz atmak için,
ptfsmf
## # A tibble: 8,760 x 3
## Tarih PTF SMF
## <dttm> <dbl> <dbl>
## 1 2019-01-01 00:00:00 100. 5
## 2 2019-01-01 01:00:00 96.7 95.0
## 3 2019-01-01 02:00:00 81.6 79.6
## 4 2019-01-01 03:00:00 38.6 0
## 5 2019-01-01 04:00:00 11.5 0
## 6 2019-01-01 05:00:00 11.1 0
## 7 2019-01-01 06:00:00 11.1 0
## 8 2019-01-01 07:00:00 24.4 0
## 9 2019-01-01 08:00:00 34.5 0
## 10 2019-01-01 09:00:00 45.2 0
## # … with 8,750 more rows
Burada tarih formatı POSIXct
formatı olarak değiştirildi, character
formatında olan sayı değerleri numeric
formatına güncellendi ve programın sayı değerlerini yanlış anlamasına sebep olan virgül ve nokta yerleştirmeleri düzenlendi.
Aynı işlemleri KUDÜP verisine uygulamadan önce KUDÜP veri setine göz atalım.
kudup
## # A tibble: 8,760 x 15
## Tarih Saat `Toplam (MWh)` `Doğal Gaz` Rüzgar Linyit `Taş Kömür`
## <chr> <chr> <chr> <chr> <chr> <chr> <chr>
## 1 01.0… 00:00 48,60 0,00 48,60 0,00 0,00
## 2 01.0… 01:00 55,60 0,00 55,60 0,00 0,00
## 3 01.0… 02:00 51,10 0,00 51,10 0,00 0,00
## 4 01.0… 03:00 45,60 0,00 45,60 0,00 0,00
## 5 01.0… 04:00 47,30 0,00 47,30 0,00 0,00
## 6 01.0… 05:00 52,20 0,00 52,20 0,00 0,00
## 7 01.0… 06:00 57,10 0,00 57,10 0,00 0,00
## 8 01.0… 07:00 62,70 0,00 62,70 0,00 0,00
## 9 01.0… 08:00 92,30 0,00 92,30 0,00 0,00
## 10 01.0… 09:00 69,00 0,00 69,00 0,00 0,00
## # … with 8,750 more rows, and 8 more variables: `İthal Kömür` <chr>, `Fuel
## # Oil` <chr>, Jeotermal <chr>, Barajlı <chr>, Nafta <chr>, Biyokütle <chr>,
## # Akarsu <chr>, Diğer <chr>
Görüleceği üzere bu döküman için gerekli olmayan birçok sütuna sahip. Bu sütunların kaldırılması ve yukarıda bahsedilen dönüşümlerin yapılması,
kudup <- kudup %>%
select(Tarih, Saat, Rüzgar) %>%
rename(KUDUP = Rüzgar) %>%
mutate(Tarih_Yeni = as.POSIXct(paste(Tarih, Saat),format="%d.%m.%Y %H:%M", "GMT")) %>%
select(Tarih_Yeni, KUDUP) %>%
rename(Tarih = Tarih_Yeni)
kudup$KUDUP <- as.numeric(gsub(",", "\\.", kudup$KUDUP))
Tablonun son haline bakacak olursak,
kudup
## # A tibble: 8,760 x 2
## Tarih KUDUP
## <dttm> <dbl>
## 1 2019-01-01 00:00:00 48.6
## 2 2019-01-01 01:00:00 55.6
## 3 2019-01-01 02:00:00 51.1
## 4 2019-01-01 03:00:00 45.6
## 5 2019-01-01 04:00:00 47.3
## 6 2019-01-01 05:00:00 52.2
## 7 2019-01-01 06:00:00 57.1
## 8 2019-01-01 07:00:00 62.7
## 9 2019-01-01 08:00:00 92.3
## 10 2019-01-01 09:00:00 69
## # … with 8,750 more rows
Son olarak da aynı işlemleri GZÜ veri setine uygulamadan önce veri setini inceleyecek olursak,
gzu
## # A tibble: 8,760 x 18
## Tarih Saat `Toplam (MWh)` `Doğal Gaz` Barajlı Linyit Akarsu `İthal Kömür`
## <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
## 1 01.0… 00:00 1,62 0,00 0,00 0,00 0,00 0,00
## 2 01.0… 01:00 0,51 0,00 0,00 0,00 0,00 0,00
## 3 01.0… 02:00 2,47 0,00 0,00 0,00 0,00 0,00
## 4 01.0… 03:00 4,27 0,00 0,00 0,00 0,00 0,00
## 5 01.0… 04:00 14,62 0,00 0,00 0,00 0,00 0,00
## 6 01.0… 05:00 12,66 0,00 0,00 0,00 0,00 0,00
## 7 01.0… 06:00 4,18 0,00 0,00 0,00 0,00 0,00
## 8 01.0… 07:00 3,53 0,00 0,00 0,00 0,00 0,00
## 9 01.0… 08:00 14,49 0,00 0,00 0,00 0,00 0,00
## 10 01.0… 09:00 16,68 0,00 0,00 0,00 0,00 0,00
## # … with 8,750 more rows, and 10 more variables: Rüzgar <chr>, Güneş <chr>,
## # `Fuel Oil` <chr>, Jeotermal <chr>, `Asfaltit Kömür` <chr>, `Taş
## # Kömür` <chr>, Biyokütle <chr>, Nafta <chr>, LNG <chr>, Uluslararası <chr>
Şimdi gerekli düzenlemeleri yapalım,
gzu <- gzu %>%
select(Tarih, Saat, Rüzgar) %>%
rename(GZU = Rüzgar) %>%
mutate(Tarih_Yeni = as.POSIXct(paste(Tarih, Saat),format="%d.%m.%Y %H:%M", "GMT")) %>%
select(Tarih_Yeni, GZU) %>%
rename(Tarih = Tarih_Yeni)
gzu$GZU <- as.numeric(gsub(",", "\\.", gzu$GZU))
Tablonun son hali şu şekilde olacaktır,
gzu
## # A tibble: 8,760 x 2
## Tarih GZU
## <dttm> <dbl>
## 1 2019-01-01 00:00:00 1.62
## 2 2019-01-01 01:00:00 0.51
## 3 2019-01-01 02:00:00 2.47
## 4 2019-01-01 03:00:00 4.27
## 5 2019-01-01 04:00:00 14.6
## 6 2019-01-01 05:00:00 12.7
## 7 2019-01-01 06:00:00 4.18
## 8 2019-01-01 07:00:00 3.53
## 9 2019-01-01 08:00:00 14.5
## 10 2019-01-01 09:00:00 16.7
## # … with 8,750 more rows
Son olarak, ortaya çıkan düzenlenmiş bu 3 tabloyu tek bir tabloda Tarih sütunu yardımıyla birleştirelim.
temp <- merge(x = gzu, y = kudup, by = "Tarih")
df <- merge(x = temp, y = ptfsmf, by = "Tarih")
Burada iki kere merge fonksiyonunun kullanılma sebebi bu fonksiyonun doğası gereği yalnızca iki tabloyu birleştirebilmesindendir. O nedenle iki ayrı birleştirme operasyonu yapılmış gibi düşünülebilir.
Tablonun son haline göz atacak olursak,
head(df, n=10)
## Tarih GZU KUDUP PTF SMF
## 1 2019-01-01 00:00:00 1.62 48.6 100.38 5.00
## 2 2019-01-01 01:00:00 0.51 55.6 96.72 95.04
## 3 2019-01-01 02:00:00 2.47 51.1 81.60 79.60
## 4 2019-01-01 03:00:00 4.27 45.6 38.58 0.00
## 5 2019-01-01 04:00:00 14.62 47.3 11.52 0.00
## 6 2019-01-01 05:00:00 12.66 52.2 11.14 0.00
## 7 2019-01-01 06:00:00 4.18 57.1 11.14 0.00
## 8 2019-01-01 07:00:00 3.53 62.7 24.37 0.00
## 9 2019-01-01 08:00:00 14.49 92.3 34.50 0.00
## 10 2019-01-01 09:00:00 16.68 69.0 45.21 0.00
İstenilen her değişkeni aynı tabloda toplamayı ve bu değişkenleri gerekli formatlara getirmeyi başardık. KÜPST cezasının nasıl hesaplandığının anlatıldığı ve pratikte uygulandığı bir sonraki bölüme geçmeye hazırsınız.
Uygulamaya geçmeden önce KÜPST cezasının teorik olarak nasıl hesaplandığından bahsetmek gerekmektedir. Yukarıda da bahsedildiği gibi KÜPST cezası saatlik KUDÜP ve gerçekleşen üretim miktarı arasındaki farkın belli bir toleransı geçmesiyle oluşur. KÜPST hesaplama aşamaları aşağıdaki gibidir.
\[ Tolerans = GZÜ / 10 \] \[ KÜPST = |GZÜ - KUDÜP| - Tolerans \] \[ Birim KÜPST = max(PTF, SMF)*0.03 \] \[ Toplam KÜPST = KÜPST*BirimKÜPST \]
Toplam KÜPST cezasının hesaplanma aşamaları anlatıldıktan sonra uygulamaya geçilebilir.
Gerekli kodlar şu şekildedir,
df <- df %>%
mutate(Tolerans = GZU/10, KUPST = (abs(GZU - KUDUP) - Tolerans),
BirimKUPST = ifelse(PTF>SMF, PTF*0.03, SMF*0.03),
KUPST_Cezasi = KUPST * BirimKUPST)
Tablonun son haline göz atacak olursak,
head(df, n=10)
## Tarih GZU KUDUP PTF SMF Tolerans KUPST BirimKUPST
## 1 2019-01-01 00:00:00 1.62 48.6 100.38 5.00 0.162 46.818 3.0114
## 2 2019-01-01 01:00:00 0.51 55.6 96.72 95.04 0.051 55.039 2.9016
## 3 2019-01-01 02:00:00 2.47 51.1 81.60 79.60 0.247 48.383 2.4480
## 4 2019-01-01 03:00:00 4.27 45.6 38.58 0.00 0.427 40.903 1.1574
## 5 2019-01-01 04:00:00 14.62 47.3 11.52 0.00 1.462 31.218 0.3456
## 6 2019-01-01 05:00:00 12.66 52.2 11.14 0.00 1.266 38.274 0.3342
## 7 2019-01-01 06:00:00 4.18 57.1 11.14 0.00 0.418 52.502 0.3342
## 8 2019-01-01 07:00:00 3.53 62.7 24.37 0.00 0.353 58.817 0.7311
## 9 2019-01-01 08:00:00 14.49 92.3 34.50 0.00 1.449 76.361 1.0350
## 10 2019-01-01 09:00:00 16.68 69.0 45.21 0.00 1.668 50.652 1.3563
## KUPST_Cezasi
## 1 140.98773
## 2 159.70116
## 3 118.44158
## 4 47.34113
## 5 10.78894
## 6 12.79117
## 7 17.54617
## 8 43.00111
## 9 79.03364
## 10 68.69931
Burada yapılan işlemlerden kısaca bahsedecek olursak, öncelikle Tolerans adında bir sütun oluşturularak GZÜ değerinin 1/10’una eşitlendi. Sonra sırasıyla KÜPST ve Birim KÜPST değerleri yukarıda verilen denklemler çerçevesinde hesaplandı. En son olarak da toplam KÜPST cezası KUPST_Cezasi adında bir sütunda KUPST ve BirimKUPST değerlerinin çarpımıyla hesaplandı.
Bu dökümanda Rüzgar Enerji Santralleri (RES) için önemli bir dengesizlik cezası olan KÜPST cezasının nasıl hesaplanabileceği adım adım gösterilmeyi çalışılmıştır. Bu değerin Rüzgar Santralleri için önemli oldukça önemli olmasının nedeni, Rüzgar Santrallerinin genellikle dengeden sorumlu grup içerisinde olmalarından ve dengesizlik cezalarından fazla etkilenmeseler de KÜPST cezasından etkilenmelerinden kaynaklanmaktadır.
Herhangi bir sorun ya da öneri durumunda kitabın yazarına Baran Doğru hesabından ulaşabilirsiniz.