Strasmore Research
Deep Dives · Matt ConnorBy Matt Connor · · Updated 2026-08-05

מאגר נתונים מקומי למניות A עבור סוכני AI

ashare-lake בונה בדיסק מאגר מניות A עם 39 מערכי נתונים, רשומות מחיקה, שאילתות לפי נקודת זמן ושרת MCP לסוכנים, כדי לשחזר ניתוחים בלי תלות בספק.

מאגר נתונים מקומי של מניות A הוא ההיסטוריה של שוק המניות ביבשת סין, המאוחסנת בדיסק שלכם כקובצי Parquet עמודתיים. אפשר לקרוא אותם באמצעות DuckDB או Polars, במקום לפנות בכל פעם לעמוד יחיד אצל ספק נתונים. ashare-lake הוא פרויקט קוד פתוח שבונה מאגר כזה, לצד משימה יומית השומרת אותו מעודכן ושרת Model Context Protocol המאפשר לסוכן AI לשלוף ממנו נתונים. שתי החלטות תכנוניות מצדיקות כתיבה על הפרויקט כאן: מניות שנמחקו מהמסחר נשמרות, וניתן לקרוא את הנתונים הפונדמנטליים כפי שהיו במועד עבר.

מדוע סוכן AI זקוק לאגם נתונים מקומי למניות A

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

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

שאילתהשבוע אחד של נתוני הדקות בארה״ב: סימולים ומספר הנרות בכל סשן, 20–24 ביולי 2026
ה-SQL המדויק מאחורי כל מספר
SELECT toDate(toTimeZone(window_start, 'America/New_York')) AS session,
       formatDateTime(toDate(toTimeZone(window_start, 'America/New_York')), '%b %e') AS session_label,
       uniqExact(ticker) AS tickers_count,
       round(count() / 1000000, 2) AS minute_bars_millions
FROM global_markets.delayed_stocks_minute_aggs
WHERE toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2026-07-20')
  AND toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-07-24')
GROUP BY session, session_label
ORDER BY session
Run this yourself

ב-Jul 20 נרשמו 1.79 מיליון נרות של דקה על פני 11737 סמלים, וארבעת ימי המסחר האחרים בלוח חוזרים על אותה תבנית. שוק לאומי אחד, שבוע אחד ורזולוציה אחת. עשור של נתוני נרות יומיים, נתוני יסוד, הרכב מדדים ורשומות תזרימי כספים עבור שוק אחר יוצר היקף דומה, והעברת נתונים מדורגת באמצעות HTTP צורכת את כל הריצה של הסוכן.

אגם נתונים מקומי משנה שני דברים במקביל. הקריאות הופכות לסריקת קובץ במקום לצריכת מכסה, ושאילתה שנכתבת היום תחזיר את אותן שורות גם בעוד שישה חודשים. זו דרישה חיונית לבדיקת backtest. ההערות שלנו על מיומנויות נתוני שוק לסוכני AI ועל API של SQL מעל נתוני שוק מציגות את אותו טיעון גם לגבי נתוני ארה״ב.

התקינו אותו וקבעו גרסה יחידה

Python 3.10 ואילך. קבעו את הגרסה במפורש: בין 27 ביולי ל־2 באוגוסט 2026 פורסמו שש גרסאות, והתקנה ללא קיבוע גרסה בתוך סקריפט ההגדרה של סוכן היא יעד משתנה. הקוד נמצא ב־rootSunc/ashare-lake תחת רישיון Apache 2.0.

  • pip install ashare-lake==0.5.0 מתקין את הגרסה העדכנית בתחילת אוגוסט 2026.
  • asl --version מציג את גרסת ה־build המותקנת.
  • asl config init --data-root /path/to/ashare-lake כותב את קובץ ה־TOML לדוגמה המצורף, לאחר מילוי נתיב השורש של הנתונים, ללא צורך בשכפול המאגר. --config קובע את נתיב הפלט, ו־--force מחליף קובץ קיים.
  • asl doctor מריץ את הבדיקות במצב לא מקוון, לפני העברת נתונים כלשהי.
  • asl servers test בודק את מארחי הציטוטים במקור. asl sources בודק כל מקור, עם --vantage של cn, overseas או local.

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

מה מבצע תהליך ה-backfill

asl init יוצר את מבנה התיקיות ומשלים את נתוני ההיסטוריה. בתיעוד הפרויקט מצוין שהרצה מלאה נמשכת שעות ודורשת כמה GB של שטח אחסון, וכן חיבור פעיל לשרת ציטוטים upstream של Tongdaxin — חיבור שאותו asl servers test מאמת. asl init --profile quick מכסה במקום זאת את שלוש השנים האחרונות בתוך דקות, ועדיין שומר כל נייר שנסחר במהלך התקופה, כולל ניירות שכבר נמחקו מהמסחר. asl run daily הוא התהליך התוספתי שמתבצע לאחר מכן, asl status --datasets מדווח על היקף הכיסוי ועדכניות הנתונים בכל dataset, ו-asl serve מציב לוח מחוונים לקריאה בלבד בכתובת 127.0.0.1:8787.

המאגר אינו כולל נתונים כלשהם. כל קובץ Parquet נבנה במחשב שלך, ובכל שורה נשמרים פרטי lineage המציינים איזה מקור הפיק אותה ומתי היא נשלפה.

מהם 39 מערכי הנתונים?

הם בנויים בשכבות, מנתוני ייחוס כלפי חוץ: 36 טבלאות שנאספו בקפידה ו-3 טבלאות נגזרות.

  • נתוני ייחוס: מכשירים פיננסיים, לוח מסחר המכסה את השנים 2016 עד 2027, וסטטוס מסחר.
  • נתוני שוק: נתוני מסחר יומיים, נתוני מדדים, נתוני מסחר במרווחים של דקה אחת ושל 5 דקות, עסקאות שבוצעו, נתוני סחורות, גורמי התאמה ואירועי מחיקה ממסחר.
  • אירועים תאגידיים: פעולות תאגידיות, אינדקס הודעות ולוח הזמנים לפרסום דוחות הרווחים.
  • נתוני יסוד ותמחור: סעיפים בדוחות הכספיים, מדדי תמחור וקונצנזוס אנליסטים.
  • תנועות הון: זרימות כספים, מסחר במרג'ין, זרימות והחזקות northbound, לוח dragon-tiger של דיווחים על פקודות גדולות, עסקאות בלוק והחזקות מוסדיים.
  • מבנה ותעשייה: חברות המשתייכות לסקטורים, מרכיבי מדדים, חברות המשתייכות לענפים ומדד ענפי.
  • מאקרו: אינדיקטורים מאקרו-כלכליים, רוחב השוק ולוח שנה כלכלי.
  • סנטימנט ורוטציה: ציוני סנטימנט, דירוג מניות חמות, נתוני מסחר סקטוריאליים, זרימות כספים סקטוריאליות, כותרות חדשות ושירות חדשות מבזקיות.
  • סיכון וציות: לוח הזמנים לשחרור מניות חסומות ואירועים רגולטוריים.

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

כיצד מאגר מקומי מתמודד עם הטיית שורדים

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

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

שאילתהשרידות בפועל: קבוצות הסימולים של מרץ שעדיין נסחרו בסוף יולי 2026
ה-SQL המדויק מאחורי כל מספר
WITH on_tape_now AS (
    SELECT ticker
    FROM global_markets.delayed_stocks_minute_aggs
    WHERE toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2026-07-20')
      AND toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-07-31')
    GROUP BY ticker
),
cohort AS (
    SELECT toYear(toTimeZone(window_start, 'America/New_York')) AS cohort_year,
           ticker
    FROM global_markets.delayed_stocks_minute_aggs
    WHERE toYear(toTimeZone(window_start, 'America/New_York')) BETWEEN 2016 AND 2025
      AND toMonth(toTimeZone(window_start, 'America/New_York')) = 3
      AND toDayOfMonth(toTimeZone(window_start, 'America/New_York')) BETWEEN 10 AND 14
    GROUP BY cohort_year, ticker
)
SELECT c.cohort_year AS year,
       count() AS names_on_tape_count,
       countIf(n.ticker != '') AS still_trading_count,
       count() - countIf(n.ticker != '') AS gone_count,
       round(100 * countIf(n.ticker != '') / count(), 1) AS still_trading_pct
FROM cohort AS c
LEFT JOIN on_tape_now AS n ON c.ticker = n.ticker
GROUP BY year
ORDER BY year
Run this yourself

מבין 8101 הסימולים שנסחרו באותו שבוע בשנת 2016, 50.1% עדיין הופיעו בנתוני המסחר בסוף יולי 2026, ואילו 4040 לא. בקבוצת 2025 הנתון הוא 86.7%. הרצת סריקה שנבנתה על סמך הרישומים של היום לאחור לאורך 10 השנים האלה משמיטה בדרך יותר ויותר שמות מהשוק.

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

שאילתהמי עזב את המסחר: סימולי מרץ 2021 לפי מחזור כספי יומי, בהשוואה לסוף יולי 2026
ה-SQL המדויק מאחורי כל מספר
WITH on_tape_now AS (
    SELECT ticker
    FROM global_markets.delayed_stocks_minute_aggs
    WHERE toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2026-07-20')
      AND toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-07-31')
    GROUP BY ticker
),
march_2021 AS (
    SELECT ticker,
           sum(toFloat64(close) * toFloat64(volume))
             / uniqExact(toDate(toTimeZone(window_start, 'America/New_York'))) AS avg_daily_dollar_volume
    FROM global_markets.delayed_stocks_minute_aggs
    WHERE toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2021-03-01')
      AND toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2021-03-31')
    GROUP BY ticker
)
SELECT multiIf(d.avg_daily_dollar_volume >= 1000000000, '$1B or more',
               d.avg_daily_dollar_volume >= 100000000, '$100M to $1B',
               d.avg_daily_dollar_volume >= 10000000, '$10M to $100M',
               d.avg_daily_dollar_volume >= 1000000, '$1M to $10M',
               'under $1M') AS liquidity_bucket,
       count() AS names_count,
       countIf(n.ticker = '') AS gone_count,
       round(100 * countIf(n.ticker = '') / count(), 1) AS gone_pct
FROM march_2021 AS d
LEFT JOIN on_tape_now AS n ON d.ticker = n.ticker
GROUP BY liquidity_bucket
ORDER BY min(d.avg_daily_dollar_volume)
Run this yourself

הדרג under $1M איבד את השיעור הגדול ביותר — 57.5% מתוך 3968 שמות. גם הדרג הפעיל ביותר לא היה חסין: 3.4% מתוך 89 הסימולים שנסחרו במחזור של $1B or more ליום במרץ 2021 כבר לא היו במסחר בסוף יולי 2026. מיזוגים, הפיכות לחברות פרטיות, פשיטות רגל ויציאה ממדדים מסתיימים כולם באותה צורה בטבלת מחירים: השורות מפסיקות להופיע.

ashare-lake מתייחס לכך כאל בעיה מרכזית. מערך הנתונים של המכשירים הפיננסיים שומר סימולים שנמחקו מהמסחר, במקום לסנן ולהשאיר רק שמות פעילים. טבלת delisting_events מתעדת כיצד הסתיים המסחר בכל שם שעזב, ו-universe="all_a" ב-API של Python פותר שאילתה היסטורית הכוללת גם אותם. התיעוד של הפרויקט עצמו מדווח על פער של בערך פי שניים בין בדיקת ביצועים היסטורית הכוללת רק שורדים לבין בדיקה הכוללת גם מחיקות מהמסחר, בתקופה שבין 2016 ל-2021. זהו הצד ההפוך של המלכודת המתוארת בהערות שלנו על הטיית הסתכלות קדימה בבדיקות היסטוריות: יקום שמכיר את העתיד בלי לומר זאת.

שליפות מנקודת זמן

load("financial_statement_items", as_of="2018-04-30") מחזירה את הגרסה העדכנית ביותר של כל פריט שורה שפורסם עד לאותו תאריך, ולא את הנתון כפי שתוקן במועד מאוחר יותר. לברים יש ארגומנט adjust: hfq להתאמה לאחור, qfq לנרמול בתוך חלון השאילתה, או מחירים גולמיים. פקטור שהותאם לנתונים שהשוק עדיין לא פרסם אינו מודד דבר. זו הבדיקה הראשונה שיש לבצע בכל צינור של פקטור alpha שנוצר באמצעות LLM.

רישום השרת כשרת MCP

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

  • claude mcp add ashare-lake -- asl mcp --config /abs/path/to/ashare-lake.toml
  • כל לקוח MCP אחר משתמש באותם שני רכיבים: asl כפקודה, ו-mcp --config בתוספת נתיב מוחלט כארגומנטים. הנתיב חייב להיות מוחלט, משום שהלקוח עשוי להפעיל את התהליך מכל ספרייה.

שישה כלים זמינים, והם מאורגנים לפי השאלה ולא לפי מערך הנתונים: describe_lake נועד לתיאור הנתונים הקיימים ולאופן קריאתם; resolve_symbol ממפה שם לקוד, כולל שמות של חברות שנמחקו מהמסחר; query_bars מיועד לנתוני bars; query_fundamentals כולל את הארגומנט as_of; query_dataset מיועד לכל השאר; ו-run_sql מריץ שאילתת DuckDB מסוג SELECT, לקריאה בלבד, על פני כמה מערכי נתונים. דגל --live מאפשר לשרת להשיב על חיפושי סמלים ועל נתוני bars יומיים שאינם מתואמים ישירות ממקור הנתונים upstream, בלי לכתוב אותם ל-lake.

מגבלות שחשוב להכיר תחילה

  • מניות A בלבד. ללא הונג קונג, ללא רישומים בארה״ב וללא דבר מחוץ לסין היבשתית.
  • זהו פרויקט אישי. סוגיות ובקשות משיכה מקבלות טיפול במידת האפשר, והמסמכים מציינים במפורש שאין ערובה לזמינות: אתרי המקור עשויים להשתנות, וכתובת IP עלולה להיחסם, דבר שעוצר את קליטת הנתונים עד שמישהו מעדכן את הקוד.
  • רישיון Apache 2.0 חל על הקוד, לא על הנתונים. כל מקור חיצוני כפוף לתנאים שלו, ומתחזק הפרויקט אינו מעניק זכות להפיץ מחדש או למכור את קובצי Parquet שתבנו. יש לקרוא את תנאי המקור לפני כל שימוש מסחרי.
  • אין צורך בחשבון או באסימון עבור המקורות שמהם הפרויקט קורא נתונים. זו גם נקודת המשיכה שלו וגם מקור השבריריות שלו.
  • התמיכה ב-Windows נוספה בגרסה 0.3.0, וגרסת Python המינימלית עלתה ל-3.10 בגרסה 0.3.1.
מהו מקור העובדות על הפרויקט

גרסה 0.5.0, ששת מועדי השחרור וגרסת Python המינימלית נלקחו מהיסטוריית הגרסאות של הפרויקט ב-PyPI ומקובץ CHANGELOG, שנקראו ב-4 באוגוסט 2026. קטלוג מערכי הנתונים, התנהגות הסרת הרישום והנתונים בנקודת זמן, דגלי ה-CLI, רשימת כלי MCP ונוסח תנאי הרישוי והתמיכה נלקחו ממסמכי המאגר: docs/datasets/catalog.md, docs/reference/cli.md, docs/reference/mcp.md ו-docs/legal-and-data-sources.md. תוכנה מתעדכנת מהר יותר מפוסטים, לכן יש לבדוק את המסמכים עבור הגרסה שמותקנת אצלכם. שני לוחות ההישרדות מודדים סימולים בארה״ב במחסן הנתונים שלנו, ולא רישומים בסין, ומשמשים להמחשת המנגנון ולא למדידה של שוק מניות A.

שאלות נפוצות

האם נדרש מפתח API כדי לבנות אגם נתונים מקומי למניות A?

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

כמה זמן נדרש להשלמת טעינת ההיסטוריה של ashare-lake?

בתיעוד מצוין כי טעינת היסטוריה מלאה נמשכת כמה שעות זמן שעון ותופסת כמה GB בדיסק. לאורך כל התהליך נדרש חיבור תקין לשרת הציטוטים המקורי. asl init --profile quick מכסה את שלוש השנים האחרונות בתוך דקות, ועדיין כולל מניות שנמחקו מאז מהמסחר.

האם אגם נתונים מקומי למניות A כולל מניות שנמחקו מהמסחר?

כן. הסמלים שנמחקו מהמסחר נשארים במערך הנתונים של המכשירים הפיננסיים. טבלת delisting_events מתעדת כיצד הסתיים המסחר בכל מניה, ו-universe="all_a" בונה תמונת מצב היסטורית הכוללת אותן. המדידה העצמאית שלנו בארה״ב לעיל ממחישה מה היקף הנתונים שאוכלוסייה הכוללת רק מניות ששרדו משאירה בחוץ.

האם סוכן AI יכול לשאול את ashare-lake ישירות?

כן. asl mcp חושף שישה כלים באמצעות Model Context Protocol, ובהם כלי SQL לקריאה בלבד. כך הסוכן שולף נתונים מקובצי Parquet מקומיים במקום לבצע scraping. רושמים אותו באמצעות claude mcp add ashare-lake -- asl mcp --config /abs/path/to/ashare-lake.toml.

האם ashare-lake מהווה תחליף ל-AkShare או ל-Baostock?

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


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

#market-data#mcp#a-shares#open-source#ai-agents