1use crate::calculation_cluster::CalculationCluster;
2use crate::config::Configuration;
3use crate::depth_cache::DepthCache;
4use crate::trading_pair::TradingPair;
5use crate::triangular_relationship::TriangularRelationship;
6use binance::api::*;
7use binance::general::*;
8use binance::model::*;
9use console::style;
10use std::collections::HashMap;
11use std::fmt;
12
13#[allow(non_camel_case_types)]
17pub struct bTrader {
18 calculation_cluster: CalculationCluster,
19}
20
21impl fmt::Display for bTrader {
22 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
23 write!(f, "<bTrader>")
24 }
25}
26
27impl bTrader {
28 pub fn new(config_path: &str) -> bTrader {
30 let config: Configuration = Configuration::new(config_path);
32 print!("{} Connecting to Binance...", style("[1/7]").bold().dim(),);
34 let general: General = Binance::new(None, None);
35 println!(" Successfully connected!");
36 print!("{} Getting trading pairs...", style("[2/7]").bold().dim(),);
38 let mut pairs: Vec<TradingPair> = Vec::new();
39 let result = match general.exchange_info() {
40 Ok(answer) => answer,
41 Err(e) => panic!("Error on getting exchange info: {}", e),
42 };
43 for symbol in &result.symbols {
44 if symbol.status == "TRADING" {
46 let mut step: f64 = 0.0;
47 for filter in &symbol.filters {
49 if let Filters::LotSize {
50 min_qty: _,
51 max_qty: _,
52 step_size,
53 } = filter
54 {
55 step = step_size.parse().unwrap()
56 };
57 }
58 pairs.push(TradingPair::new(
59 symbol.symbol.to_string(),
60 symbol.base_asset.to_string(),
61 symbol.quote_asset.to_string(),
62 step,
63 ));
64 }
65 }
66 println!(" {} symbols found!", pairs.len());
67 print!(
69 "{} Getting arbitrage deal starters...",
70 style("[3/7]").bold().dim(),
71 );
72 let mut starters: Vec<TradingPair> = Vec::new();
73 for pair in &pairs {
74 if pair.has_asset(config.investment_base.to_string()) {
75 starters.push(pair.clone());
76 }
77 }
78 println!(
79 " {} symbols could start or end a triangular operation.",
80 starters.len()
81 );
82 print!(
84 "{} Computing triangular relationships...",
85 style("[4/7]").bold().dim(),
86 );
87 let mut relationships: HashMap<String, TriangularRelationship> = HashMap::new();
88 let mut socket_pairs: Vec<String> = Vec::new();
89 for (i, start_pair) in starters[0..starters.len() - 1].iter().enumerate() {
90 for end_pair in starters[i + 1..starters.len()].iter() {
91 let middle = TradingPair::new(
92 "".to_string(),
93 start_pair.get_the_other(config.investment_base.to_string()),
94 end_pair.get_the_other(config.investment_base.to_string()),
95 0.0,
96 );
97 for middle_pair in pairs.iter() {
98 if middle_pair == &middle {
99 if !socket_pairs.contains(&start_pair.get_symbol()) {
101 socket_pairs.push(start_pair.get_symbol());
102 }
103 if !socket_pairs.contains(&middle_pair.get_symbol()) {
105 socket_pairs.push(middle_pair.get_symbol());
106 }
107 if !socket_pairs.contains(&end_pair.get_symbol()) {
109 socket_pairs.push(end_pair.get_symbol());
110 }
111 relationships.insert(
112 format!(
113 "{} -> {} -> {}",
114 start_pair.get_symbol(),
115 middle_pair.get_symbol(),
116 end_pair.get_symbol()
117 ),
118 TriangularRelationship::new(
119 config.investment_base.to_string(),
120 TradingPair::new(
121 start_pair.get_symbol(),
122 start_pair.get_base_asset(),
123 start_pair.get_quote_asset(),
124 start_pair.get_step(),
125 ),
126 TradingPair::new(
127 middle_pair.get_symbol(),
128 middle_pair.get_base_asset(),
129 middle_pair.get_quote_asset(),
130 middle_pair.get_step(),
131 ),
132 TradingPair::new(
133 end_pair.get_symbol(),
134 end_pair.get_base_asset(),
135 end_pair.get_quote_asset(),
136 end_pair.get_step(),
137 ),
138 ),
139 );
140 break;
141 }
142 }
143 }
144 }
145 println!(
146 " {} triangular relationships found, will have to handle {} websockets",
147 relationships.len(),
148 socket_pairs.len()
149 );
150 let depth_cache = DepthCache::new(&socket_pairs, 8, 1);
151 let calculation_cluster = CalculationCluster::new(relationships, depth_cache, config);
152 bTrader {
153 calculation_cluster,
154 }
155 }
156 pub fn run(&self) {
158 self.calculation_cluster.start();
159 }
160}