skayn-trading-sdk
Version:
Professional Bitcoin trading strategy backtesting framework with institutional-grade architecture
94 lines (82 loc) • 2.78 kB
JavaScript
/**
* Abstract Data Provider Interface
* Defines contract for all historical data providers
*/
class IDataProvider {
/**
* Fetch historical market data
* @param {string} startDate - ISO date string
* @param {string} endDate - ISO date string
* @param {string} interval - '1m', '5m', '1h', '1d', etc.
* @param {string} symbol - Trading pair symbol
* @returns {Promise<Array>} OHLCV data array
*/
async getData(startDate, endDate, interval = '1d', symbol = 'BTCUSDT') {
throw new Error('IDataProvider.getData() must be implemented');
}
/**
* Validate data integrity
* @param {Array} data - OHLCV data array
* @param {string} interval - Data interval for gap detection
* @returns {Object} Validation result with issues array
*/
validateData(data, interval = '1d') {
const issues = [];
if (!Array.isArray(data)) {
issues.push('Data must be an array');
return { valid: false, issues };
}
for (let i = 0; i < data.length; i++) {
const bar = data[i];
// Check required fields
if (!bar.timestamp || !bar.open || !bar.high || !bar.low || !bar.close) {
issues.push(`Missing required fields at index ${i}`);
}
// Check OHLC logic
if (bar.high < bar.low) {
issues.push(`Invalid OHLC: high < low at ${bar.timestamp}`);
}
if (bar.close > bar.high || bar.close < bar.low) {
issues.push(`Close price outside high/low range at ${bar.timestamp}`);
}
// Check for gaps (more than 1.5x expected interval)
if (i > 0) {
const expectedInterval = this.getIntervalMs(interval);
const actualInterval = bar.timestamp - data[i-1].timestamp;
if (actualInterval > expectedInterval * 1.5) {
issues.push(`Data gap detected: ${actualInterval}ms vs expected ${expectedInterval}ms`);
}
}
}
return { valid: issues.length === 0, issues };
}
/**
* Generate cache key for data request
* @param {string} startDate
* @param {string} endDate
* @param {string} interval
* @param {string} symbol
* @returns {string} Cache key
*/
getCacheKey(startDate, endDate, interval, symbol) {
return `${symbol}_${interval}_${startDate}_${endDate}`;
}
/**
* Convert interval string to milliseconds
* @param {string} interval
* @returns {number} Milliseconds
*/
getIntervalMs(interval) {
const intervals = {
'1m': 60 * 1000,
'5m': 5 * 60 * 1000,
'15m': 15 * 60 * 1000,
'1h': 60 * 60 * 1000,
'4h': 4 * 60 * 60 * 1000,
'1d': 24 * 60 * 60 * 1000,
'1w': 7 * 24 * 60 * 60 * 1000
};
return intervals[interval] || intervals['1d'];
}
}
module.exports = IDataProvider;