Ana içeriğe geç
Kesit Power BI
İleri · Vaka Çalışmaları

Vaka: kredi portföyü ve geri ödeme planı

Bir finansman şirketinin risk yöneticisi on kredilik portföyün durumunu soruyor. Her kredi için PMT ve GENERATESERIES ile aylık geri ödeme planı kurar, taksiti faiz ve anaparaya ayırır, rapor tarihindeki kalan bakiyeyi, segmentlere göre gecikme oranını, sözleşme ve riskten arındırılmış portföy getirisini hesaplar ve kredi düzeyinde bir detay sayfası tasarlarsın.

Uygulamada aç, 6 alıştırmayı çözÜcretsiz, hesap gerekmez, kurulum yok.

Bu sayfa dersin okuma sürümüdür. Metin bir kutuyu çalıştırmanı ya da adıma geçmeni söylüyorsa dersi uygulamada aç.

1. Şirketin sorusu ve brif

Kim soruyor? Küçük bir finansman şirketinin risk yöneticisi. Kurul toplantısından önce portföyün 31.12.2024 itibarıyla fotoğrafını istiyor.

Hangi karar? 2025’te hangi segmentte yeni kredi verilmeye devam edilecek, hangisinde koşullar sıkılaştırılacak? Brifin soruları:

  1. Her kredinin aylık taksiti ne, taksitin ne kadarı faiz, ne kadarı anapara?
  2. Rapor tarihinde portföyde ne kadar bakiye var?
  3. Gecikme ve takip (30+ ve 90+ gün) bakiyenin yüzde kaçı; segmentlere göre fark var mı?
  4. Portföy ne getiriyor? Riskli krediler hesaba katılınca getiri ne olur?
  5. Bir krediye tıklayınca açılan, o kredinin ödeme planını gösteren bir detay sayfası.

Paranın zaman değeri ve PMT fonksiyonunun mantığı Finansal raporlama: gelir tablosu, bütçe sapması, oranlar ve finansal fonksiyonlar dersinde anlatıldı; burada tekrar etmiyoruz, onu bir portföye uyguluyoruz.

Bu vakadaki krediler örnektirUygulamanın modelinde kredi verisi yok. Aşağıdaki on kredi ders için uydurulmuştur; gerçek kişi, şirket ya da kurumla ilgisi yoktur.

2. Veri ve model

Krediler =
DATATABLE(
    "KrediNo", STRING, "Segment", STRING, "Tutar", CURRENCY, "YillikFaiz", DOUBLE,
    "Vade", INTEGER, "Baslangic", DATETIME, "GecikmeGun", INTEGER,
    {
        {"K01", "KOBİ", 400000, 0.42, 24, "2024-01-15", 0},
        {"K02", "KOBİ", 250000, 0.45, 12, "2024-06-01", 45},
        {"K03", "Bireysel", 120000, 0.48, 36, "2023-09-01", 0},
        {"K04", "Bireysel", 80000, 0.50, 24, "2024-03-01", 120},
        {"K05", "Kurumsal", 1000000, 0.38, 36, "2023-04-01", 0},
        {"K06", "Kurumsal", 600000, 0.40, 24, "2024-09-01", 0},
        {"K07", "KOBİ", 300000, 0.44, 18, "2023-12-01", 0},
        {"K08", "Bireysel", 60000, 0.52, 12, "2024-02-01", 35},
        {"K09", "KOBİ", 150000, 0.46, 24, "2024-04-01", 95},
        {"K10", "Kurumsal", 450000, 0.39, 12, "2024-07-01", 0}
    }
)
SütunAnlamı
Tutar, YillikFaiz, VadeKullandırılan anapara, yıllık sözleşme faizi, ay cinsinden vade. Eşit taksitli (anüite) kredi.
BaslangicKullandırım tarihi; ilk taksit bir ay sonra.
GecikmeGunRapor tarihinde en eski ödenmemiş taksitin gecikme günü. 30+ “gecikmede”, 90+ “takipte”.

Modelde ikinci tablo ödeme planıdır: her kredi için her ay bir satır. Krediler ile ödeme planı arasında bire-çok ilişki kurulur (KrediNo), plandaki ödeme tarihi de tarih tablosuna bağlanır.

Veri sınırları:

3. Analiz adımları

Adım 1: Ödeme planı (amortisman tablosu). Aylık faiz i = yıllık faiz ÷ 12, taksit A = PMT(i, Vade, -Tutar). k. taksitten sonra kalan bakiye için kapalı formül: Bk = P·(1+i)k − A·((1+i)k − 1) ÷ i. k. taksitin faizi bir önceki bakiyenin faizidir: Bk−1 × i; anapara = A − faiz. GENERATE her kredi satırı için GENERATESERIES(1, Vade) ile taksit satırlarını üretir:

Ödeme Planı =
GENERATE(
    Krediler,
    VAR i = [YillikFaiz] / 12
    VAR A = PMT(i, [Vade], -[Tutar])
    VAR P0 = [Tutar]
    VAR Bas = [Baslangic]
    RETURN
        SELECTCOLUMNS(
            GENERATESERIES(1, [Vade]),
            "TaksitNo", [Value],
            "OdemeTarihi", EDATE(Bas, [Value]),
            "Taksit", A,
            "Faiz", (P0 * POWER(1 + i, [Value] - 1) - A * (POWER(1 + i, [Value] - 1) - 1) / i) * i,
            "Kalan", P0 * POWER(1 + i, [Value]) - A * (POWER(1 + i, [Value]) - 1) / i
        )
)

Uygulamanın motorunda Krediler modelde olmadığı için aynı tabloyu sorguda değişkenle deneriz. Önce tek bir kredi (K03):

EVALUATE
VAR Krediler =
    DATATABLE(
        "KrediNo", STRING, "Tutar", CURRENCY, "YillikFaiz", DOUBLE, "Vade", INTEGER, "Baslangic", DATETIME,
        {{"K03", 120000, 0.48, 36, "2023-09-01"}}
    )
VAR Plan = GENERATE(
        Krediler,
        VAR i = [YillikFaiz] / 12
        VAR A = PMT(i, [Vade], -[Tutar])
        VAR P0 = [Tutar]
        VAR Bas = [Baslangic]
        RETURN
            SELECTCOLUMNS(
                GENERATESERIES(1, [Vade]),
                "TaksitNo", [Value],
                "OdemeTarihi", EDATE(Bas, [Value]),
                "Taksit", A,
                "Faiz", (P0 * POWER(1 + i, [Value] - 1) - A * (POWER(1 + i, [Value] - 1) - 1) / i) * i,
                "Kalan", P0 * POWER(1 + i, [Value]) - A * (POWER(1 + i, [Value]) - 1) / i
            )
    )
RETURN
    SELECTCOLUMNS(
        FILTER(Plan, [TaksitNo] <= 2 || [TaksitNo] = 15 || [TaksitNo] = 36),
        "Taksit No", [TaksitNo], "Tarih", [OdemeTarihi], "Taksit", [Taksit],
        "Faiz", [Faiz], "Anapara", [Taksit] - [Faiz], "Kalan", [Kalan]
    )
K03 taksitTarihTaksitFaizAnaparaKalan bakiye
101.10.20236.346,43 ₺4.800,00 ₺1.546,43 ₺118.453,57 ₺
201.11.20236.346,43 ₺4.738,14 ₺1.608,28 ₺116.845,29 ₺
1501.12.20246.346,43 ₺3.668,52 ₺2.677,91 ₺89.035,02 ₺
3601.09.20266.346,43 ₺244,09 ₺6.102,33 ₺0,00 ₺

Bulgu: Taksit sabit, içeriği değişiyor. K03’ün ilk taksitinin %76’sı faiz; son taksitin %96’sı anapara. Kredi boyunca toplam 228.471 ₺ ödenecek; bunun 108.471 ₺’si faiz. Son satırda kalan bakiyenin tam 0 çıkması planın doğru kurulduğunun testidir; bu kontrolü her kredi için yap.

Adım 2: Rapor tarihinde kalan bakiye ve 2024 faiz geliri. Her kredi için rapor tarihine kadar vadesi gelen taksitleri sayar, son taksitten sonraki bakiyeyi alırız. Henüz taksiti gelmemiş kredinin bakiyesi tutarın kendisidir.

DEFINE
VAR Krediler = DATATABLE(
    "KrediNo", STRING, "Segment", STRING, "Tutar", CURRENCY, "YillikFaiz", DOUBLE,
    "Vade", INTEGER, "Baslangic", DATETIME, "GecikmeGun", INTEGER,
    {
        {"K01", "KOBİ", 400000, 0.42, 24, "2024-01-15", 0},
        {"K02", "KOBİ", 250000, 0.45, 12, "2024-06-01", 45},
        {"K03", "Bireysel", 120000, 0.48, 36, "2023-09-01", 0},
        {"K04", "Bireysel", 80000, 0.50, 24, "2024-03-01", 120},
        {"K05", "Kurumsal", 1000000, 0.38, 36, "2023-04-01", 0},
        {"K06", "Kurumsal", 600000, 0.40, 24, "2024-09-01", 0},
        {"K07", "KOBİ", 300000, 0.44, 18, "2023-12-01", 0},
        {"K08", "Bireysel", 60000, 0.52, 12, "2024-02-01", 35},
        {"K09", "KOBİ", 150000, 0.46, 24, "2024-04-01", 95},
        {"K10", "Kurumsal", 450000, 0.39, 12, "2024-07-01", 0}
    }
)
VAR Plan = GENERATE(
    Krediler,
    VAR i = [YillikFaiz] / 12
    VAR A = PMT(i, [Vade], -[Tutar])
    VAR P0 = [Tutar]
    VAR Bas = [Baslangic]
    RETURN
        SELECTCOLUMNS(
            GENERATESERIES(1, [Vade]),
            "TaksitNo", [Value],
            "OdemeTarihi", EDATE(Bas, [Value]),
            "Taksit", A,
            "Faiz", (P0 * POWER(1 + i, [Value] - 1) - A * (POWER(1 + i, [Value] - 1) - 1) / i) * i,
            "Kalan", P0 * POWER(1 + i, [Value]) - A * (POWER(1 + i, [Value]) - 1) / i
        )
)
VAR Rapor = DATE(2024, 12, 31)
EVALUATE
ADDCOLUMNS(
    Krediler,
    "Durum", SWITCH(TRUE(), [GecikmeGun] >= 90, "Takipte", [GecikmeGun] >= 30, "Gecikmede", "Düzenli"),
    "Odenen", VAR k = [KrediNo] RETURN COUNTROWS(FILTER(Plan, [KrediNo] = k && [OdemeTarihi] <= Rapor)) + 0,
    "Bakiye",
        VAR k = [KrediNo]
        VAR t = [Tutar]
        VAR p = FILTER(Plan, [KrediNo] = k && [OdemeTarihi] <= Rapor)
        RETURN IF(ISEMPTY(p), t, MINX(p, [Kalan])),
    "Faiz2024", VAR k = [KrediNo] RETURN SUMX(FILTER(Plan, [KrediNo] = k && YEAR([OdemeTarihi]) = 2024), [Faiz]),
    "Tahsilat2025", VAR k = [KrediNo] RETURN SUMX(FILTER(Plan, [KrediNo] = k && YEAR([OdemeTarihi]) = 2025), [Taksit])
)
KrediSegmentTutarDurumÖdenen taksitKalan bakiye2024 faiz
K01KOBİ400.000 ₺Düzenli11 / 24256.632 ₺130.633 ₺
K02KOBİ250.000 ₺Gecikmede (45)6 / 12138.749 ₺46.268 ₺
K03Bireysel120.000 ₺Düzenli15 / 3689.035 ₺50.019 ₺
K04Bireysel80.000 ₺Takipte (120)9 / 2458.652 ₺26.683 ₺
K05Kurumsal1.000.000 ₺Düzenli20 / 36582.299 ₺282.409 ₺
K06Kurumsal600.000 ₺Düzenli3 / 24548.172 ₺58.310 ₺
K07KOBİ300.000 ₺Düzenli12 / 18122.209 ₺98.934 ₺
K08Bireysel60.000 ₺Gecikmede (35)10 / 1212.234 ₺17.408 ₺
K09KOBİ150.000 ₺Takipte (95)8 / 24114.086 ₺41.453 ₺
K10Kurumsal450.000 ₺Düzenli5 / 12283.204 ₺62.630 ₺

Bulgu: 3.410.000 ₺ kullandırılmış, rapor tarihinde 2.205.272 ₺ bakiye var. 2024’te vadesi gelen taksitlerin faiz kısmı 814.747 ₺, anapara kısmı 1.063.190 ₺: tahsil edilmesi gerekenin %43’ü faiz. 2025’te planlanan tahsilat 2.189.223 ₺; bunun 350.646 ₺’si (%16) 30 gün ve üstü gecikmedeki kredilerden.

Adım 3: Segmentlere göre risk ve getiri. Gecikme oranını kredi sayısıyla değil bakiyeyle ölçeriz: küçük bir kredinin gecikmesi büyük bir kredininkiyle aynı ağırlığı taşımamalı. Getiri için iki ölçü: sözleşme getirisi (bakiye ağırlıklı faiz) ve takipteki kredileri getirisiz sayan riskten arındırılmış getiri.

DEFINE
VAR Krediler = DATATABLE(
    "KrediNo", STRING, "Segment", STRING, "Tutar", CURRENCY, "YillikFaiz", DOUBLE,
    "Vade", INTEGER, "Baslangic", DATETIME, "GecikmeGun", INTEGER,
    {
        {"K01", "KOBİ", 400000, 0.42, 24, "2024-01-15", 0},
        {"K02", "KOBİ", 250000, 0.45, 12, "2024-06-01", 45},
        {"K03", "Bireysel", 120000, 0.48, 36, "2023-09-01", 0},
        {"K04", "Bireysel", 80000, 0.50, 24, "2024-03-01", 120},
        {"K05", "Kurumsal", 1000000, 0.38, 36, "2023-04-01", 0},
        {"K06", "Kurumsal", 600000, 0.40, 24, "2024-09-01", 0},
        {"K07", "KOBİ", 300000, 0.44, 18, "2023-12-01", 0},
        {"K08", "Bireysel", 60000, 0.52, 12, "2024-02-01", 35},
        {"K09", "KOBİ", 150000, 0.46, 24, "2024-04-01", 95},
        {"K10", "Kurumsal", 450000, 0.39, 12, "2024-07-01", 0}
    }
)
VAR Plan = GENERATE(
    Krediler,
    VAR i = [YillikFaiz] / 12
    VAR A = PMT(i, [Vade], -[Tutar])
    VAR P0 = [Tutar]
    VAR Bas = [Baslangic]
    RETURN
        SELECTCOLUMNS(
            GENERATESERIES(1, [Vade]),
            "TaksitNo", [Value],
            "OdemeTarihi", EDATE(Bas, [Value]),
            "Taksit", A,
            "Faiz", (P0 * POWER(1 + i, [Value] - 1) - A * (POWER(1 + i, [Value] - 1) - 1) / i) * i,
            "Kalan", P0 * POWER(1 + i, [Value]) - A * (POWER(1 + i, [Value]) - 1) / i
        )
)
VAR Rapor = DATE(2024, 12, 31)
VAR Ozet = ADDCOLUMNS(
    Krediler,
    "Durum", SWITCH(TRUE(), [GecikmeGun] >= 90, "Takipte", [GecikmeGun] >= 30, "Gecikmede", "Düzenli"),
    "Odenen", VAR k = [KrediNo] RETURN COUNTROWS(FILTER(Plan, [KrediNo] = k && [OdemeTarihi] <= Rapor)) + 0,
    "Bakiye",
        VAR k = [KrediNo]
        VAR t = [Tutar]
        VAR p = FILTER(Plan, [KrediNo] = k && [OdemeTarihi] <= Rapor)
        RETURN IF(ISEMPTY(p), t, MINX(p, [Kalan])),
    "Faiz2024", VAR k = [KrediNo] RETURN SUMX(FILTER(Plan, [KrediNo] = k && YEAR([OdemeTarihi]) = 2024), [Faiz]),
    "Tahsilat2025", VAR k = [KrediNo] RETURN SUMX(FILTER(Plan, [KrediNo] = k && YEAR([OdemeTarihi]) = 2025), [Taksit])
)
EVALUATE
ADDCOLUMNS(
    DISTINCT(SELECTCOLUMNS(Krediler, "Segment", [Segment])),
    "Bakiye", VAR s = [Segment] RETURN SUMX(FILTER(Ozet, [Segment] = s), [Bakiye]),
    "Gecikme 30+ %", VAR s = [Segment]
        RETURN DIVIDE(SUMX(FILTER(Ozet, [Segment] = s && [GecikmeGun] >= 30), [Bakiye]), SUMX(FILTER(Ozet, [Segment] = s), [Bakiye])) + 0,
    "Takip 90+ %", VAR s = [Segment]
        RETURN DIVIDE(SUMX(FILTER(Ozet, [Segment] = s && [GecikmeGun] >= 90), [Bakiye]), SUMX(FILTER(Ozet, [Segment] = s), [Bakiye])) + 0,
    "Sözleşme Getirisi", VAR s = [Segment]
        RETURN DIVIDE(SUMX(FILTER(Ozet, [Segment] = s), [Bakiye] * [YillikFaiz]), SUMX(FILTER(Ozet, [Segment] = s), [Bakiye])),
    "Riskten Arındırılmış", VAR s = [Segment]
        RETURN DIVIDE(SUMX(FILTER(Ozet, [Segment] = s && [GecikmeGun] < 90), [Bakiye] * [YillikFaiz]), SUMX(FILTER(Ozet, [Segment] = s), [Bakiye]))
)
SegmentKrediBakiye (pay)Gecikme 30+Takip 90+Sözleşme getirisiRiskten arındırılmış
Kurumsal31.413.675 ₺ (%64,1)%0%0%39,0%39,0
KOBİ4631.677 ₺ (%28,6)%40,0%18,1%43,8%35,5
Bireysel3159.921 ₺ (%7,3)%44,3%36,7%49,0%30,7
Portföy102.205.272 ₺%14,7%7,8%41,1%37,4

Bulgu: Kâğıt üzerinde en kârlı segment Bireysel (%49,0), ama takipteki K04 hesaba katılınca getirisi %30,7’ye iniyor ve en düşük segment oluyor. Kurumsal hiç gecikme olmadan %39,0 getiriyor. Yüksek faiz riskin bedelidir; risk gerçekleşince getiri kaybolur. Portföy düzeyinde takip oranı %7,8 ve bu bakiye 2024 faizinin 68.136 ₺’sini oluşturuyor; bu faiz büyük olasılıkla tahsil edilemeyecek.

Neden 10 kredi az?Gerçek bir portföyde binlerce kredi olur ve oranlar daha durağandır. Burada tek bir kredi (K04) Bireysel segmentin takip oranını %36,7’ye çıkarıyor. Küçük segmentlerde kredi sayısını tablonun yanında göster; Vaka: şehir ve temsilci kıyaslaması’ndaki örnek büyüklüğü uyarısı burada da geçerli.

Adım 4: Model ölçüleri ve kredi detay sayfası. Gerçek modelde Krediler ve Ödeme Planı iki tablodur; ölçüler ilişki üzerinden çalışır. Kalan bakiye yarı toplanabilir bir değerdir: krediler üzerinden toplanır ama aylar üzerinden toplanmaz (Yarı toplanabilir ölçüler: stok, bakiye, nüfus).

Kalan Bakiye =
VAR Rapor = MAX(Tarih[Tarih])
RETURN
    SUMX(
        VALUES(Krediler[KrediNo]),
        VAR Son = CALCULATE(MIN('Ödeme Planı'[Kalan]), REMOVEFILTERS(Tarih), 'Ödeme Planı'[OdemeTarihi] <= Rapor)
        RETURN IF(ISBLANK(Son), CALCULATE(SUM(Krediler[Tutar])), Son)
    )
Gecikme 30+ % =
DIVIDE(CALCULATE([Kalan Bakiye], Krediler[GecikmeGun] >= 30), [Kalan Bakiye])
Kredi Başlığı =
VAR No = SELECTEDVALUE(Krediler[KrediNo])
VAR Gun = SELECTEDVALUE(Krediler[GecikmeGun])
VAR Durum = SWITCH(TRUE(), Gun >= 90, "Takipte", Gun >= 30, "Gecikmede", "Düzenli")
RETURN
    IF(
        ISBLANK(No), "Bir kredi seçin",
        No & " · " & SELECTEDVALUE(Krediler[Segment]) & " · " & FORMAT(SELECTEDVALUE(Krediler[Tutar]), "#,##0") & " ₺ · yıllık %"
            & FORMAT(SELECTEDVALUE(Krediler[YillikFaiz]) * 100, "0") & " · " & Durum & IF(Gun > 0, " (" & Gun & " gün)")
    )

Portföy sayfasındaki kredi tablosunda bir satıra sağ tıklayıp Detaya git denince Kredi detayı sayfası açılır; detay alanı Krediler[KrediNo]. K04 için başlık “K04 · Bireysel · 80.000 ₺ · yıllık %50 · Takipte (120 gün)” olur. Sayfada ödeme planı tablosu (taksit no, tarih, faiz, anapara, kalan), faiz ve anaparayı yığılmış sütunla gösteren grafik ve rapor tarihini işaretleyen bir sabit çizgi bulunur.

4. Rapor sayfası taslağı

Sayfa / konumGörselAlanlar
Portföy, üst şerit4 kartKalan bakiye (2.205.272 ₺), Gecikme 30+ % (%14,7), Takip 90+ % (%7,8), Riskten arındırılmış getiri (%37,4)
Portföy, solKümelenmiş çubukSegment; Sözleşme getirisi ve riskten arındırılmış getiri yan yana
Portföy, sağYığılmış sütun2025 ayları; planlanan tahsilat, Durum’a göre renkli (Düzenli / Gecikmede / Takipte)
Portföy, altTabloKredi; Segment, Tutar, Ödenen taksit, Kalan bakiye, Durum (koşullu ikon)
Kredi detayıDetay sayfasıBaşlık: Kredi Başlığı; ödeme planı tablosu; faiz/anapara yığılmış sütunu; “Geri” düğmesi

5. Bulgu özeti ve öneri

  1. Portföyün %14,7’si 30 gün ve üstü gecikmede, %7,8’i takipte. Takipteki iki kredi (K04, K09) için yapılandırma ya da hukuki takip kararı ve karşılık ayrılması gerekiyor.
  2. Bireysel segmentte koşulları sıkılaştır: en yüksek sözleşme faizine (%49,0) rağmen riskten arındırılmış getiri en düşük (%30,7). Faizi artırmak yerine kredi onay kriterlerini gözden geçir.
  3. Kurumsal segment portföyün bel kemiği: bakiyenin %64,1’i, gecikme yok, getiri %39,0. Büyüme bu segmentte daha güvenli; ama tek bir kredinin (K05) bakiyenin %26’sı olduğu yoğunlaşma riski not edilmeli.
  4. 2025 nakit planını riske göre ayır: planlanan 2.189.223 ₺ tahsilatın 350.646 ₺’si gecikmedeki kredilerden; nakit planında bu kısmı ayrı satırda ve iskontolu göster.
  5. Modeli tamamla: gerçek tahsilat tablosu ve vadelerin sonuna kadar uzanan tarih tablosu olmadan bakiye sözleşme varsayımına dayanır.
Alıştırmalara geç (6)