feat: 接入 OKX 加密货币数据源(实时价格+历史K线)
This commit is contained in:
parent
8830dd17ae
commit
20ab0c5173
@ -70,12 +70,38 @@ public class MarketDataService : IMarketDataService
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取加密货币实时价格
|
/// 获取加密货币实时价格
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="symbol">加密货币代码(如 BTCUSD)</param>
|
/// <param name="symbol">加密货币代码(如 BTC-USDT)</param>
|
||||||
/// <returns>加密货币价格信息</returns>
|
/// <returns>加密货币价格信息</returns>
|
||||||
public async Task<MarketPriceResponse> GetCryptoPriceAsync(string symbol)
|
public async Task<MarketPriceResponse> GetCryptoPriceAsync(string symbol)
|
||||||
{
|
{
|
||||||
// 待接入 OKX API
|
try
|
||||||
throw new NotImplementedException("加密货币数据源待接入 OKX API");
|
{
|
||||||
|
_logger.LogInformation($"Requesting crypto price for symbol: {symbol}");
|
||||||
|
|
||||||
|
// OKX 实时 ticker 接口,symbol 格式如 BTC-USDT
|
||||||
|
var url = $"https://www.okx.com/api/v5/market/ticker?instId={symbol}";
|
||||||
|
var response = await _httpClient.GetFromJsonAsync<OkxTickerResponse>(url);
|
||||||
|
|
||||||
|
if (response == null || response.code != "0" || response.data == null || response.data.Count == 0)
|
||||||
|
{
|
||||||
|
throw new Exception($"No data found for {symbol}, code: {response?.code}, msg: {response?.msg}");
|
||||||
|
}
|
||||||
|
|
||||||
|
var latest = response.data[0];
|
||||||
|
return new MarketPriceResponse
|
||||||
|
{
|
||||||
|
Symbol = symbol,
|
||||||
|
Price = decimal.TryParse(latest.last, out var price) ? price : 0,
|
||||||
|
PreviousClose = decimal.TryParse(latest.sodUtc0, out var prevClose) ? prevClose : 0, // UTC0 开盘价作为昨日收盘价
|
||||||
|
Timestamp = DateTime.UtcNow,
|
||||||
|
AssetType = "Crypto"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, $"Error getting crypto price for {symbol}");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -133,14 +159,82 @@ public class MarketDataService : IMarketDataService
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取加密货币历史数据
|
/// 获取加密货币历史数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="symbol">加密货币代码</param>
|
/// <param name="symbol">加密货币代码(如 BTC-USDT)</param>
|
||||||
/// <param name="timeframe">时间周期</param>
|
/// <param name="timeframe">时间周期</param>
|
||||||
/// <param name="limit">数据点数量</param>
|
/// <param name="limit">数据点数量</param>
|
||||||
/// <returns>历史数据列表</returns>
|
/// <returns>历史数据列表</returns>
|
||||||
public async Task<List<MarketDataResponse>> GetCryptoHistoricalDataAsync(string symbol, string timeframe, int limit)
|
public async Task<List<MarketDataResponse>> GetCryptoHistoricalDataAsync(string symbol, string timeframe, int limit)
|
||||||
{
|
{
|
||||||
// 待接入 OKX API
|
try
|
||||||
throw new NotImplementedException("加密货币数据源待接入 OKX API");
|
{
|
||||||
|
_logger.LogInformation($"Requesting crypto historical data for symbol: {symbol}, timeframe: {timeframe}, limit: {limit}");
|
||||||
|
|
||||||
|
// 转换 timeframe 为 OKX 支持的粒度
|
||||||
|
var bar = ConvertToOkxBar(timeframe);
|
||||||
|
|
||||||
|
// OKX K线接口
|
||||||
|
var url = $"https://www.okx.com/api/v5/market/candles?instId={symbol}&bar={bar}&limit={limit}";
|
||||||
|
var response = await _httpClient.GetFromJsonAsync<OkxCandlesResponse>(url);
|
||||||
|
|
||||||
|
if (response == null || response.code != "0" || response.data == null)
|
||||||
|
{
|
||||||
|
throw new Exception($"No data found for {symbol}, code: {response?.code}, msg: {response?.msg}");
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = new List<MarketDataResponse>();
|
||||||
|
foreach (var item in response.data)
|
||||||
|
{
|
||||||
|
if (item.Length < 6) continue;
|
||||||
|
|
||||||
|
if (long.TryParse(item[0], out var ts) &&
|
||||||
|
decimal.TryParse(item[1], out var open) &&
|
||||||
|
decimal.TryParse(item[2], out var high) &&
|
||||||
|
decimal.TryParse(item[3], out var low) &&
|
||||||
|
decimal.TryParse(item[4], out var close) &&
|
||||||
|
decimal.TryParse(item[5], out var volume))
|
||||||
|
{
|
||||||
|
result.Add(new MarketDataResponse
|
||||||
|
{
|
||||||
|
Symbol = symbol,
|
||||||
|
Open = open,
|
||||||
|
High = high,
|
||||||
|
Low = low,
|
||||||
|
Close = close,
|
||||||
|
Volume = volume,
|
||||||
|
Timestamp = DateTimeOffset.FromUnixTimeMilliseconds(ts).UtcDateTime,
|
||||||
|
AssetType = "Crypto"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 按时间升序排列
|
||||||
|
result = result.OrderBy(x => x.Timestamp).ToList();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, $"Error getting crypto historical data for {symbol}");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 转换 timeframe 为 OKX 支持的 bar 格式
|
||||||
|
/// </summary>
|
||||||
|
private string ConvertToOkxBar(string timeframe)
|
||||||
|
{
|
||||||
|
return timeframe.ToLower() switch
|
||||||
|
{
|
||||||
|
"1min" => "1m",
|
||||||
|
"5min" => "5m",
|
||||||
|
"15min" => "15m",
|
||||||
|
"1h" => "1H",
|
||||||
|
"4h" => "4H",
|
||||||
|
"1d" => "1D",
|
||||||
|
"1w" => "1W",
|
||||||
|
"1m" => "1M",
|
||||||
|
_ => "1D"
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -195,3 +289,25 @@ internal class TiingoCryptoBar
|
|||||||
public decimal? volume { get; set; }
|
public decimal? volume { get; set; }
|
||||||
public DateTime? date { get; set; }
|
public DateTime? date { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OKX 响应模型
|
||||||
|
internal class OkxTickerResponse
|
||||||
|
{
|
||||||
|
public string code { get; set; }
|
||||||
|
public string msg { get; set; }
|
||||||
|
public List<OkxTickerData> data { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class OkxTickerData
|
||||||
|
{
|
||||||
|
public string instId { get; set; }
|
||||||
|
public string last { get; set; }
|
||||||
|
public string sodUtc0 { get; set; } // UTC0 开盘价,作为昨日收盘价
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class OkxCandlesResponse
|
||||||
|
{
|
||||||
|
public string code { get; set; }
|
||||||
|
public string msg { get; set; }
|
||||||
|
public List<string[]> data { get; set; }
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user