cyberhybridhub/server/lib/alpaca/alpaca_market_data_client.dart

83 lines
2.4 KiB
Dart

import 'dart:convert';
import 'package:http/http.dart' as http;
import 'alpaca_env.dart';
import 'alpaca_models.dart';
/// REST client for Alpaca Market Data API v2 (IEX feed on Basic plan).
class AlpacaMarketDataClient {
AlpacaMarketDataClient({
required AlpacaEnv env,
http.Client? httpClient,
}) : _env = env,
_client = httpClient ?? http.Client();
final AlpacaEnv _env;
final http.Client _client;
Map<String, String> get _headers => <String, String>{
'APCA-API-KEY-ID': _env.apiKeyId,
'APCA-API-SECRET-KEY': _env.apiSecretKey,
};
/// `GET /v2/stocks/{symbol}/trades/latest`
Future<AlpacaLatestTradeResponse> getLatestTrade(String symbol) async {
_env.requireCredentials();
final Uri uri = Uri.parse(
'${_env.dataBaseUrl}/v2/stocks/${Uri.encodeComponent(symbol)}/trades/latest',
).replace(queryParameters: <String, String>{'feed': _env.dataFeed});
final http.Response response = await _client.get(uri, headers: _headers);
if (response.statusCode != 200) {
throw AlpacaMarketDataException(
'getLatestTrade($symbol) failed: ${response.statusCode} ${response.body}',
);
}
return AlpacaLatestTradeResponse.fromJson(
jsonDecode(response.body) as Map<String, dynamic>,
);
}
/// `GET /v2/stocks/bars` — batched symbols, daily bars newest last.
Future<AlpacaBarsResponse> getDailyBars(
List<String> symbols, {
int limit = 2,
}) async {
_env.requireCredentials();
if (symbols.isEmpty) {
return AlpacaBarsResponse(barsBySymbol: <String, List<AlpacaBar>>{});
}
final Uri uri = Uri.parse('${_env.dataBaseUrl}/v2/stocks/bars').replace(
queryParameters: <String, String>{
'symbols': symbols.join(','),
'timeframe': '1Day',
'limit': limit.toString(),
'feed': _env.dataFeed,
},
);
final http.Response response = await _client.get(uri, headers: _headers);
if (response.statusCode != 200) {
throw AlpacaMarketDataException(
'getDailyBars failed: ${response.statusCode} ${response.body}',
);
}
return AlpacaBarsResponse.fromJson(
jsonDecode(response.body) as Map<String, dynamic>,
);
}
void close() => _client.close();
}
class AlpacaMarketDataException implements Exception {
AlpacaMarketDataException(this.message);
final String message;
@override
String toString() => message;
}