Skip to content

Commit db12f61

Browse files
committed
wip: unified methods across markets. lacking: associate Market with Exchange
1 parent 7985643 commit db12f61

File tree

5 files changed

+109
-56
lines changed

5 files changed

+109
-56
lines changed

examples/bybit/market.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
use std::env;
22

3-
use v_exchanges::{bybit::Bybit, core::Exchange};
3+
use v_exchanges::{bybit::Bybit, core::Exchange, Market};
44

55
#[tokio::main]
66
async fn main() {
77
color_eyre::install().unwrap();
88
v_utils::utils::init_subscriber(v_utils::utils::LogDestination::xdg("v_exchanges"));
99

10+
let m: Market = "Bybit/Linear".into();
11+
let mut bb = m.client();
1012
let mut bb = Bybit::default();
1113

1214
//let ticker: serde_json::Value =
@@ -17,7 +19,7 @@ async fn main() {
1719

1820
//let klines = bb.futures_klines(("BTC", "USDT").into(), "1m".into(), 2.into()).await.unwrap();
1921
//dbg!(&klines);
20-
let price = bb.futures_price(("BTC", "USDT").into()).await.unwrap();
22+
let price = bb.price(("BTC", "USDT").into(), m).await.unwrap();
2123
dbg!(&price);
2224

2325
if let (Ok(key), Ok(secret)) = (env::var("BYBIT_TIGER_READ_KEY"), env::var("BYBIT_TIGER_READ_SECRET")) {

v_exchanges/src/binance/mod.rs

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use eyre::Result;
88
use v_exchanges_adapters::Client;
99
use v_utils::trades::{Asset, Pair, Timeframe};
1010

11-
use crate::core::{AssetBalance, Exchange, Klines, KlinesRequestRange};
11+
use crate::core::{AssetBalance, Exchange, Klines, KlinesRequestRange, Market as M};
1212

1313
#[derive(Clone, Debug, Default, Deref, DerefMut)]
1414
pub struct Binance(pub Client);
@@ -20,32 +20,40 @@ impl Exchange for Binance {
2020
self.update_default_option(BinanceOption::Secret(secret.into()));
2121
}
2222

23-
async fn spot_klines(&self, pair: Pair, tf: Timeframe, range: KlinesRequestRange) -> Result<Klines> {
24-
market::klines(&self.0, pair, tf, range, Market::Spot).await
23+
async fn klines(&self, pair: Pair, tf: Timeframe, range: KlinesRequestRange, m: M) -> Result<Klines> {
24+
match m {
25+
M::Binance(m) => market::klines(&self.0, pair, tf, range, m).await,
26+
_ => unimplemented!(),
27+
}
2528
}
2629

27-
async fn spot_prices(&self, pairs: Option<Vec<Pair>>) -> Result<Vec<(Pair, f64)>> {
28-
spot::market::prices(&self.0, pairs).await
30+
async fn prices(&self, pairs: Option<Vec<Pair>>, m: M) -> Result<Vec<(Pair, f64)>> {
31+
match m {
32+
M::Binance(Market::Spot) => spot::market::prices(&self.0, pairs).await,
33+
_ => unimplemented!(),
34+
}
2935
}
3036

31-
async fn spot_price(&self, pair: Pair) -> Result<f64> {
32-
spot::market::price(&self.0, pair).await
37+
async fn price(&self, pair: Pair, m: M) -> Result<f64> {
38+
match m {
39+
M::Binance(Market::Spot) => spot::market::price(&self.0, pair).await,
40+
M::Binance(Market::Futures) => futures::market::price(&self.0, pair).await,
41+
_ => unimplemented!(),
42+
}
3343
}
3444

35-
async fn futures_klines(&self, pair: Pair, tf: Timeframe, range: KlinesRequestRange) -> Result<Klines> {
36-
market::klines(&self.0, pair, tf, range, Market::Futures).await
45+
async fn asset_balance(&self, asset: Asset, m: M) -> Result<AssetBalance> {
46+
match m {
47+
M::Binance(Market::Futures) => futures::account::asset_balance(self, asset).await,
48+
_ => unimplemented!(),
49+
}
3750
}
3851

39-
async fn futures_price(&self, pair: Pair) -> Result<f64> {
40-
futures::market::price(&self.0, pair).await
41-
}
42-
43-
async fn futures_asset_balance(&self, asset: Asset) -> Result<AssetBalance> {
44-
futures::account::asset_balance(&self.0, asset).await
45-
}
46-
47-
async fn futures_balances(&self) -> Result<Vec<AssetBalance>> {
48-
futures::account::balances(&self.0).await
52+
async fn balances(&self, m: M) -> Result<Vec<AssetBalance>> {
53+
match m {
54+
M::Binance(Market::Futures) => futures::account::balances(&self.0).await,
55+
_ => unimplemented!(),
56+
}
4957
}
5058
}
5159

@@ -56,3 +64,8 @@ pub enum Market {
5664
Spot,
5765
Margin,
5866
}
67+
impl Market {
68+
pub fn client(&self) -> Box<dyn Exchange> {
69+
Box::new(Binance::default())
70+
}
71+
}

v_exchanges/src/bybit/mod.rs

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use eyre::Result;
88
use v_exchanges_adapters::Client;
99
use v_utils::trades::{Asset, Pair, Timeframe};
1010

11-
use crate::core::{AssetBalance, Exchange, Klines, KlinesRequestRange};
11+
use crate::core::{Market as M, AssetBalance, Exchange, Klines, KlinesRequestRange};
1212

1313
#[derive(Clone, Debug, Default, Deref, DerefMut)]
1414
pub struct Bybit(pub Client);
@@ -20,35 +20,37 @@ impl Exchange for Bybit {
2020
self.update_default_option(BybitOption::Secret(secret.into()));
2121
}
2222

23-
async fn spot_klines(&self, pair: Pair, tf: Timeframe, range: KlinesRequestRange) -> Result<Klines> {
24-
todo!();
23+
async fn klines(&self, pair: Pair, tf: Timeframe, range: KlinesRequestRange, m: M) -> Result<Klines> {
24+
match m {
25+
M::Bybit(Market::Linear) => market::klines(&self.0, pair, tf, range).await,
26+
_ => unimplemented!(),
27+
}
2528
}
2629

27-
async fn spot_prices(&self, pairs: Option<Vec<Pair>>) -> Result<Vec<(Pair, f64)>> {
28-
todo!();
30+
async fn price(&self, pair: Pair, m: M) -> Result<f64> {
31+
match m {
32+
M::Bybit(Market::Linear) => market::price(&self.0, pair).await,
33+
_ => unimplemented!(),
34+
}
2935
}
3036

31-
async fn spot_price(&self, symbol: Pair) -> Result<f64> {
37+
async fn prices(&self, pairs: Option<Vec<Pair>>, m: M) -> Result<Vec<(Pair, f64)>> {
3238
todo!();
3339
}
3440

35-
async fn futures_klines(&self, symbol: Pair, tf: Timeframe, range: KlinesRequestRange) -> Result<Klines> {
36-
market::klines(&self.0, symbol, tf, range).await
41+
async fn asset_balance(&self, asset: Asset, m: M) -> Result<AssetBalance> {
42+
match m {
43+
M::Bybit(Market::Linear) => account::asset_balance(&self.0, asset).await,
44+
_ => unimplemented!(),
45+
}
3746
}
3847

39-
async fn futures_price(&self, symbol: Pair) -> Result<f64> {
40-
market::price(&self.0, symbol).await
48+
async fn balances(&self, m: M) -> Result<Vec<AssetBalance>> {
49+
match m{
50+
M::Bybit(Market::Linear) => account::balances(&self.0).await,
51+
_ => unimplemented!(),
52+
}
4153
}
42-
43-
async fn futures_asset_balance(&self, asset: Asset) -> Result<AssetBalance> {
44-
account::asset_balance(&self.0, asset).await
45-
}
46-
47-
async fn futures_balances(&self) -> Result<Vec<AssetBalance>> {
48-
account::balances(&self.0).await
49-
}
50-
51-
//DO: async fn balance(&self,
5254
}
5355

5456

@@ -59,3 +61,8 @@ pub enum Market {
5961
Spot,
6062
Inverse,
6163
}
64+
impl Market {
65+
pub fn client(&self) -> Box<impl Exchange> {
66+
Box::new(Bybit::default())
67+
}
68+
}

v_exchanges/src/core.rs

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,28 @@ use chrono::{DateTime, TimeDelta, Utc};
44
use derive_more::{Deref, DerefMut};
55
use eyre::{Report, Result};
66
use v_utils::trades::{Asset, Kline, Pair, Timeframe};
7+
use eyre::bail;
78
use crate::{binance, bybit};
89

910
//TODO!!!!!!!!!!!!!: klines switch to defining the range via an Enum over either limit either start and end times
1011

1112
pub trait Exchange {
1213
fn auth<S: Into<String>>(&mut self, key: S, secret: S);
1314

14-
fn spot_klines(&self, pair: Pair, tf: Timeframe, range: KlinesRequestRange) -> impl std::future::Future<Output = Result<Klines>> + Send;
15-
fn spot_price(&self, pair: Pair) -> impl std::future::Future<Output = Result<f64>> + Send;
16-
/// If no symbols are specified, returns all spot prices.
17-
fn spot_prices(&self, pairs: Option<Vec<Pair>>) -> impl std::future::Future<Output = Result<Vec<(Pair, f64)>>> + Send;
18-
1915
//? should I have Self::Pair too? Like to catch the non-existent ones immediately? Although this would increase the error surface on new listings.
20-
fn futures_klines(&self, pair: Pair, tf: Timeframe, range: KlinesRequestRange) -> impl std::future::Future<Output = Result<Klines>> + Send;
21-
fn futures_price(&self, pair: Pair) -> impl std::future::Future<Output = Result<f64>> + Send;
16+
fn klines(&self, pair: Pair, tf: Timeframe, range: KlinesRequestRange, market: Market) -> impl std::future::Future<Output = Result<Klines>> + Send;
17+
18+
/// If no pairs are specified, returns for all;
19+
fn prices(&self, pairs: Option<Vec<Pair>>, market: Market) -> impl std::future::Future<Output = Result<Vec<(Pair, f64)>>> + Send;
20+
fn price(&self, pair: Pair, market: Market) -> impl std::future::Future<Output = Result<f64>> + Send;
2221

2322
// Defined in terms of actors
2423
//TODO!!!: fn spawn_klines_listener(&self, symbol: Pair, tf: Timeframe) -> mpsc::Receiver<Kline>;
2524

2625
/// balance of a specific asset
27-
fn futures_asset_balance(&self, asset: Asset) -> impl std::future::Future<Output = Result<AssetBalance>> + Send;
26+
fn asset_balance(&self, asset: Asset, market: Market) -> impl std::future::Future<Output = Result<AssetBalance>> + Send;
2827
/// vec of balances of specific assets
29-
fn futures_balances(&self) -> impl std::future::Future<Output = Result<Vec<AssetBalance>>> + Send;
28+
fn balances(&self, market: Market) -> impl std::future::Future<Output = Result<Vec<AssetBalance>>> + Send;
3029
//? potentially `total_balance`? Would return precompiled USDT-denominated balance of a (bybit::wallet/binance::account)
3130
// balances are defined for each margin type: [futures_balance, spot_balance, margin_balance], but note that on some exchanges, (like bybit), some of these may point to the same exact call
3231
// to negate confusion could add a `total_balance` endpoint
@@ -155,6 +154,14 @@ pub enum Market {
155154
Bybit(bybit::Market),
156155
//TODO
157156
}
157+
impl Market {
158+
pub fn client(&self) -> Box<impl Exchange> {
159+
match self {
160+
Market::Binance(m) => m.client(),
161+
Market::Bybit(m) => m.client(),
162+
}
163+
}
164+
}
158165
impl Default for Market {
159166
fn default() -> Self {
160167
Self::Binance(binance::Market::default())
@@ -178,12 +185,35 @@ impl std::str::FromStr for Market {
178185
if parts.len() != 2 {
179186
return Err(eyre::eyre!("Invalid market string: {}", s));
180187
}
181-
let market = parts[0];
182-
let exchange = parts[1];
183-
match market.to_lowercase().as_str() {
184-
"binance" => Ok(Self::Binance(exchange.parse()?)),
185-
"bybit" => Ok(Self::Bybit(exchange.parse()?)),
186-
_ => Err(eyre::eyre!("Invalid market string: {}", s)),
188+
let exchange = parts[0];
189+
let sub_market = parts[1];
190+
match exchange.to_lowercase().as_str() {
191+
"binance" => Ok(Self::Binance(sub_market.parse()?)),
192+
"bybit" => Ok(Self::Bybit({
193+
match sub_market.parse() {
194+
Ok(m) => m,
195+
Err(e) => match sub_market.to_lowercase() == "futures" {
196+
true => bybit::Market::Linear,
197+
false => bail!(e),
198+
}
199+
}
200+
})),
201+
_ => bail!("Invalid market string: {}", s),
187202
}
188203
}
189204
}
205+
impl From<Market> for String {
206+
fn from(value: Market) -> Self {
207+
value.to_string()
208+
}
209+
}
210+
impl From<String> for Market {
211+
fn from(value: String) -> Self {
212+
value.parse().unwrap()
213+
}
214+
}
215+
impl From<&str> for Market {
216+
fn from(value: &str) -> Self {
217+
value.parse().unwrap()
218+
}
219+
}

v_exchanges/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
pub extern crate v_exchanges_adapters as adapters;
22

3+
pub use core::Market;
34
pub mod core;
45

56
pub mod binance;

0 commit comments

Comments
 (0)