pandas למסחר — הפונקציות שכל בוט צריך
pandas למסחר אלגוריתמי: הפונקציות המרכזיות לחישוב אינדיקטורים, זיהוי איתותים, וניתוח תוצאות Backtesting — עם דוגמאות קוד לכל אחת.
pandas היא ספריית עיבוד הנתונים המרכזית של פייתון, והכלי היומיומי הכי חשוב לבניית בוט מסחר — כמעט כל שלב, מחישוב אינדיקטורים ועד ניתוח תוצאות Backtesting, עובר דרכה. המדריך הזה מכסה את הפונקציות שבפועל חוזרות בכל אסטרטגיה, בלי להיכנס לכל ה-API הענק של הספרייה.
rolling() — ממוצעים נעים ואינדיקטורים
df["ma20"] = df["Close"].rolling(20).mean()
df["ma50"] = df["Close"].rolling(50).mean()
df["volatility"] = df["Close"].rolling(20).std()
rolling(N) מחשב חלון נע של N שורות אחורה — קריטי לכך שהחישוב לא "מסתכל קדימה" (ראו Look-ahead Bias). כל אינדיקטור מבוסס-חלון (ממוצע נע, סטיית תקן, ATR) עובר דרך rolling().
shift() — הזזת נתונים כדי למנוע Look-ahead Bias
df["prev_close"] = df["Close"].shift(1) # מחיר הסגירה של היום הקודם
df["signal"] = df["Close"].shift(1) > df["ma20"].shift(1) # החלטה על סמך נתונים ידועים בלבד
shift() היא כנראה הפונקציה הכי קריטית למניעת Look-ahead Bias בבקטסט: היא מזיזה נתונים אחורה בזמן, כך שההחלטה בכל שורה מבוססת רק על מה שהיה ידוע לפני אותה שורה.
diff() ו-pct_change() — שינויים ותשואות
df["daily_change"] = df["Close"].diff() # שינוי מוחלט
df["daily_return"] = df["Close"].pct_change() # שינוי באחוזים
df["cumulative_return"] = (1 + df["daily_return"]).cumprod() - 1
pct_change() היא נקודת ההתחלה לכל חישוב תשואה — ומשם ל-Sharpe Ratio ולעקומת התשואה המצטברת.
cummax() ו-Drawdown
equity_curve = (1 + df["daily_return"]).cumprod()
running_max = equity_curve.cummax()
drawdown = (equity_curve - running_max) / running_max
max_drawdown = drawdown.min()
cummax() מחזיר את הערך המקסימלי המצטבר עד לכל נקודה — בדיוק מה שצריך כדי לחשב Max Drawdown: הפער בין השווי הנוכחי לשיא הקודם.
where() — תנאים בלי לולאות
df["gain"] = df["Close"].diff().where(df["Close"].diff() > 0, 0)
df["loss"] = -df["Close"].diff().where(df["Close"].diff() < 0, 0)
where() מאפשר לוגיקה מותנית וקטורית — הרבה יותר מהיר מלולאת for על כל שורה, וזה חשוב כשבודקים אסטרטגיה על שנים של נתונים.
merge() ו-concat() — שילוב מקורות נתונים
combined = df.merge(fundamentals_df, on="date", how="left")
all_stocks = pd.concat([aapl_df, msft_df, googl_df], keys=["AAPL", "MSFT", "GOOGL"])
שימושי כששילוב בין נתוני מחיר (מ-yfinance) לנתונים נוספים — נתונים פונדמנטליים, סנטימנט, או מדדים חיצוניים.
סיכום — סדר הפעולות הטיפוסי
df = yf.download("AAPL", period="2y") # 1. משיכת נתונים
df["ma20"] = df["Close"].rolling(20).mean() # 2. חישוב אינדיקטורים
df["signal"] = df["Close"].shift(1) > df["ma20"].shift(1) # 3. איתותים בלי Look-ahead Bias
df["returns"] = df["Close"].pct_change() # 4. תשואות
equity = (1 + df["returns"]).cumprod() # 5. עקומת הון מצטברת
שאלות נפוצות
האם צריך ללמוד את כל pandas כדי לבנות בוט מסחר?
לא. הפונקציות שמכוסות במדריך הזה — rolling, shift, pct_change, cummax, where — מכסות את רוב הצרכים היומיומיים של בניית ובדיקת אסטרטגיה. אפשר ללמוד את השאר לפי הצורך.
מה ההבדל בין diff() ל-pct_change()?
diff() מחזיר את השינוי המוחלט (בדולרים או בכל יחידה שהנתונים בה). pct_change() מחזיר את השינוי היחסי באחוזים — לרוב מה שרוצים כשמחשבים תשואות ומדדי סיכון.
למה חשוב להשתמש ב-shift() ולא סתם להשוות עמודות?
בלי shift(), השוואה בין df["Close"] ל-df["ma20"] באותה שורה משתמשת בשני ערכים שנודעו רק בסוף אותו יום מסחר — מה שיוצר Look-ahead Bias. shift(1) מבטיח שההחלטה מבוססת על נתונים שכבר היו ידועים במלואם לפני הרגע שבו היא מתקבלת.
האם pandas מספיק מהיר לבקטסט על נתונים גדולים?
לרוב כן, במיוחד עם פעולות וקטוריות (כמו rolling, where) במקום לולאות for איטיות. לבדיקות מאוד גדולות (אלפי מניות, נתוני דקה על שנים רבות) שווה לשקול ספריות מיוחדות כמו vectorbt שמותאמות לביצועים.