9 个版本
0.1.8 | 2021 年 4 月 26 日 |
---|---|
0.1.7 | 2021 年 4 月 19 日 |
#8 in #algorithmic-trading
每月 29 次下载
98KB
2K SLoC
Rust Binance API 异步/Await 库,配合 Tokio 使用
WebSocket
https://github.com/binance/binance-spot-api-docs/blob/master/web-socket-streams.md
单独交易 / 订单簿快照 / 汇总交易 / 部分订单簿深度流 / 24 小时快照 / 差异深度流
use binance_ws::websocket::*;
use binance_ws::futures::TryStreamExt;
use binance_ws::api::Binance;
#[tokio::main]
async fn main() -> Result<(), BinanceErr> {
let symbols = vec!["ETHBTC".into(), "ADABTC".into()];
let mut binance_ws: Websocket = Binance::new(None, None);
// ** Change the variant wrapping the input symbols passed to the subscribe function to change the stream type!
// For e.g., to do aggregated trades instead:
// let sub_id = binance_ws.subscribe(WebsocketStreamType::AggregatedTrades(symbols)).await?;
let sub_id = binance_ws.subscribe(WebsocketStreamType::IndividualTrade(symbols)).await?;
while let Some(event) = binance_ws.try_next().await.expect("Didn't receive next transmit") {
match event {
WebsocketEvent::IndividualTrade(data) => {
println!("{}, {}, {}", data.price, data.symbol, data.qty);
},
// Other events that use same format:
// WebsocketEvent::BookTicker(data) => {
// println!("{}, {}, {}", data.best_bid, data.symbol, data.update_id);
// },
// WebsocketEvent::AggregatedTrades(data) => {
// println!("{}, {}, {}", data.price, data.symbol, data.qty);
// },
// WebsocketEvent::PartialBookDepthStream(data) => {
// println!("{}, {}, {}", data.asks.len(), data.bids.len(), data.last_update_id);
// },
// WebsocketEvent::TwentyFourHourTicker(data) => {
// println!("{}, {}, {}", data.prev_close, data.best_ask_qty, data.event_time);
// },
// WebsocketEvent::DiffDepthStream(data) => {
// println!("{}, {}, {}", data.bids.len(), data.symbol, data.event_time);
// },
_ => {}
}
}
binance_ws.unsubscribe(sub_id);
Ok(())
}
蜡烛图
use binance_ws::websocket::*;
use binance_ws::futures::TryStreamExt;
use binance_ws::api::Binance;
#[tokio::main]
async fn main() -> Result<(), BinanceErr> {
let symbols = vec!["ETHBTC".into(), "ADABTC".into()];
let mut binance_ws: Websocket = Binance::new(None, None);
let interval = KlineInterval::Minutes(5);
// OR let interval = KlineInterval::None;
let sub_id = binance_ws.subscribe(WebsocketStreamType::Kline { interval, symbols }).await?;
while let Some(event) = binance_ws.try_next().await.expect("Didn't receive next transmit") {
match event {
WebsocketEvent::Kline(kline) => {
println!("{}, {}, {}", kline.symbol, kline.event_time, kline.kline.high);
},
_ => {}
}
}
binance_ws.unsubscribe(sub_id);
}
每日快照全部
use binance_ws::websocket::*;
use binance_ws::futures::TryStreamExt;
use binance_ws::api::Binance;
use binance_ws::userstream::{UserStream, UserStreamAsync};
#[tokio::main]
async fn main() -> Result<(), BinanceErr> {
let mut binance_ws: Websocket = Binance::new(None, None);
let sub_id = binance_ws.subscribe(WebsocketStreamType::DayTickerAll).await?;
while let Some(event) = binance_ws.try_next().await.expect("Didn't receive next transmit") {
match event {
WebsocketEvent::DayTickerAll(many_ticker) => {
for ticker in many_ticker {
println!("{}, {}, {}", ticker.best_ask_qty, ticker.high, ticker.close_time);
}
},
_ => {}
}
}
binance_ws.unsubscribe(sub_id);
}
用户流
https://github.com/binance/binance-spot-api-docs/blob/master/user-data-stream.md
use binance_api_async::userstream::{UserStream, UserStreamAsync};
use binance_api_async::api::Binance;
use binance_api_async::futures::TryStreamExt;
use binance_api_async::websocket::WebsocketEvent;
#[tokio::main]
async fn main() -> Result<(), BinanceErr> {
let mut user_stream: UserStream = Binance::new(Some("<api-key>".into()), Some("<api-secret>".into()));
let sub_id = user_stream.subscribe().await?;
let mut binance_ws = user_stream.ws.as_mut().expect("You didn't subscribe!");
while let Some(event) = binance_ws.try_next().await.expect("Didn't receive next transmit") {
match event {
WebsocketEvent::OrderUpdate(data) => {
println!("{}, {}, {}", data.accumulated_qty_filled_trades, data.commission, data.qty_last_filled_trade)
},
WebsocketEvent::AccountUpdate(data) => {
println!("{}", data.balance.first().unwrap().free)
},
WebsocketEvent::BalanceUpdate(data) => {
println!("{}, {}, {}", data.asset, data.balance_delta, data.clear_time)
}
_ => {}
}
}
user_stream.unsubscribe(sub_id);
Ok(())
}
HTTP 请求
https://github.com/binance/binance-spot-api-docs/blob/master/rest-api.md
(这几乎是对 https://docs.rs/crate/binance/0.12.3 的分支进行修改并使其异步的)
市场
use binance::api::*;
use binance::market::*;
#[tokio::main]
async fn main() -> Result<(), BinanceErr> {
let market: Market = Binance::new(None, None);
// Order book at default depth
let depth = market.get_depth("BNBETH").await?;
// Latest price for ALL symbols
let all_prices = market.get_all_prices().await?;
// Latest price for ONE symbol
let price = market.get_price("BNBETH").await?;
// Current average price for ONE symbol
let avg_price = market.get_average_price("BNBETH").await?;
// Best price/qty on the order book for ALL symbols
let all_book_tickers = market.get_all_book_tickers().await?;
// Best price/qty on the order book for ONE symbol
let book_ticker = market.get_book_ticker("BNBETH").await?;
// 24hr ticker price change statistics
let twenty_four_hour_price = market.get_24h_price_stats("BNBETH").await?;
// last 10 5min klines (candlesticks) for a symbol:
let klines = market.get_klines("BNBETH", "5m", 10, None, None).await?;
Ok(())
}
账户
use binance_api_async::account::Account;
use binance_api_async::api::Binance;
use binance_api_async::error::BinanceErr;
#[tokio::main]
async fn main() -> Result<(), BinanceErr> {
let api_key = Some("YOUR_API_KEY".into());
let secret_key = Some("YOUR_SECRET_KEY".into());
let account: Account = Binance::new(api_key, secret_key);
let account = account.get_account().await?;
let open_orders = account.get_open_orders("WTCETH").await?;
let limit_buy = account.limit_buy("WTCETH", 10, 0.014000).await?;
let market_buy = account.market_buy("WTCETH", 5).await?;
let limit_sell = account.limit_sell("WTCETH", 10, 0.035000).await?;
let market_sell = account.market_sell("WTCETH", 5).await?;
let custom_order = account.custom_order("WTCETH", 9999, 0.0123, "SELL", "LIMIT", "IOC").await?;
let order_id = 1_957_528;
let order_status = account.order_status("WTCETH", order_id).await?;
let cancelled_order = account.cancel_order("WTCETH", order_id).await?;
let all_cancelled_orders = account.cancel_all_open_orders("WTCETH").await?;
let balances = account.get_balance("KNC").await?;
let trade_history = account.trade_history("WTCETH").await?;
Ok(())
}
错误
"get_fmt_error" 是由本库 "BinanceErr" 暴露的泛型错误类型上的一个方法,该方法返回格式化的错误消息。
此方法是不必要的,仅存在于绕过 IntelliJ IDEs 无法理解 std::fmt::Display 实际已实现的问题。
use binance_api_async::api::Binance;
use binance_api_async::account::Account;
#[tokio::main]
async fn main() -> Result<(), BinanceErr> {
let account: Account = Binance::new(Some(format!("<api-key>")), Some(format!("<API-SECRET>")));
match account.market_buy(format!("DOGEBTC"), 101).await {
Err(e) => {
println!("{}", e);
},
_ => {}
}
// If you are getting "std::fmt::Display not implemented for BinanceErr"
match account.market_buy(format!("DOGEBTC"), 101).await {
Err(mut e) => {
println!("{}", e.get_fmt_error());
},
_ => {}
}
Ok(())
}
依赖
~8–21MB
~340K SLoC