פיתוח מנוע בקטסטינג ב-JavaScript עבור מטבעות קריפטוגרפיים

חישובים על היסטוריה אינם תואמים לתוצאות אמיתיות, ובדיקת אסטרטגיה נמשכת שעות. אנו מפתחים מנוע בקטסטינג ב-JavaScript כפתרון מקצה לקצה: מעבירים את החישובים לנתונים אמיתיים ומקצרים את זמן בדיקת האסטרטגיה פי כמה.

שירותי פיתוח בלוקצ'יין

שאלות נפוצות

העבודות האחרונות

  • פיתוח אפליקציית ווב עבור FEEDME
    פיתוח אפליקציית ווב עבור FEEDME
    1359
  • פיתוח חנות מקוונת לחברת FURNORO
    פיתוח חנות מקוונת לחברת FURNORO
    1330
  • עיצוב לוגו לחברת B2B Advance
    עיצוב לוגו לחברת B2B Advance
    776
  • פיתוח אפליקציית ווב עבור Enviok
    פיתוח אפליקציית ווב עבור Enviok
    1077
  • פיתוח לוגו חברת AIDER
    פיתוח לוגו חברת AIDER
    1022
  • פיתוח CRM עבור Chasseurs
    פיתוח CRM עבור Chasseurs
    1113

מדוע בקטסטינג ב-JavaScript נשבר על נתונים אמיתיים

הרצה עצמית של אסטרטגיה נראית משכנעת עד ההשוואה הראשונה ליומן העסקאות האמיתיות. הפער מול העסקאות האמיתיות נוצר לא בגלל טעות בנוסחה, אלא בגלל הנחות שלא נרשמו בקוד.

הראשון — מודל ביצוע ההזמנות. כאשר הזמנת שוק מתבצעת במחיר הסגירה של הנר, והזמנת לימיט בנגיעה ברמה, המנוע מעניק לאסטרטגיה באופן מרומז מחיר טוב מזה שהיא תקבל בספר ההזמנות. מחוץ לתמונה נשארים סליפג', ביצוע חלקי ותור הזמנות באותה רמת מחיר.

השני — נתונים. מערכים גדולים של היסטוריה במימוש נאיבי נטענים לזיכרון בשלמותם ועוברים בלולאה אחת. על פני כמה שנים של נרות דקה זה כבר לא נכנס לזיכרון המוקצה: ההרצה מאטה, אחר כך נתקעת, והתוצאות בין הרצות הופכות לבלתי ניתנות להשוואה.

השלישי — הצצה בלתי מורגשת אל העתיד. אינדיקטור שחושב על פני כל הסדרה בבת אחת כבר יודע, עד לרגע האות, את הציטוטים הבאים; כך גם קורה בחישוב מחדש על הרכב נתונים שהשתנה, בשינוי אזור זמן ובפערים בהיסטוריה.

לכן בקטסטינג ב-JavaScript מתחיל לא בלולאה על הנרות, אלא בתיאור מודל השוק: כללי ביצוע, עמלות, מגבלות נזילות, סדר טעינת ההיסטוריה. נבחן כיצד זה נסגר במנוע לבדיקת אסטרטגיות.

מה נותן מנוע בקטסטינג עצמאי ב-JavaScript

כל עוד מערך האסטרטגיות מחושב בשירות חיצוני או בסקריפט בעל תהליך אחד, מחזור בדיקת ההשערה נמתח לשעות. מנוע ב-JavaScript/TypeScript חי באותו runtime שבו חיה הלוגיקה המסחרית, ומפזר את ההרצות על ליבות התהליך: מערך של עשרות קונפיגורציות מחושב בדקות. ההבדל אינו ב«אופטימיזציה», אלא בכך שהחוקר מספיק לבדוק עשרה וריאנטים של פרמטרים לפני שאיבד את החוט.

חישוב חוזר על ההיסטוריה נשען על מטמון הנרות הטעונים ועל חישוב אינקרמנטלי: בעת תיקון של כלל אחד מחושבים מחדש רק הקטעים והעסקאות שנפגעו. הרצה מלאה נדרשת רק בשינוי מערך הנתונים או לוגיקת הביצוע, ולא בכל איטרציה. עריכת אסטרטגיה מפסיקה להיות פעולה יקרה.

יכולת השחזור נשענת על snapshot קבוע של נתוני השוק, על מודל מעוגן של עמלות וסליפג', ועל seed שמור של מחולל המספרים האקראיים. אותה הרצה, שחוזרת כעבור חודש או על מכונה אחרת, מניבה עקומת תשואה זהה ורשימת עסקאות זהה.

יחד עם זה נעלם סוג של כשלים, שבו אסטרטגיה נראית עובדת על ההיסטוריה רק בגלל פער בנתונים או התאמה בלתי מורגשת לעבר.

את עלות זמן ההמתנה של החישובים בדרך כלל מזלזלים בה: כל עוד מחושב וריאנט אחד, תור ההשערות עומד, והחלטות מתקבלות על בסיס תמונה מיושנת. כאשר ההרצה אורכת דקות, רעיונות שנויים במחלוקת נפסלים על ההיסטוריה, ולא על חשבון חי.

גישות לחישוב: אירועי, וקטורי וזרימתי

בחירת מצב החישוב קובעת עד כמה התנהגות האסטרטגיה על ההיסטוריה תתאים להתנהגותה בשטח. חישוב וקטורי מעבד את כל סדרת הציטוטים בפעולה אחת: הוא מהיר ונוח לסינון ראשוני של השערות, אך אינו משחזר את סדר ההזמנות בתוך הנר ומחליק על פני חציות של סטופ ויעד. חישוב אירועי מריץ את הנתונים אירוע אחר אירוע — זהו אותו סדר כמו במצב בדיקת אסטרטגיות בשוק חי.

הדרישות לנתונים היסטוריים שונות בין המצבים.

הווקטורי זקוק לסדרות מיושרות באותה תדירות וללא פערים, האירועי — לחותמות זמן תקינות ולמקורות לא מסונכרנים, ועיבוד זרימה של ציטוטים מציב את התנאים המחמירים ביותר: סדר ותבנית הרשומות חייבים להתאים לאלה של הבורסה, כולל קיטועים ופרסומים חוזרים.

מצב מתי מתאים מגבלות
חישוב וקטורי מעבר המוני על השערות, אסטרטגיות אינדיקטוריות ותיקיות על היסטוריה ארוכה אינו מדמה אירועים תוך-נריים, מנפח את התוצאה באסטרטגיות עם סטופים
חישוב אירועי הזמנות, ביצועים חלקיים, עבודה על כמה כלים במקביל מחשב לאט יותר, דורש נתונים מלאים על הזמנות ועמלות
עיבוד זרימה של ציטוטים השוואה מול זרימה חיה והשמעה חוזרת של סשן מוקלט שגיאה בנתונים עוברת ללא אזהרה, נדרש מעגל בקרה נפרד

בפועל המצבים אינם מתחרים: את ההשערות מסננים בחישוב וקטורי, את המועמדים הסופיים מריצים בחישוב אירועי ומשווים להשמעה זורמת. אז הפער בין ההיסטוריה למציאות נמדד מראש, ולא מתגלה על החשבון.

שלבי פיתוח המנוע לבדיקת אסטרטגיות מסחר

סדר העבודה בנוי כך שאת התוצאה של כל שלב ניתן לבדוק לפני המעבר לשלב הבא. בדיקת אסטרטגיות על ההיסטוריה היא בראש ובראשונה שאלה של יכולת שחזור: אותו מערך נתונים ואותו קוד חייבים להניב דוח זהה ללא תלות במכונה ובזמן ההרצה. אם אין זאת, כל מסקנה לגבי רווחיות האסטרטגיה אינה שווה דבר.

  1. ביקורת מעגל החישוב. נבחן כיצד התוצאות מחושבות כיום: היכן אובדת היסטוריית העסקאות, האם נלקחות בחשבון עמלות וסליפג', והאם קיימת הצצה לנתוני עתיד ביחס לרגע הכניסה.
  2. תכנון סכמת הנתונים. מגדירים את תבנית האחסון של ציטוטים ועסקאות, את כללי האיחוד של טיימפריימים שונים, ואת ניהול הגרסאות של המערכים, כדי שניתן יהיה לחזור על הרצה ישנה כעבור חודשים.
  3. הגדרת סביבת החישובים. מקבעים את מקור הזמן, מבודדים תלויות, ומשיגים דוח זהה בהרצה מקומית ובהרצה על שרת.
  4. מימוש הליבה. כותבים מעבד לזרימת הציטוטים, חישוב מדדים ודיווח; הליבה נשארת נקייה, בלי הצמדות למקור נתונים מסוים.
  5. מערכי נתונים לבקרה. מכינים הרצות ייחוס עם תוצאה ידועה מראש: פער במספר העסקאות או בעקומה הסופית הוא אות חוסם, ולא סיבה להמשיך.
  6. מסירת המנוע לצוות. מוסרים קונפיגורציות, תיאור סכמת הנתונים, תקנון תחזוקה ונוהל הוספת כלים חדשים, ומקיימים סקירה עם המהנדסים שלכם.

בסיום מקבל הצוות לא חישוב חד-פעמי, אלא כלי שאפשר לתת בו אמון בעת השוואת אסטרטגיות: פערים בדוחות מוסברים על ידי לוגיקת האסטרטגיה, ולא על ידי התנהגות המנוע עצמו.

מה נשאר במאגר לאחר מסירת המנוע

אנחנו מוסרים לא «קוד ושיחת זום», אלא מאגר עבודה שבו הצוות שלכם ממשיך לעבוד בלעדינו. להלן מה שנמצא בענף ברגע המסירה ולשם מה נדרש כל ארטיפקט.

  • קונפיגורציות סביבה — מערכים נפרדים לסביבה מקומית, לטסט ולסביבת עבודה: מקורות ציטוטים, מגבלות הרצות מקבילות, נתיבים לאחסון התוצאות. סודות נטענים ממשתני סביבה ואינם נכנסים למאגר.
  • סכמת נתוני החישובים — ישויות של נרות, עסקאות, פקודות והרצות עם סוגי שדות וקשרים. מדד חדש משתלב בה בלי עריכת טבלאות קיימות.
  • מדיניות גישה לנתונים — תפקידים לשירותים ולאנשים: קריאת היסטוריה, כתיבת תוצאות, גישה למפתחות מסחר. מפתחות מחוברים לקריאה בלבד.
  • תקנון עדכון ההיסטוריה — כיצד נטענים נרות חסרים, במה נבדקים קיטועים וכפילויות, ובאיזה סדר מתבצע החישוב מחדש. הרצה חלקית מסומנת במפורש, ולא מוצגת כתוצאה.
  • תיעוד המנוע — נקודות הרחבה עם דוגמאות ב-JavaScript וב-TypeScript: כיצד להוסיף אינדיקטור, סוג פקודה, מודל עמלות וסליפג'.
  • טסטים והרצות ייחוס — מערך נתונים קבוע ומדדים צפויים, שלפיהם רואים שאחרי עריכות התוצאה לא זזה.
  • הוראות הרצה וחזרה לאחור — כיצד להעלות את המנוע מאפס ולחזור לגרסה הקודמת.

סקירה של המאגר מתבצעת בסוף הפרויקט: עוברים עם הצוות שלכם על כל ארטיפקט ומראים היכן מה לשנות.

מקרה בוחן: החישובים הואצו, הפערים בדוחות נעלמו

הלקוח — צוות למסחר כמותי בקריפטו — חישב אסטרטגיות באמצעות מערך של סקריפטים מפוזרים: ההיסטוריה נמשכה ממקורות שונים, עמלות וסליפג' נלקחו בחשבון ידנית, והדוח החודשי התאים לדף החשבון מהבורסה רק לאחר עריכות בגיליון. הרצה אחת על היסטוריה ארוכה ארכה שעות, ולכן ההשערות נבדקו לעיתים רחוקות ובמקבצים גדולים.

הרכבנו מנוע אחיד ב-JavaScript וב-TypeScript: שכבת הטעינה ממירה ציטוטים ממקורות שונים לסכמה אחת, מודול החישוב משחזר את סדר האירועים בתוך הנר, ומודל העסקה לוקח בחשבון עמלה, סליפג' וביצועים חלקיים.

את ההיסטוריה לוקחים דרך CoinGecko וארכיונים של בורסות, ואת תוצאות ההרצות מאחסנים במאגר ביניים — חישוב חוזר על אותם נתונים אינו מתחיל מאפס.

מה השתנה במדידות

  • זמן ההרצה על היסטוריה של שנים רבות — משעות לדקות על אותו מערך נתונים;
  • שיעור הפערים מול העסקאות האמיתיות — מעשירית מהעסקאות למקרים בודדים;
  • עריכות ידניות בדוחות — מעשרות שורות לדוח עד אפס.

את יציבות החישובים סגרנו בנפרד: מערך קבוע של תקופות היסטוריה מורץ לפני כל שינוי, והתוצאה מושווית לעסקאות בפועל לפי יומן הביצועים. אם הפער גבוה מהסף, הבנייה לא עוברת — דוח עם תשואה שגויה לא יכול לצאת בטעות.

במה שונה הבדיקה על ההיסטוריה ממסחר בדמו?

הבדיקה על ההיסטוריה, כלומר הבקטסטינג, מריצה את אותה זרימת ציטוטים שוב ושוב, ולכן יכולת השחזור של ההרצות כאן מלאה: אותם נתוני קלט מניבים את אותו מערך עסקאות.

מכאן גם השליטה בתנאי החישוב — עמלות, פאנדינג, סליפג', כללי ההפעלה של הזמנות לימיט ורגע ההגשה מוגדרים במפורש ונשמרים יחד עם גרסת הלוגיקה, כך שעריכות באסטרטגיה מושוות על אותו קטע בדיוק.

הצד השני של המטבע — ההנחות של מודל הביצוע. אם הזמנה מבוצעת במחיר הסגירה של הנר, בחישוב אין תור הזמנות, ביצוע חלקי והשהיית רשת, והתוצאה סוטה מהמציאות ככל שהמסחר צפוף יותר. תוסיפו כלים שנשרו מהמדגם לאחר דליסטינג, ופערים בנתונים — והחישוב יציג יציבות במקום שאין כזו.

מצב המסחר המדגמי נותן משהו אחר: זרימה חיה ומעגל ביצוע אמיתי. כאן רואים את מגבלות הקצב של בקשות לממשק הבורסה, סירובי פקודות, ניתוקי חיבור, ספרד ועומק אמיתיים. אך החזרתיות אפסית — הטייפ אינו חוזר על עצמו, ולכן שתי הרצות של אותה לוגיקה אינן בנות השוואה זו לזו.

המסקנה המעשית: החישוב ההיסטורי עונה אם ללוגיקה יש יתרון תחת ההנחות שהוגדרו, ואילו המצב המדגמי — אם היא תעמוד במגע עם תשתית ייצורית. אסור לערבב בין התשובות האלה: את איכות האסטרטגיה מודדים על ההיסטוריה, ומהדמו לוקחים את עובדות הסירובים וההתנהגות בזמן תקלות.

ספקות טכניים לפני תחילת הפיתוח

הספקות לפני ההתחלה בדרך כלל אותם ספקות: החישוב אידיאלי מדי מכדי להאמין לו, המנוע לא יתלכד עם קוד הייצור, ההרצה תיתקל במגבלות משאבים. להלן כיצד כל אחד מהם נסגר עוד בשלב הפיתוח.

עד כמה מדויקים החישובים?

הרצה על נרות ממצעת את התנועה בתוך הקטע — הזמנה עשויה להתבצע במחיר שמעולם לא היה בשוק. אנחנו מחשבים על זרימת אירועים לפי סדר הגעתם, ואת הפער מול הרצה מפורטת מציגים בדוח, ולא משאירים אותו לאחר כך.

כיצד נלקחות בחשבון עמלות וסליפג'?

העמלה נלקחת לפי הביצוע בפועל: בנפרד עבור הזמנות נגדיות והזמנות שוק. הסליפג' תלוי בנפח ההזמנה מול הנזילות — המודל מסיר כמה רמות מספר ההזמנות. אנחנו חוזרים על ההרצה בתנאים מחמירים: אסטרטגיה שמחזיקה מעמד רק בביצוע אידיאלי נפסלת עוד לפני ההשקה.

האם זה תואם לקוד הנוכחי?

המנוע מתחבר כספרייה, והלוגיקה שלכם של כניסות ויציאות נשארת העיקרית. מתאם ממיר את הנתונים והאירועים לצורה אחידה, והרצת בקרה משווה את האותות עד שרשימת הפערים מתאפסת.

האם מעגל החישוב יעמוד בעומס?

ההיסטוריה נחתכת לטווחים ומחושבת במקביל, והנתונים נשמרים במטמון בין הרצות. הרצה של שנים רבות על עשרות כלים נכנסת לתוך דקות, ואפשר להריץ אותה בחלון הלילה בלי לתפוס כוח חישוב למשימות אחרות.

כיצד לא להתאים את האסטרטגיה יתר על המידה להיסטוריה?

המדגם מחולק לקטע כיול ולקטע בדיקה, שאינו משתתף בכיול. הפרמטרים מורצים על מצבי שוק שונים, והפיזור של התוצאה נכנס לדוח: אם הרווח מחזיק מעמד על מערך מוצלח אחד בלבד, זה נראה מראש.

נדבר על המשימה ונחזור עם הערכה ותוכנית

כדי שההערכה תישען על הנתונים שלכם ולא על הנחות ממוצעות, מספיק להתחיל בתיאור המשימה ובשליחת מה שכבר קיים. משם אנחנו עוברים על החומרים, שואלים שאלות הבהרה וחוזרים עם תוכנית עבודה מחולקת לשלבים — עם ציון מה אנחנו עושים בכל שלב ומה נדרש מכם.

  • הגדרת המשימה: אילו אסטרטגיות בודקים, על אילו כלים וטיימפריימים, ומה נחשב לתוצאה של הרצה אחת.
  • מקורות נתונים: מהיכן לוקחים היסטוריית מחירים ועסקאות, באיזו תבנית היצוא, והאם יש פערים וכיצד הם מסומנים.
  • כללי ביצוע: עמלות, סליפג', מגבלות נפח, מינוף, לוגיקת ביטול ומילוי חלקי של הזמנות.
  • מדדים בפלט: אילו נתונים נדרשים ובאיזו צורה לצפות בהם — טבלה, גרף, ייצוא לקובץ.
  • מגבלות סביבה: היכן רץ המנוע, האם נדרשת הרצה מקבילה של מערך אסטרטגיות, והאם חשובה עבודה בדפדפן.
  • חישובי ייחוס: דוגמה שאתם סומכים עליה, כדי להשוות אליה את התוצאה של המנוע שלנו.
  • קבלה: אילו תרחישים הם חובה ומה משמעות תוצאה תקינה של בקטסטינג עבורכם.

סדר ההתחלה הוא כזה: שיחה קצרה על המשימה עם המהנדס שיבצע אותה, ואחר כך הערכה ותוכנית לפי שלבים. אנחנו מדווחים על כל שלב בפורמט אחד: מה נעשה, באילו מדדים זה מאושר, אילו מגבלות נותרו ומה נדרש מכם. אנחנו מציגים תוצאה על הנתונים שלכם ועל האסטרטגיות שלכם, ולא על דוגמה סינתטית.

תארו את המשימה בצורה חופשית — נחזור עם הערכה ותוכנית עבודה.