פיתוח גרף נרות מותאם אישית לבורסות ו-DeFi

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

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

שאלות נפוצות

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

  • פיתוח אתר חברה B2B ADVANCE
    פיתוח אתר חברה B2B ADVANCE
    1481
  • פיתוח אפליקציית ווב עבור FEEDME
    פיתוח אפליקציית ווב עבור FEEDME
    1336
  • פיתוח אתר עבור BELFINGROUP
    פיתוח אתר עבור BELFINGROUP
    1034
  • פיתוח חנות מקוונת לחברת FURNORO
    פיתוח חנות מקוונת לחברת FURNORO
    1293
  • עיצוב לוגו לחברת B2B Advance
    עיצוב לוגו לחברת B2B Advance
    738
  • פיתוח אפליקציית ווב עבור Enviok
    פיתוח אפליקציית ווב עבור Enviok
    1032

פלטפורמת מסחר עם מיליון עסקאות בשעה—ווידג'טים סטנדרטיים של TradingView לא יכולים להתמודד עם זה: הצבירה מפגרת, וההתאמה האישית בלתי אפשרית. בפרויקט אחד עבור לקוח עם 50,000 זוגות ו-2 מיליון עסקאות בדקה, בנינו גרף נרות מותאם אישית מאפס. הפתרון משתמש ב-TimescaleDB עבור OHLCV, באגרגטור Go לזמן אמת, וב-Lightweight Charts לעיבוד—מעבד נר ב-3 אלפיות השנייה ומציג נתונים ללא עיכובים. בואו נפרק כיצד להימנע ממלכודות נפוצות ולקבל גרף שלא מפגר אפילו עם 100,000 נרות. הגישה שלנו מפחיתה עלויות תשתית פי 2 באמצעות צבירה יעילה. צרו קשר כדי לדון בדרישות הגרף שלכם.

למה לבחור בגרף מותאם אישית?

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

בעיות שאנחנו פותרים

הקשיים העיקריים בבניית גרפים מותאמים אישית הם זמן השהיה והתאמה אישית. ווידג'טים מוכנים לא מאפשרים לשנות את לוגיקת הצבירה (למשל, שימוש במחירים משוקללי נפח) או להוסיף אינדיקטורים כמו VWAP עם תקופה מותאמת. הבעיה השנייה היא ביצועים: עם אלפי נרות וכמה אינדיקטורים, העיבוד יכול לגמגם. אנחנו פותרים זאת עם שילוב של TimescaleDB בשרת ו-Lightweight Charts בלקוח.

איך אנחנו פותרים את בעיית זמן ההשהיה

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

  1. קבלה: שער WebSocket מטפל בעד 100,000 הודעות בשנייה לכל מופע.
  2. צבירה: אגרגטור בזיכרון ב-Go מעדכן את הנר הנוכחי ב-<2 מיקרו-שניות, ונרות סגורים ב-5 מיקרו-שניות.
  3. מסירה: דיכוי עדכונים ל-10 פעמים בשנייה, שליחה אצווה של לא יותר מ-10 נרות להודעה.

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

איך ליישם אינדיקטורים מותאמים אישית?

אינדיקטורים (EMA, VWAP, פרופיל נפח) מחושבים בלקוח או בשרת—הבחירה תלויה בתדירות החישוב מחדש. עבור אינדיקטורים עם חלון קבוע (למשל, EMA של 12 תקופות), אנו משתמשים בצבירה בצד השרת על ידי הוספת עמודות לאגרגט הרציף. עבור אינטראקטיביים (למשל, גרירת נקודות), אנו משתמשים בחישוב בצד הלקוח ב-Web Worker כדי למנוע חסימת ממשק המשתמש.

דוגמה לאינדיקטור בצד השרת—VWAP עם תקופה ניתנת להגדרה:

CREATE MATERIALIZED VIEW vwap_1m
WITH (timescaledb.continuous) AS
SELECT time_bucket('1 minute', created_at) AS bucket,
       pair_id,
       sum(price * quantity) / sum(quantity) AS vwap
FROM trades
GROUP BY bucket, pair_id;

איך ליישם גרף נרות מותאם אישית?

שקלו מקרה טיפוסי: בורסה רוצה להציג נרות של דקה אחת עם Heikin-Ashi ו-EMA. אנו תומכים גם ב-Renko, Kagi ו-Point-and-Figure. חלק השרת מצבר עסקאות דרך TimescaleDB, והפרונטאנד משתמש בספריית Lightweight Charts.

אחסון וצבירת OHLCV

עסקאות גולמיות מאוחסנות ב-TimescaleDB. לצבירה מהירה, אנו יוצרים אגרגט רציף:

CREATE MATERIALIZED VIEW candles_1m
WITH (timescaledb.continuous) AS
SELECT time_bucket('1 minute', created_at) AS bucket,
       pair_id,
       first(price, created_at) AS open,
       max(price) AS high,
       min(price) AS low,
       last(price, created_at) AS close,
       sum(quantity) AS volume,
       count(*) AS trades_count
FROM trades
GROUP BY bucket, pair_id;

SELECT add_continuous_aggregate_policy('candles_1m',
    start_offset => INTERVAL '3 hours',
    end_offset => INTERVAL '1 minute',
    schedule_interval => INTERVAL '1 minute');

מנרות של דקה, מסגרות זמן גבוהות יותר נבנות תוך כדי תנועה—אותו SQL עם CREATE MATERIALIZED VIEW vwap_1m WITH (timescaledb.continuous) AS SELECT time_bucket('1 minute', created_at) AS bucket, pair_id, sum(price * quantity) / sum(quantity) AS vwap FROM trades GROUP BY bucket, pair_id; .

עדכון בזמן אמת ב-Go

type CandleAggregator struct {
	mu sync.RWMutex
	current map[PairTimeframe]*Candle
}

func (ca *CandleAggregator) OnTrade(trade Trade) {
	ca.mu.Lock()
	defer ca.mu.Unlock()
	for _, tf := range TIMEFRAMES {
		key := PairTimeframe{trade.PairID, tf}
		bucket := truncateToTimeframe(trade.Time, tf)
		candle, exists := ca.current[key]
		if !exists || candle.Bucket != bucket {
			if exists {
				ca.publishClosedCandle(candle)
			}
			ca.current[key] = &Candle{
				Bucket: bucket,
				Open: trade.Price,
				High: trade.Price,
				Low: trade.Price,
				Close: trade.Price,
				Volume: trade.Quantity,
			}
		} else {
			if trade.Price > candle.High {
				candle.High = trade.Price
			}
			if trade.Price < candle.Low {
				candle.Low = trade.Price
			}
			candle.Close = trade.Price
			candle.Volume = candle.Volume.Add(trade.Quantity)
		}
		ca.publishLiveCandle(ca.current[key])
	}
}

פרונטאנד: TradingView Lightweight Charts

import { createChart, CandlestickSeries } from 'lightweight-charts';

const chart = createChart(container, {
  layout: {
    background: { color: '#0d0d0f' },
    textColor: '#9b9ea8',
  },
  grid: {
    vertLines: { color: '#1e2030' },
    horzLines: { color: '#1e2030' },
  },
  timeScale: {
    timeVisible: true,
    secondsVisible: false,
  },
});

const candleSeries = chart.addSeries(CandlestickSeries, {
  upColor: '#00b15e',
  downColor: '#e84242',
  borderVisible: false,
});

// Load historical + stream via WebSocket
candleSeries.setData(historicalData);
ws.onmessage = (event) => candleSeries.update(JSON.parse(event.data));

אינדיקטורים (EMA, VWAP) מתווספים כ-CREATE MATERIALIZED VIEW candles_1m WITH (timescaledb.continuous) AS SELECT time_bucket('1 minute', created_at) AS bucket, pair_id, first(price, created_at) AS open, max(price) AS high, min(price) AS low, last(price, created_at) AS close, sum(quantity) AS volume, count(*) AS trades_count FROM trades GROUP BY bucket, pair_id; SELECT add_continuous_aggregate_policy('candles_1m', start_offset => INTERVAL '3 hours', end_offset => INTERVAL '1 minute', schedule_interval => INTERVAL '1 minute'); מעל. עבור Heikin-Ashi, המירו נתונים בלקוח:

function toHeikinAshi(candles: OHLCV[]): OHLCV[] {
  return candles.map((c, i) => {
    const prev = i > 0 ? candles[i-1] : c;
    const haClose = (c.open + c.high + c.low + c.close) / 4;
    const haOpen = i === 0 ? (c.open + c.close)/2 : (prev.open + prev.close)/2;
    return {
      time: c.time,
      open: haOpen,
      high: Math.max(c.high, haOpen, haClose),
      low: Math.min(c.low, haOpen, haClose),
      close: haClose,
    };
  });
}

השוואת ביצועים: Lightweight Charts מול ספריות אחרות

פרמטר Lightweight Charts v4 D3.js Highcharts
זמן עיבוד עבור 10,000 נרות 12 אלפיות השנייה 45 אלפיות השנייה 30 אלפיות השנייה
RAM ב-100,000 נרות 8 MB 25 MB 18 MB
תמיכה ב-Web Worker כן כן מוגבל
אינדיקטורים מותאמים אישית TypeScript JavaScript JSON

Lightweight Charts מהיר פי 3–4 מ-D3.js בעיבוד 10,000 נרות ומשתמש בפי 3 פחות זיכרון.

אילו נתונים אנחנו צריכים כדי להתחיל?

כדי להתחיל, אנו זקוקים לגישה לאירועי עסקאות (עסקאות גולמיות) דרך API או קבצים. אנו מגדירים את הצבירה בעצמנו. אם אין נתונים זמינים, אנו עוזרים להתחבר למקורות בורסה דרך WebSocket או REST. התצורה המינימלית אינה דורשת סכמות ספציפיות—TimescaleDB מסתגל לכל מבנה.

שלבי העבודה

שלב מה אנחנו עושים
ארכיטקטורה בחירת DB, סכמת צבירה, עיצוב API
שרת TimescaleDB + מיקרוסרוויס Go לזמן אמת
פרונטאנד שילוב Lightweight Charts, אינדיקטורים מותאמים אישית, מיתוג
WebSocket דחיפת עדכונים עם דיכוי
תיעוד תיאור סכמות, API, הוראות פריסה
הדרכה סדנה למפתחים שלכם (יומיים)
תמיכה שבועיים לאחר ההשקה (באגים, שיפורים)

מה כלול בעבודה

התוצאה כוללת חבילה מלאה: תיעוד (סכמות DB, מפרט API, הוראות פריסה), גישה לקוד המקור במאגר Git, הדרכה לצוות שלכם (סדנה של יומיים), שבועיים של תמיכה חינם לאחר ההשקה, ו-SLA עם זמן תגובה של עד 4 שעות. אנו מבטיחים מעבר חלק ותפעול עצמאי.

מחסנית טכנולוגית

רכיב טכנולוגיה
מסד נתונים טורי TimescaleDB (הרחבת PostgreSQL)
צבירה בזמן אמת מיקרוסרוויס Go
WebSocket gorilla/websocket
פרונטאנד TradingView Lightweight Charts v4
אינדיקטורים TypeScript מותאם אישית + ta-lib.wasm
ניהול מצב Zustand

מסגרות זמן ועלות

מסגרות הזמן הן אינדיקטיביות ומחושבות בנפרד:

  • גרף בסיסי (עדכונים חיים, 2–3 אינדיקטורים): 4–6 שבועות.
  • גרפים מלאים (כל מסגרות הזמן, 10+ אינדיקטורים, ציור, Heikin-Ashi/Renko): 2–3 חודשים.
  • חלק השרת (TimescaleDB + אגרגטור + WebSocket): 3–5 שבועות במקביל.

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

הניסיון והערבויות שלנו

אנחנו צוות פיתוח בלוקצ'יין עם ניסיון של 5+ שנים ב-Web3. יישמנו 30+ פרויקטים עבור בורסות קריפטו, פלטפורמות DeFi וטרמינלי מסחר. אנו משתמשים בכלים מוכחים ומספקים ערבות רשמית על הקוד.

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