Skip to content

Commit

Permalink
Correctly decode empty bar responses
Browse files Browse the repository at this point in the history
As it turns out the Alpaca Data API does not strictly adhere to always
returning an array of bars in the response to a bars request. Rather, if
no data is returned it will just set the member to null. This value
currently causes a decode error, as serde_json does not treat that as a
valid variant for an array.
With this change we fix the problem by explicitly using the vec_from_str
function for decoding purposes. This function correctly handles such
upstream values.
  • Loading branch information
d-e-s-o committed Jan 11, 2022
1 parent c507c5e commit c6cc45d
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 0 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
Unreleased
----------
- Fixed JSON decoding error when no bars are returned in response to
`data::v2::bars::Get` request


0.22.1
------
- Added support for realtime market data streaming via
Expand Down
23 changes: 23 additions & 0 deletions src/data/v2/bars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use serde::Serialize;
use serde_urlencoded::to_string as to_query;

use crate::data::DATA_BASE_URL;
use crate::util::vec_from_str;
use crate::Str;


Expand Down Expand Up @@ -107,6 +108,7 @@ pub struct Bar {
#[non_exhaustive]
pub struct Bars {
/// The list of returned bars.
#[serde(deserialize_with = "vec_from_str")]
pub bars: Vec<Bar>,
/// The symbol the bars correspond to.
pub symbol: String,
Expand Down Expand Up @@ -198,6 +200,27 @@ mod tests {
assert!(res.next_page_token.is_some())
}

/// Check that we can decode a response containing no bars correctly.
#[test(tokio::test)]
async fn no_bars() {
let api_info = ApiInfo::from_env().unwrap();
let client = Client::new(api_info);
let start = Utc.ymd(2021, 11, 5).and_hms_milli(0, 0, 0, 0);
let end = Utc.ymd(2021, 11, 5).and_hms_milli(0, 0, 0, 0);

let request = BarReq {
symbol: "SPY".to_string(),
limit: None,
start,
end,
timeframe: TimeFrame::OneDay,
page_token: None,
adjustment: None,
};
let res = client.issue::<Get>(&request).await.unwrap();
assert_eq!(res.bars, Vec::new())
}

/// Check that we can request historic bar data for a stock.
#[test(tokio::test)]
async fn request_bars() {
Expand Down

0 comments on commit c6cc45d

Please sign in to comment.