כיצד AI משנה את הגישה למכרזי זמן אמת (Real-Time Bidding)?
טעות אופיינית: מפרסם מציע הצעת מחיר קבועה של 5$ ל-CPM במכרז מחיר ראשון ותוהה מדוע eCPA עולה והתקציב נגמר תוך שעה. ללא מודלים חיזויים ו-bid shading, קמפיין RTB הוא ירייה בחושך. אופטימיזציית מכרזי זמן אמת המונעת על ידי AI לא רק חוזה CVR ו-CTR אלא גם מנהלת הצעות מחיר באופן דינמי כדי להעלות את שיעור הזכייה ולהוריד את ה-CPA.
אנו בונים מערכות AI הפותרות שלוש בעיות ב-100 מילישניות: האם להצטרף למכרז, מהי הצעת המחיר האופטימלית, וכיצד לחלק את התקציב בין קמפיינים. הפתרונות שלנו כוללים מודלים חיזויים, bid shading אדפטיבי, ו-auto-pacing המבוסס על דגימת תומפסון (Thompson Sampling). תוצאה: שיעור הזכייה גדל ב-15-35%, וה-eCPA יורד לטווח היעד.
כיצד AI מייעל הצעות מחיר ב-RTB
מערכת AI פועלת בשלוש רמות: בקשה, קמפיין, פורטפוליו. ברמת הבקשה, תוך <10ms, מתקבלת החלטה עבור כל בקשת הצעת מחיר: להצטרף או לא, ובאיזה מחיר. כאן נעשה שימוש במודלי CTR/CVR (gradient boosting או רשתות נוירונים) ובאלגוריתמי bid shading. ברמת הקמפיין — ניהול תקציב עם אסטרטגיות pacing המתאימות את עצמן לדפוסי תנועה יומיים. ברמת הפורטפוליו — חלוקת תקציב בין קמפיינים על בסיס ROI חזוי.
שקלו מקרה: לקוח מסחר אלקטרוני עם eCPA יעד של 10$ ותקציב יומי של 500$. נתונים היסטוריים: 200,000 מכרזים במשך שבועיים. פרסנו מערכת עם דגימת תומפסון ו-bid shading. במשך 3 שבועות, ה-eCPA ירד מ-12$ ל-9.8$, ושיעור הזכייה עלה מ-18% ל-24%. הסוד טמון בחקירת אסטרטגיות אדפטיבית: האלגוריתם בודק אוטומטית גישות שונות (שמרנית, אגרסיבית, מודעת לנראות) ובוחר את הטובה ביותר. דגימת תומפסון מקצרת את זמן הכוונון ב-40% בהשוואה לבדיקות A/B מסורתיות.
בסיס מתמטי
import numpy as np
from scipy import stats
from scipy.optimize import minimize_scalar
import pandas as pd
class OptimalBiddingStrategy:
""" Математически обоснованная стратегия ставок.
Базируется на теории механизмов аукционов и оптимальном управлении.
"""
def __init__(self, campaign_goal: str = 'cpa'):
"""
campaign_goal: 'cpa' | 'ctr' | 'roas' | 'awareness'
"""
self.goal = campaign_goal
def compute_bid_landscape(self, historical_auctions: pd.DataFrame, floor_price: float) -> dict:
""" Оценка конкурентного ландшафта аукциона.
historical_auctions: winning_price, floor_price, won (bool)
"""
winning_prices = historical_auctions[historical_auctions['won']]['winning_price']
if len(winning_prices) < 50:
return {'distribution': 'unknown', 'p50': floor_price * 2}
# Подбираем распределение победных цен
# Log-normal хорошо описывает цены в RTB
params = stats.lognorm.fit(winning_prices, floc=0)
dist = stats.lognorm(*params)
return {
'distribution': 'lognorm',
'params': params,
'p25': dist.ppf(0.25),
'p50': dist.ppf(0.50),
'p75': dist.ppf(0.75),
'p90': dist.ppf(0.90),
'mean': float(winning_prices.mean()),
}
def optimal_cpa_bid(self, predicted_cvr: float, target_cpa: float, bid_landscape: dict, budget_remaining: float, impressions_remaining: int) -> float:
""" Оптимальная ставка для цели CPA.
Максимизирует число конверсий при соблюдении eCPA <= target_cpa.
"""
# Valuation: сколько стоит одно впечатление для нас
valuation = predicted_cvr * target_cpa * 1000 # В CPM
if bid_landscape.get('distribution') == 'unknown':
return valuation * 0.7 # Консервативно без данных
# Для second-price auction: bid = valuation (dominant strategy)
# Для first-price: применяем bid shading
params = bid_landscape['params']
dist = stats.lognorm(*params)
def expected_profit(bid_cpm):
win_prob = dist.cdf(bid_cpm)
expected_payment = bid_cpm # First-price (мы платим свою ставку)
profit = win_prob * (valuation - expected_payment)
return -profit # Минус для минимизации
result = minimize_scalar(
expected_profit,
bounds=(0.01, valuation * 1.5),
method='bounded'
)
optimal_bid = result.x
# Корректировка на бюджетный дефицит
if impressions_remaining > 0:
avg_bid_needed = budget_remaining / impressions_remaining * 1000
# Не ставим выше среднего необходимого
optimal_bid = min(optimal_bid, avg_bid_needed * 2)
return round(float(optimal_bid), 4)
def compute_efficiency_frontier(self, bid_range: np.ndarray, cvr_model, bid_landscape: dict) -> pd.DataFrame:
""" Кривая эффективности: для каждого уровня ставки считаем ожидаемое число конверсий и стоимость за конверсию.
"""
results = []
params = bid_landscape.get('params')
if params is None:
return pd.DataFrame()
dist = stats.lognorm(*params)
for bid in bid_range:
win_prob = float(dist.cdf(bid))
expected_conversions_per_1k = win_prob * cvr_model.get('avg_cvr', 0.02)
cost_per_conversion = bid / max(expected_conversions_per_1k, 1e-6)
results.append({
'bid_cpm': bid,
'win_probability': round(win_prob, 3),
'expected_conversions_per_1k': round(expected_conversions_per_1k, 4),
'ecpa': round(cost_per_conversion, 2),
})
return pd.DataFrame(results)
class MultiObjectiveBidOptimizer:
""" Оптимизация ставок при нескольких целях одновременно.
Типичный сценарий: минимизировать CPA И удержать долю показов.
"""
def pareto_optimal_bid(self, predicted_ctr: float, predicted_cvr: float, weights: dict) -> float:
""" Взвешенная комбинация нескольких объективов.
weights: {'cpa': 0.6, 'reach': 0.2, 'viewability': 0.2}
"""
target_cpa = weights.get('target_cpa', 10.0)
reach_weight = weights.get('reach', 0.2)
# Базовая ценность от конверсий
conversion_value = predicted_ctr * predicted_cvr * target_cpa * 1000
# Бонус за охват (если цель = awareness)
reach_bonus = weights.get('reach_bonus_cpm', 0) * reach_weight
return conversion_value + reach_bonus
def adjust_for_viewability(self, base_bid: float, predicted_viewability: float, viewability_target: float = 0.70) -> float:
""" Снижаем ставку за невидимые показы.
Если viewability = 40% при цели 70% → понижающий коэф.
"""
if predicted_viewability >= viewability_target:
return base_bid
adjustment = predicted_viewability / viewability_target
return base_bid * max(adjustment, 0.5) # Минимум 50% от базовой
class BidThrottlingController:
""" Управление темпом участия в аукционах.
Цель: расходовать бюджет равномерно, не участвуя в каждом аукционе.
"""
def __init__(self, daily_budget: float, daily_impression_forecast: int):
self.daily_budget = daily_budget
self.daily_impressions = daily_impression_forecast
self.avg_cpm = daily_budget / daily_impression_forecast * 1000
def compute_participation_rate(self, spent_pct: float, time_elapsed_pct: float) -> float:
""" Процент bid requests, в которых участвуем.
spent_pct: доля бюджета, потраченная за сегодня
time_elapsed_pct: доля суток, прошедшая
"""
# Нормальный темп: spent_pct ≈ time_elapsed_pct
deviation = spent_pct - time_elapsed_pct
if deviation > 0.15:
# Тратим слишком быстро — жёсткий throttling
return max(0.3, 1.0 - deviation * 3)
elif deviation < -0.15:
# Тратим слишком медленно — агрессивное участие
return min(1.0, 1.0 + abs(deviation) * 2)
else:
return 1.0
def should_bid(self, request_id: str, participation_rate: float) -> bool:
"""Детерминированный sampling по request hash"""
hash_val = hash(request_id) % 10000 / 10000
return hash_val < participation_rate
מדוע Bid Shading קריטי למכרזי מחיר ראשון?
במכרזי מחיר ראשון, אתה משלם את הצעת המחיר שלך, לא את המחיר השני. ללא bid shading, אתה משלם יותר ב-15-30%. ה-bid shading האדפטיבי שלנו משתמש בהתפלגות היסטורית של מחירי זכייה (בדרך כלל לוג-נורמלית) ומוצא את הצעת המחיר שממקסמת את הרווח הצפוי. התוצאה היא חיסכון בתקציב של 15-25% באותו שיעור המרה — פי שניים יותר יעיל מגורם הנחה קבוע.
| גישה | חיסכון בתקציב | מורכבות יישום | סיכון להחמצת חשיפות |
|---|---|---|---|
| גורם הנחה קבוע | 5-10% | נמוכה | גבוה (הצעה עשויה להיות נמוכה מדי) |
| Bid shading אדפטיבי | 15-25% | בינונית | נמוך (מתאים את עצמו לשוק) |
כיצד להעלות את שיעור הזכייה עם דגימת תומפסון?
דגימת תומפסון היא גישת Bayesian multi-armed bandit המאזנת בין חקירה לניצול. אנו משתמשים בה כדי לבחור אסטרטגיות הצעות מחיר ברמת המכרז.
class BidExperimentManager:
""" Многорукий бандит для выбора оптимальной стратегии ставок.
Thompson Sampling: балансирует exploration vs exploitation.
"""
def __init__(self, strategies: list[str]):
self.strategies = strategies
# Beta распределение для каждой стратегии: (wins, losses)
self.alpha = {s: 1.0 for s in strategies}
self.beta = {s: 1.0 for s in strategies}
self.conversions = {s: 0 for s in strategies}
self.spend = {s: 0.0 for s in strategies}
def select_strategy(self) -> str:
"""Thompson Sampling: выбираем стратегию с наибольшим семплом"""
samples = {
s: np.random.beta(self.alpha[s], self.beta[s])
for s in self.strategies
}
return max(samples, key=samples.get)
def update(self, strategy: str, won: bool, converted: bool, spend: float):
"""Обновление статистики после аукциона"""
if won:
self.alpha[strategy] += int(converted)
self.beta[strategy] += int(not converted)
self.conversions[strategy] += int(converted)
self.spend[strategy] += spend
def get_strategy_stats(self) -> pd.DataFrame:
"""Текущая эффективность стратегий"""
rows = []
for s in self.strategies:
total = self.alpha[s] + self.beta[s] - 2
conv_rate = self.alpha[s] / (self.alpha[s] + self.beta[s])
cpa = self.spend[s] / max(self.conversions[s], 1)
rows.append({
'strategy': s,
'auctions_won': int(total),
'conversions': self.conversions[s],
'estimated_cvr': round(conv_rate, 4),
'ecpa': round(cpa, 2),
'confidence_lower': round(
np.percentile(
np.random.beta(self.alpha[s], self.beta[s], 10000),
5
),
4
),
})
return pd.DataFrame(rows).sort_values('ecpa')
אילו מדדים חשובים באופטימיזציית RTB?
| מדד | ערך אופייני | שיטת שיפור |
|---|---|---|
| שיעור זכייה | 15-35% | העלאת הצעות מחיר, צמצום טרגוט, שיפור מודל CVR |
| eCPA | יעד ± 20% | כיול מודל CVR, bid shading |
| ניצול תקציב | 85-95% | Pacing אדפטיבי |
| חלק חשיפות | מחושב | הרחבת טרגוט או העלאת הצעות מחיר |
| שיעור Bid Shading | חיסכון של 15-25% | אימון על נתונים היסטוריים |
המדד המרכזי הוא יעילות מקסימלית ב-eCPA היעד. מערכות עם bid shading חוסכות עד 25% תקציב במכרזי מחיר ראשון. אופק החזר השקעה של המודל הוא 2-4 שבועות בנפח של 50,000+ מכרזים ביום.
מה כלול בתוצרים
- תיעוד ארכיטקטורה — תיאורי מודלים, pipelines, חוזי API.
- מודלים מאומנים — מודלי CVR/CTR, bid shading ו-pacing מסודרים.
- קוד Pipeline — סקריפטים לאימון, walidacja ופריסה.
- לוחות מחוונים לניטור — Grafana + Prometheus למעקב אחר מדדים.
- הכשרת צוות הלקוח — סדנה ותיעוד תפעולי.
תהליך יישום מערכת AI RTB
- אנליטיקה — איסוף וניתוח נתונים היסטוריים (מכרזים, המרות, לוגים). הגדרת יעדים: eCPA, ROAS, ריץ' (reach).
- עיצוב — פיתוח ארכיטקטורה: מודלי הצעות מחיר, bid shading, pacing. בחירת מסגרת (PyTorch, HuggingFace, scikit-learn).
- פיתוח ואימון — אימון מודלי CVR/CTR, כיול, walidacja על נתונים היסטוריים.
- בדיקות — ניסוי A/B: אסטרטגיה חדשה מול נוכחית. ניטור מדדים מרכזיים.
- פריסה — אינטגרציה עם פלטפורמת RTB דרך API, הגדרת ניטור והתראות.
טעויות נפוצות באופטימיזציית RTB
- התעלמות מנראות (viewability): הצעות מחיר על חשיפות שאינן נראות מבזבזות תקציב. המודלים שלנו מתאימים הצעות מחיר על בסיס נראות חזויה.
- שימוש במכרז מחיר ראשון ללא bid shading: אתה משלם יותר ב-15-30%. אנו מיישמים bid shading אדפטיבי המבוסס על התפלגות מחירי זכייה.
- נתונים היסטוריים לא מספקים: מודלים זקוקים לפחות ל-50,000 מכרזים ביום לביצועים יציבים. פחות מכך — אנו משתמשים בגישות Bayesian.
- בחירת מדד אופטימיזציה שגוי: CTR לא תמיד מתאם עם המרות. אנו מייעלים ישירות ל-eCPA או ROAS.
לוחות זמנים ותמחור
לוחות הזמנים לפיתוח ויישום נעים בין 4 ל-8 שבועות, תלוי במורכבות האינטגרציה ובאיכות הנתונים. התמחור מחושב באופן אישי על בסיס נפח מכרזים, מספר קמפיינים ודיוק המודל הנדרש. אנו מבטיחים שקיפות: אתה מקבל מפרט ברור ומסירה בשלבים של תוצאות.
מוכן לשפר את ביצועי קמפיין ה-RTB שלך? בקש ביקורת של האסטרטגיה הנוכחית שלך — זה לוקח לא יותר משעה. קבל ייעוץ ממהנדס שבאמת מבין RTB.
נתונים המבוססים על 15+ פרויקטים במסחר אלקטרוני, פינטק וגיימינג. למידע נוסף, עיין בתיעוד Real-Time Bidding.







