Files
trendyol-analiz/backend/analytics/metrics.py
furkanyigit34 c7be57064b Initial commit: Trendyol Analiz platform
- FastAPI backend with Python
- React + Vite admin panel
- PostgreSQL database
- Trendyol marketplace analytics
- GitHub Actions CI/CD workflow

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-15 00:14:38 +03:00

289 lines
7.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
Metrics Utilities - Genel metrik hesaplama fonksiyonları
Performance optimized with Counter and NumPy
"""
from typing import List, Dict
from collections import Counter, defaultdict
import numpy as np
def calculate_hhi_index(products: List[Dict]) -> float:
"""
HHI (Herfindahl-Hirschman Index) hesapla
Pazar konsantrasyonunu ölçer (0-10000 arası)
PERFORMANCE: Counter kullanarak optimize edildi
Args:
products: Ürün listesi
Returns:
HHI Index (0-10000)
"""
# Counter kullanarak marka sayılarını topla (O(n) complexity)
brand_names = [
p.get("brand", {}).get("name", "Unknown")
for p in products
if p.get("brand", {}).get("name")
]
if not brand_names:
return 0
# Counter ile hızlı sayım
brand_counts = Counter(brand_names)
total = len(products)
if total == 0:
return 0
# NumPy array ile hızlı hesaplama
counts_array = np.array(list(brand_counts.values()))
market_shares = counts_array / total
hhi = np.sum(market_shares ** 2) * 10000
return round(float(hhi), 2)
def calculate_market_concentration(brand_counts: Dict[str, int]) -> Dict[str, float]:
"""
Pazar konsantrasyonu hesapla (marka payları)
PERFORMANCE: NumPy ile optimize edildi
Args:
brand_counts: Marka bazlı ürün sayıları
Returns:
Marka payları (yüzde)
"""
if not brand_counts:
return {}
total = sum(brand_counts.values())
if total == 0:
return {}
# NumPy ile hızlı hesaplama
counts_array = np.array(list(brand_counts.values()))
shares = (counts_array / total) * 100
return {
brand: round(float(share), 2)
for brand, share in zip(brand_counts.keys(), shares)
}
def calculate_price_premium(category_avg_price: float, overall_avg_price: float) -> float:
"""
Fiyat primi hesapla
Kategori ortalamasının genel ortalamaya göre farkı
Args:
category_avg_price: Kategori ortalama fiyatı
overall_avg_price: Genel ortalama fiyat
Returns:
Fiyat primi (yüzde)
"""
if overall_avg_price == 0:
return 0
premium = ((category_avg_price / overall_avg_price) - 1) * 100
return round(premium, 2)
def calculate_conversion_rates(social_data: Dict) -> Dict[str, float]:
"""
Conversion rate'leri hesapla
Görüntülenme → Sepet → Sipariş dönüşüm oranları
Args:
social_data: Sosyal kanıt verileri
Returns:
Conversion rate'ler (yüzde)
"""
details = social_data.get("details", {})
total_views = sum(
data.get("page_views", 0)
for data in details.values()
)
total_baskets = sum(
data.get("baskets", 0)
for data in details.values()
)
total_orders = sum(
data.get("orders", 0)
for data in details.values()
)
return {
"view_to_basket": round((total_baskets / total_views * 100) if total_views > 0 else 0, 2),
"basket_to_order": round((total_orders / total_baskets * 100) if total_baskets > 0 else 0, 2),
"view_to_order": round((total_orders / total_views * 100) if total_views > 0 else 0, 2),
"total_views": total_views,
"total_baskets": total_baskets,
"total_orders": total_orders
}
def calculate_brand_strength(
brand_products: List[Dict],
total_products: int,
social_data: Dict = None
) -> float:
"""
Marka güç skoru hesapla
Formül: brand_share + (avg_rating * 5) - stockout_rate
Args:
brand_products: Markaya ait ürünler
total_products: Toplam ürün sayısı
social_data: Sosyal kanıt verileri (opsiyonel)
Returns:
Marka güç skoru
"""
brand_count = len(brand_products)
brand_share = (brand_count / total_products * 100) if total_products > 0 else 0
# Rating ortalaması
ratings = []
for p in brand_products:
rating = p.get("rating", 0)
if isinstance(rating, dict):
rating = rating.get("averageRating", 0)
if rating and rating > 0:
ratings.append(rating)
avg_rating = sum(ratings) / len(ratings) if ratings else 0
# Stockout rate
out_of_stock = sum(1 for p in brand_products if not p.get("inStock", False))
stockout_rate = (out_of_stock / brand_count * 100) if brand_count > 0 else 0
# Güç skoru
strength_score = brand_share + (avg_rating * 5) - stockout_rate
return round(strength_score, 2)
def calculate_potential_score(
page_views: int,
orders: int,
review_count: int,
conversion_rate: float,
competition_level: str
) -> float:
"""
Potential score hesapla (0-100)
Ürünün büyüme potansiyelini ölçer
Args:
page_views: Görüntülenme sayısı
orders: Sipariş sayısı
review_count: Yorum sayısı
conversion_rate: Dönüşüm oranı (yüzde)
competition_level: Rekabet seviyesi (low/medium/high)
Returns:
Potential score (0-100)
"""
score = 0
# 1. Görüntülenme skoru (30 puan)
if page_views >= 10000:
score += 30
elif page_views >= 5000:
score += 20
elif page_views >= 1000:
score += 10
# 2. Conversion rate skoru (25 puan)
if conversion_rate >= 5:
score += 25
elif conversion_rate >= 3:
score += 20
elif conversion_rate >= 2:
score += 15
else:
score += 10
# 3. Rekabet seviyesi skoru (25 puan)
if competition_level == "low":
score += 25
elif competition_level == "medium":
score += 15
else:
score += 5
# 4. Yorum sayısı skoru (20 puan) - Az yorum = henüz keşfedilmemiş
if 1 <= review_count <= 10:
score += 20 # Çok az yorum, büyüme potansiyeli
elif 11 <= review_count <= 20:
score += 15
elif 21 <= review_count <= 50:
score += 10
else:
score += 5
return min(100, round(score, 2))
def get_rating_value(product: Dict) -> float:
"""
Ürün rating'ini al (dict veya number olabilir)
Args:
product: Ürün dict'i
Returns:
Rating değeri (0-5)
"""
rating = product.get("rating", 0)
if isinstance(rating, dict):
return rating.get("averageRating", 0) or 0
return float(rating) if rating else 0
def get_review_count(product: Dict) -> int:
"""
Ürün yorum sayısını al
Args:
product: Ürün dict'i
Returns:
Yorum sayısı
"""
review_count = product.get("rating_count", 0)
if not review_count:
rating = product.get("rating", {})
if isinstance(rating, dict):
review_count = rating.get("totalComments", 0) or rating.get("totalCount", 0) or 0
return int(review_count) if review_count else 0
def calculate_competition_score_from_hhi(hhi: float) -> float:
"""
HHI Index'ten rekabet skoru hesapla (0-100)
Args:
hhi: HHI Index değeri
Returns:
Rekabet skoru (0-100)
"""
if hhi < 1500:
# Düşük konsantrasyon (rekabetçi pazar) → YÜKSEK SKOR
return round(100 - (hhi / 15), 2)
elif hhi < 2500:
# Orta konsantrasyon → ORTA SKOR
return round(70 - ((hhi - 1500) / 10), 2)
else:
# Yüksek konsantrasyon (tekelci pazar) → DÜŞÜK SKOR
return round(max(0, 55 - ((hhi - 2500) / 50)), 2)