65 个发布版本

0.21.0 2024年3月7日
0.20.2 2023年1月1日
0.20.1 2022年12月11日
0.20.0 2022年10月27日
0.1.2 2017年11月20日

#910魔法豆

Download history 140/week @ 2024-04-15 223/week @ 2024-04-22 85/week @ 2024-04-29 44/week @ 2024-05-06 21/week @ 2024-05-13 40/week @ 2024-05-20 30/week @ 2024-05-27 27/week @ 2024-06-03 65/week @ 2024-06-10 15/week @ 2024-06-17 158/week @ 2024-06-24 170/week @ 2024-07-01 176/week @ 2024-07-08 170/week @ 2024-07-15 232/week @ 2024-07-22 174/week @ 2024-07-29

770 每月下载量
用于 btrader

MIT/Apache

180KB
4.5K SLoC

binance-rs

非官方的 Binance API 和 Binance 期货 API (正在开发中,即将进行重大更改)

Crates.io Build Status CI MIT licensed Apache-2.0 licensed

docs.rs 上的文档

Binance API 电报群

https://t.me/binance_api_english

风险提示

这是一个个人项目,使用风险自担。我不会对您的投资损失负责。加密货币投资存在较高的市场风险。

用法

将以下内容添加到您的 Cargo.toml 文件中

[dependencies]
binance = { git = "https://github.com/wisespace-io/binance-rs.git" }

Rust >= 1.56.1

rustup install stable

目录

市场数据

use binance::api::*;
use binance::model::*;
use binance::market::*;

fn main() {
    let market: Market = Binance::new(None, None);

    // Order book at default depth
    match market.get_depth("BNBETH") {
        Ok(answer) => println!("{:?}", answer),
        Err(e) => println!("Error: {}", e),
    }

    // Order book at depth 500
    match market.get_custom_depth("BNBETH", 500) {
        Ok(answer) => println!("{:?}", answer),
        Err(e) => println!("Error: {}", e),
    }

    // Latest price for ALL symbols
    match market.get_all_prices() {
        Ok(answer) => println!("{:?}", answer),
        Err(e) => println!("Error: {:?}", e),
    }

    // Latest price for ONE symbol
    match market.get_price("BNBETH") {
        Ok(answer) => println!("{:?}", answer),
        Err(e) => println!("Error: {:?}", e),
    }

    // Current average price for ONE symbol
    match market.get_average_price("BNBETH") {
        Ok(answer) => println!("{:?}", answer),
        Err(e) => println!("Error: {:?}", e),
    }

    // Best price/qty on the order book for ALL symbols
    match market.get_all_book_tickers() {
        Ok(answer) => println!("{:?}", answer),
        Err(e) => println!("Error: {:?}", e),
    }

    // Best price/qty on the order book for ONE symbol
    match market.get_book_ticker("BNBETH") {
        Ok(answer) => println!(
            "Bid Price: {}, Ask Price: {}",
            answer.bid_price, answer.ask_price
        ),
        Err(e) => println!("Error: {:?}", e),
    }

    // 24hr ticker price change statistics
    match market.get_24h_price_stats("BNBETH") {
        Ok(answer) => println!(
            "Open Price: {}, Higher Price: {}, Lower Price: {:?}",
            answer.open_price, answer.high_price, answer.low_price
        ),
        Err(e) => println!("Error: {:?}", e),
    }

    // last 10 5min klines (candlesticks) for a symbol:
    match market.get_klines("BNBETH", "5m", 10, None, None) {
        Ok(klines) => {   
            match klines {
                binance::model::KlineSummaries::AllKlineSummaries(klines) => {
                    let kline: KlineSummary = klines[0].clone(); // You need to iterate over the klines
                    println!(
                        "Open: {}, High: {}, Low: {}",
                        kline.open, kline.high, kline.low
                    )
                }
            }
        },
        Err(e) => println!("Error: {}", e),
    }
}

账户数据

use binance::api::*;
use binance::account::*;

fn main() {
    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);

    match account.get_account() {
        Ok(answer) => println!("{:?}", answer.balances),
        Err(e) => println!("Error: {:?}", e),
    }

    match account.get_open_orders("WTCETH") {
        Ok(answer) => println!("{:?}", answer),
        Err(e) => println!("Error: {:?}", e),
    }

    match account.limit_buy("WTCETH", 10, 0.014000) {
        Ok(answer) => println!("{:?}", answer),
        Err(e) => println!("Error: {:?}", e),
    }

    match account.market_buy("WTCETH", 5) {
        Ok(answer) => println!("{:?}", answer),
        Err(e) => println!("Error: {:?}", e),
    }

    match account.limit_sell("WTCETH", 10, 0.035000) {
        Ok(answer) => println!("{:?}", answer),
        Err(e) => println!("Error: {:?}", e),
    }

    match account.market_sell("WTCETH", 5) {
        Ok(answer) => println!("{:?}", answer),
        Err(e) => println!("Error: {:?}", e),
    }

    match account.custom_order("WTCETH", 9999, 0.0123, "SELL", "LIMIT", "IOC") {
        Ok(answer) => println!("{:?}", answer),
        Err(e) => println!("Error: {:?}", e),
    }

    let order_id = 1_957_528;
    match account.order_status("WTCETH", order_id) {
        Ok(answer) => println!("{:?}", answer),
        Err(e) => println!("Error: {:?}", e),
    }

    match account.cancel_order("WTCETH", order_id) {
        Ok(answer) => println!("{:?}", answer),
        Err(e) => println!("Error: {:?}", e),
    }

    match account.cancel_all_open_orders("WTCETH") {
        Ok(answer) => println!("{:?}", answer),
        Err(e) => println!("Error: {:?}", e),
    }

    match account.get_balance("KNC") {
        Ok(answer) => println!("{:?}", answer),
        Err(e) => println!("Error: {:?}", e),
    }

    match account.trade_history("WTCETH") {
        Ok(answer) => println!("{:?}", answer),
        Err(e) => println!("Error: {:?}", e),
    }
}

错误处理

提供更详细的错误信息

您可以查看 Binance 错误代码

use binance::errors::ErrorKind as BinanceLibErrorKind;

[...]

Err(err) => {
    println!("Can't put an order!");

    match err.0 {
        BinanceLibErrorKind::BinanceError(response) => match response.code {
            -1013_i16 => println!("Filter failure: LOT_SIZE!"),
            -2010_i16 => println!("Funds insufficient! {}", response.msg),
            _ => println!("Non-catched code {}: {}", response.code, response.msg),
        },
        BinanceLibErrorKind::Msg(msg) => {
            println!("Binancelib error msg: {}", msg)
        }
        _ => println!("Other errors: {}.", err.0),
    };
}

测试网和 API 集群

如果端点存在性能问题,您可以覆盖默认的 binance api urls。

您还可以查看 Binance API 集群

同样适用于测试网和 Binance.US 支持。以下是一个示例

let general: General = if use_testnet {
    let config = Config::default().set_rest_api_endpoint("https://testnet.binance.vision");
                                  // .set_ws_endpoint("wss://testnet.binance.vision/ws")
                                  // .set_futures_rest_api_endpoint("https://testnet.binancefuture.com/api")
                                  // .set_futures_ws_endpoint("https://testnet.binancefuture.com/ws")
    Binance::new_with_config(None, None, &config)
} else {
    Binance::new(None, None)
};

用户流配置

use binance::api::*;
use binance::userstream::*;

fn main() {
    let api_key_user = Some("YOUR_API_KEY".into());
    let user_stream: UserStream = Binance::new(api_key_user.clone(), None);

    if let Ok(answer) = user_stream.start() {
        println!("Data Stream Started ...");
        let listen_key = answer.listen_key;

        match user_stream.keep_alive(&listen_key) {
            Ok(msg) => println!("Keepalive user data stream: {:?}", msg),
            Err(e) => println!("Error: {:?}", e),
        }

        match user_stream.close(&listen_key) {
            Ok(msg) => println!("Close user data stream: {:?}", msg),
            Err(e) => println!("Error: {:?}", e),
        }
    } else {
        println!("Not able to start an User Stream (Check your API_KEY)");
    }
}

用户流

use binance::api::*;
use binance::userstream::*;
use binance::websockets::*;
use std::sync::atomic::{AtomicBool};

fn main() {
    let api_key_user = Some("YOUR_KEY".into());
    let keep_running = AtomicBool::new(true); // Used to control the event loop
    let user_stream: UserStream = Binance::new(api_key_user, None);

    if let Ok(answer) = user_stream.start() {
	let listen_key = answer.listen_key;

	let mut web_socket = WebSockets::new(|event: WebsocketEvent| {
	    match event {
		WebsocketEvent::AccountUpdate(account_update) => {
		    for balance in &account_update.balance {
			println!("Asset: {}, free: {}, locked: {}", balance.asset, balance.free, balance.locked);
		    }
		},
		WebsocketEvent::OrderTrade(trade) => {
		    println!("Symbol: {}, Side: {}, Price: {}, Execution Type: {}", trade.symbol, trade.side, trade.price, trade.execution_type);
		},
		_ => (),
	    };
	    Ok(())
	});

	web_socket.connect(&listen_key).unwrap(); // check error
	    if let Err(e) = web_socket.event_loop(&keep_running) {
		match e {
		    err => {
		        println!("Error: {:?}", err);
		    }
		}
	     }
	} else {
	    println!("Not able to start an User Stream (Check your API_KEY)");
	}
}

交易

use binance::websockets::*;
use std::sync::atomic::{AtomicBool};

fn main() {
    let keep_running = AtomicBool::new(true); // Used to control the event loop
    let agg_trade = format!("!ticker@arr"); // All Symbols
    let mut web_socket = WebSockets::new(|event: WebsocketEvent| {
	match event {
        // 24hr rolling window ticker statistics for all symbols that changed in an array.
	    WebsocketEvent::DayTickerAll(ticker_events) => {
	        for tick_event in ticker_events {
		    if tick_event.symbol == "BTCUSDT" {
			let btcusdt: f32 = tick_event.average_price.parse().unwrap();
			let btcusdt_close: f32 = tick_event.current_close.parse().unwrap();
			println!("{} - {}", btcusdt, btcusdt_close);
		    }
		}
	    },
	    _ => (),
        };

        Ok(())
    });

    web_socket.connect(&agg_trade).unwrap(); // check error
    if let Err(e) = web_socket.event_loop(&keep_running) {
	match e {
	    err => {
	        println!("Error: {:?}", err);
	    }
	}
     }
}

蜡烛图

use binance::websockets::*;
use std::sync::atomic::{AtomicBool};

fn main() {
    let keep_running = AtomicBool::new(true); // Used to control the event loop
    let kline = format!("{}", "ethbtc@kline_1m");
    let mut web_socket = WebSockets::new(|event: WebsocketEvent| {
        match event {
            WebsocketEvent::Kline(kline_event) => {
                println!("Symbol: {}, high: {}, low: {}", kline_event.kline.symbol, kline_event.kline.low, kline_event.kline.high);
            },
            _ => (),
        };
        Ok(())
    });
 
    web_socket.connect(&kline).unwrap(); // check error
    if let Err(e) = web_socket.event_loop(&keep_running) {
        match e {
          err => {
             println!("Error: {:?}", err);
          }
        }
     }
     web_socket.disconnect().unwrap();
}

多流

use binance::websockets::*;
use std::sync::atomic::{AtomicBool};

fn main() {
    let endpoints = ["ETHBTC", "BNBETH"]
        .map(|symbol| format!("{}@depth@100ms", symbol.to_lowercase()));

    let keep_running = AtomicBool::new(true);
    let mut web_socket = WebSockets::new(|event: WebsocketEvent| {
        if let WebsocketEvent::DepthOrderBook(depth_order_book) = event {
            println!("{:?}", depth_order_book);
        }

        Ok(())
    });

    web_socket.connect_multiple_streams(&endpoints).unwrap(); // check error
    if let Err(e) = web_socket.event_loop(&keep_running) {
        println!("Error: {:?}", e);
    }
    web_socket.disconnect().unwrap();
}

其他交易所

如果您使用 Bitfinex,请查看我的 Rust 库用于 Bitfinex API

依赖项

~6–20MB
~323K SLoC