אימון סוכן RL (PPO/SAC/DQN) לאסטרטגיית מסחר
תארו לעצמכם: השקעתם חודשים באימון סוכן DQN על נתונים היסטוריים, רק כדי שיפסיד כסף בשוק החי עקב החלקה שלא נלקחה בחשבון. באחד הפרויקטים שלנו, לקוח הגיע עם בעיה דומה: הם אימנו PPO על נרות של דקה, והשיגו יחס שארפ של 1.8 בבדיקות, אבל במסחר חי המשיכה הגיעה ל-40%. הלקוח הפסיד כ-15,000 דולר בחודש בגלל החסרונות הללו. גילינו שהסביבה לא לקחה בחשבון עמלות ונזילות. לאחר כיול התגמול והוספת אימות walk-forward, יחס השארפ חזר ל-1.5 והמשיכה ירדה ל-12%. זה חסך 4,000 דולר בחודש.
עיצוב סוכן RL למסחר בקריפטו אינו רק בחירת אלגוריתם. אתם מתמודדים עם אי-נייחות שוק, עמלות נסתרות, החלקה וסיכון של התאמת יתר. אנחנו לוקחים על עצמנו את כל המחזור—מבניית צינור הנתונים ועד מסחר חי. אנו משתמשים באלגוריתמים מוכחים PPO, SAC ו-DQN, ומתאימים אותם לאסטרטגיה שלכם. הניסיון שלנו: למעלה מחמש שנים בפיתוח בלוקצ'יין, 15+ פרויקטים ל-DeFi ו-CEX, כולל אינטגרציה עם Binance API. צרו קשר לניתוח מפורט של האסטרטגיה שלכם.
שלושה אלגוריתמים עובדים: DQN, PPO, SAC
לכל אלגוריתם יש נישה משלו. בואו נבחן את החוזקות שלהם ואת מקרי השימוש האופייניים.
DQN (Deep Q-Network)
מתאים לפעולות בדידות (קנייה/החזקה/מכירה) ולאסטרטגיות פשוטות. DQN מקרב את פונקציית Q: Q(state, action) — התגמול הדיסקונטי הצפוי עבור נקיטת פעולה במצב נתון.
import torch
import torch.nn as nn
from collections import deque
import random
class DQNNetwork(nn.Module):
def __init__(self, state_dim, n_actions, hidden_dim=256):
super().__init__()
# Dueling architecture: отдельные Value и Advantage потоки
self.shared = nn.Sequential(
nn.Linear(state_dim, hidden_dim),
nn.ReLU(),
nn.Linear(hidden_dim, hidden_dim),
nn.ReLU()
)
self.value_stream = nn.Linear(hidden_dim, 1)
self.advantage_stream = nn.Linear(hidden_dim, n_actions)
def forward(self, x):
shared = self.shared(x)
value = self.value_stream(shared)
advantage = self.advantage_stream(shared)
# Dueling: Q = V + (A - mean(A))
q_values = value + (advantage - advantage.mean(dim=1, keepdim=True))
return q_values
class PrioritizedReplayBuffer:
"""Prioritized Experience Replay — чаще семплируем важные transitions"""
def __init__(self, capacity=50000, alpha=0.6):
self.buffer = deque(maxlen=capacity)
self.priorities = deque(maxlen=capacity)
self.alpha = alpha
def push(self, state, action, reward, next_state, done, td_error=1.0):
priority = (abs(td_error) + 1e-5) ** self.alpha
self.buffer.append((state, action, reward, next_state, done))
self.priorities.append(priority)
def sample(self, batch_size, beta=0.4):
probs = np.array(self.priorities) / sum(self.priorities)
indices = np.random.choice(len(self.buffer), batch_size, p=probs)
# Importance sampling weights
weights = (len(self.buffer) * probs[indices]) ** (-beta)
weights /= weights.max()
batch = [self.buffer[i] for i in indices]
return batch, indices, weights
Double DQN מבטל הערכת יתר של ערכי Q: הרשת המקוונת בוחרת את הפעולה, והרשת המטרה מעריכה אותה.
# Double DQN target calculation
with torch.no_grad():
next_actions = online_net(next_states).argmax(dim=1) # online net выбирает
next_q = target_net(next_states).gather(1, next_actions.unsqueeze(1)) # target оценивает
targets = rewards + gamma * next_q * (1 - dones) PPO (Proximal Policy Optimization)
מתאים גם לפעולות בדידות וגם רציפות, on-policy, אימון יציב. PPO מגביל את גודל עדכון המדיניות באמצעות clipping.
class PPOActor(nn.Module):
def __init__(self, state_dim, action_dim, hidden_dim=256):
super().__init__()
self.network = nn.Sequential(
nn.Linear(state_dim, hidden_dim),
nn.Tanh(),
nn.Linear(hidden_dim, hidden_dim),
nn.Tanh()
)
self.policy_head = nn.Linear(hidden_dim, action_dim)
self.value_head = nn.Linear(hidden_dim, 1)
def forward(self, x):
features = self.network(x)
logits = self.policy_head(features)
value = self.value_head(features)
return logits, value
def ppo_update(model, optimizer, states, actions, old_log_probs, advantages, returns, clip_eps=0.2, n_epochs=4):
for _ in range(n_epochs):
logits, values = model(states)
dist = torch.distributions.Categorical(logits=logits)
new_log_probs = dist.log_prob(actions)
entropy = dist.entropy()
# PPO clipped objective
ratio = (new_log_probs - old_log_probs).exp()
surr1 = ratio * advantages
surr2 = torch.clamp(ratio, 1 - clip_eps, 1 + clip_eps) * advantages
actor_loss = -torch.min(surr1, surr2).mean()
critic_loss = (returns - values.squeeze()).pow(2).mean()
entropy_loss = -entropy.mean()
total_loss = actor_loss + 0.5 * critic_loss + 0.01 * entropy_loss
optimizer.zero_grad()
total_loss.backward()
torch.nn.utils.clip_grad_norm_(model.parameters(), 0.5)
optimizer.step()
SAC (Soft Actor-Critic)
מתאים למרחב פעולה רציף (מיקום 0%–100% מההון), off-policy, יעילות דגימה מקסימלית. SAC ממקסם: import torch import torch.nn as nn from collections import deque import random class DQNNetwork(nn.Module): def __init__(self, state_dim, n_actions, hidden_dim=256): super().__init__() # Dueling architecture: отдельные Value и Advantage потоки self.shared = nn.Sequential( nn.Linear(state_dim, hidden_dim), nn.ReLU(), nn.Linear(hidden_dim, hidden_dim), nn.ReLU() ) self.value_stream = nn.Linear(hidden_dim, 1) self.advantage_stream = nn.Linear(hidden_dim, n_actions) def forward(self, x): shared = self.shared(x) value = self.value_stream(shared) advantage = self.advantage_stream(shared) # Dueling: Q = V + (A - mean(A)) q_values = value + (advantage - advantage.mean(dim=1, keepdim=True)) return q_values class PrioritizedReplayBuffer: """Prioritized Experience Replay — чаще семплируем важные transitions""" def __init__(self, capacity=50000, alpha=0.6): self.buffer = deque(maxlen=capacity) self.priorities = deque(maxlen=capacity) self.alpha = alpha def push(self, state, action, reward, next_state, done, td_error=1.0): priority = (abs(td_error) + 1e-5) ** self.alpha self.buffer.append((state, action, reward, next_state, done)) self.priorities.append(priority) def sample(self, batch_size, beta=0.4): probs = np.array(self.priorities) / sum(self.priorities) indices = np.random.choice(len(self.buffer), batch_size, p=probs) # Importance sampling weights weights = (len(self.buffer) * probs[indices]) ** (-beta) weights /= weights.max() batch = [self.buffer[i] for i in indices] return batch, indices, weights . מונח האנטרופיה H מעודד חקר.
class SACActorContinuous(nn.Module):
def __init__(self, state_dim, action_dim, hidden_dim=256):
super().__init__()
self.network = nn.Sequential(
nn.Linear(state_dim, hidden_dim),
nn.ReLU(),
nn.Linear(hidden_dim, hidden_dim),
nn.ReLU()
)
self.mean_head = nn.Linear(hidden_dim, action_dim)
self.log_std_head = nn.Linear(hidden_dim, action_dim)
def forward(self, x):
features = self.network(x)
mean = self.mean_head(features)
log_std = self.log_std_head(features).clamp(-20, 2)
std = log_std.exp()
dist = torch.distributions.Normal(mean, std)
action = dist.rsample() # reparameterization trick
# Squash to [-1, 1]
action_tanh = torch.tanh(action)
log_prob = dist.log_prob(action) - torch.log(1 - action_tanh.pow(2) + 1e-6)
return action_tanh, log_prob.sum(-1, keepdim=True) איזה אלגוריתם לבחור לאסטרטגיה שלכם?
הבחירה תלויה במרחב הפעולה ובדרישות יעילות הדגימה. אם האסטרטגיה שלכם משתמשת רק באותות בדידים (קנייה/מכירה/החזקה), DQN עם dueling ו-PER ייתן תוצאות יציבות. לניהול הון רציף (למשל, אחוז תיק), SAC הוא ללא תחרות: הוא יעיל פי 2–3 בדגימה מ-PPO. PPO הוא בחירה אוניברסלית כשאתם צריכים אמינות וקלות כוונון.
לעתים קרובות אנו משלבים אלגוריתמים בארכיטקטורת multi-agent: סוכן-מאקרו מבוסס DQN קובע את הכיוון הכללי, וסוכן-מיקרו מבוסס SAC מבצע עסקאות. זה מפחית שונות ומשפר את יחס השארפ ב-15–30%.
מדוע פונקציית תגמול נכונה חשובה?
עיצוב תגמול הוא שלב מפתח שקובע את התנהגות הסוכן. טעויות אופייניות: הסוכן לומד לצבור רווח לא ממומש (ללא התחשבות בהחלקה) או מתחיל לסחור לעתים רחוקות מאוד כדי להימנע מעמלות. אנו משתמשים בתגמול רב-רכיבי: PnL, קנס על משיכה, עמלות וספרד. לדוגמה, # Double DQN target calculation with torch.no_grad(): next_actions = online_net(next_states).argmax(dim=1) # online net выбирает next_q = target_net(next_states).gather(1, next_actions.unsqueeze(1)) # target оценивает targets = rewards + gamma * next_q * (1 - dones) . מקדמי λ נבחרים כדי לדמות תנאים ריאליסטיים.
בפרויקט DeFi אחד, תגמול שגוי הוביל את הסוכן לפתוח מאות מיקרו-עסקאות, ויצר הפסד מעמלות. לאחר עיצוב מחדש של התגמול (קנס על מספר העסקאות), הסוכן הפך לרווחי.
השוואת אלגוריתמים למסחר בקריפטו
| אלגוריתם | מרחב פעולה | יעילות דגימה | יציבות | מקרה שימוש מומלץ |
|---|---|---|---|---|
| DQN | בדיד | בינוני | בינוני | אסטרטגיות קנייה/מכירה פשוטות |
| PPO | שניהם | נמוך (on-policy) | גבוה | לשימוש כללי, אמין |
| SAC | רציף | גבוה | גבוה | קביעת גודל פוזיציה כפעולה |
כיצד להגדיר אימון סוכן RL: תוכנית שלב-אחר-שלב
- הגדירו את מרחב הפעולה ומרחב המצב. לפעולות בדידות (קנייה/מכירה/החזקה), DQN מתאים; למיקום רציף, SAC. המצב כולל מחירים, נפחים, אינדיקטורים.
- עצבו את פונקציית התגמול. קחו בחשבון PnL, עמלות, החלקה, קנס על משיכה.
- בחרו את האלגוריתם וארכיטקטורת הרשת הנוירונית. אנו משתמשים ב-dueling DQN, PPO עם clipping, SAC עם כוונון אנטרופיה אוטומטי.
- אימון עם אימות. אנו מיישמים אימות walk-forward עם 36 חלונות נעים ועצירה מוקדמת.
- בדיקה על נתונים מחוץ למדגם. העריכו יחס שארפ, משיכה מקסימלית, יציבות תגמול.
אתגרים אופייניים וכיצד אנו פותרים אותם
אי-נייחות שוק — סוכן שאומן על שוק רגוע עלול להיכשל בתנודתיות גבוהה. כפי שצוין ב-מפרט למידת חיזוק, שינוי התפלגות הוא אתגר רציני. אנו משתמשים ב-curriculum learning: הגדלת תנודתיות הסביבה בהדרגה, ובפרודקשן — כוונון רציף עם גלאי סחיפה.
הנדסת תגמול (Reward hacking) — תגמולים מנופחים באופן מלאכותי. הגנה באמצעות clipping של תגמול ושימוש בסימולטור ריאליסטי עם נתוני שוק (רמה 2, נרות היסטוריים).
התאמת יתר — שינון על ידי הסוכן. אנו משתמשים באימות walk-forward עם 36 חלונות נעים ובדיקה על תקופות מוחרגות לחלוטין (מחוץ למדגם).
דוגמה לכוונון היפרפרמטרים
עבור PPO, אנו מכוונים קצב למידה (3e-4), clip epsilon (0.2), מקדם אנטרופיה (0.01) באמצעות אופטימיזציה בייסיאנית על 50 ניסויים. התצורות הטובות ביותר נשמרות ב-MLflow. זמן חיפוש אופייני הוא יומיים על GPU.מה כלול בעבודה
- ניתוח אסטרטגיה והכנת צינור נתונים.
- עיצוב סביבה מותאמת אישית (gymnasium) תוך התחשבות בעמלות, החלקה ומשיכות.
- בחירת אלגוריתם וארכיטקטורת רשת נוירונית.
- אימון עם כוונון היפרפרמטרים (חיפוש רשת/אקראי, אופטימיזציה בייסיאנית).
- אימות walk-forward ועמידות לשינויי משטר שוק.
- אינטגרציה עם API של ברוקר (Binance, Bybit, KuCoin).
- תיעוד, הכשרת הצוות שלכם, תמיכה ל-3 חודשים.
צרו קשר כדי שנוכל לנתח את האסטרטגיה שלכם. אנו מבטיחים איכות תוצאה ותמיכה בכל השלבים.
לוחות זמנים ושלבים משוערים
| שלב | משך | תוצאה |
|---|---|---|
| ניתוח וצינור נתונים | 1–2 שבועות | נתונים מוכנים, מפרט סביבה |
| עיצוב סביבה ואלגוריתם | 1–2 שבועות | סביבה מותאמת אישית, מודל בסיסי |
| אימון וכוונון היפרפרמטרים | 2–4 שבועות | מדיניות אופטימלית, מדדים ב-MLflow |
| אימות walk-forward ובדיקות | 1–2 שבועות | דוח על שארפ, משיכה, מחוץ למדגם |
| אינטגרציה ופריסה | 1–2 שבועות | סוכן מסחר חי, תיעוד |
הזמינו ייעוץ — נבחר את האלגוריתם והארכיטקטורה למשימה שלכם. נעריך את הפרויקט בחינם תוך 2 ימי עסקים.







