Repository: yasstake/rbot (language: python)

Issue:
BoardのDepthを適宜切り取る
BoardnoWSのDepthは有限のため、エッジから遠いデータが切れる。
１０００以上のデータは信用できないので、たとえば適宜９５０、１０００あたりでデータを削除する。
VAP(Volume At Price)を作る

LinuxでのActionsでのBUILD失敗対応（SSL)
SSLのライブラリ周辺でコンパイルエラーが出ているので確認＆修正する。
ChartクラスのOHLC対応
vがない場合はVolumeエリアを非表示にする。
Calncel Orderの実装
Session#
   cancel_order(order_id)
   cancel_order_all()

の実装。
戻り値はキャンセルされたオーダー数。

成り行き注文の方法を考える



Discussion / hints:





約定価格を一定期間の間の最悪値にするのはどうか？
約定したときの平均値にしてみる。
takerFeeを導入する。

Fix patch:
diff --git a/Cargo.toml b/Cargo.toml
index 5a66f60d..583c657a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "rbot"
-version = "0.2.4"
+version = "0.2.5"
 edition = "2021"
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
diff --git a/src/common/order.rs b/src/common/order.rs
index 90cb443f..1dee2fa0 100644
--- a/src/common/order.rs
+++ b/src/common/order.rs
@@ -134,13 +134,6 @@ impl From<&str> for OrderSide {
     }
 }
 
-/*
-impl Into<String> for OrderSide {
-    fn into(self) -> String {
-        self.to_string()
-    }
-}
-*/
 
 #[pymethods]
 impl OrderSide {
diff --git a/src/db/df.rs b/src/db/df.rs
index 1ee02768..05b442ab 100644
--- a/src/db/df.rs
+++ b/src/db/df.rs
@@ -11,10 +11,10 @@ use polars::prelude::DynamicGroupOptions;
 use polars::prelude::NamedFrom;
 use polars::prelude::Series;
 use polars_core::prelude::SortOptions;
-use polars_lazy::dsl::{lit, AggExpr, Expr};
+
 use polars_lazy::frame::pivot::pivot;
 use polars_lazy::prelude::{col, LazyFrame};
-use polars_lazy::prelude::{IntoLazy, Literal, LiteralValue};
+use polars_lazy::prelude::IntoLazy;
 use polars_time::ClosedWindow;
 
 #[allow(non_upper_case_globals)]
@@ -406,7 +406,6 @@ pub fn vap_df_bak(df: &DataFrame, start_time: MicroSec, end_time: MicroSec) -> D
     vap
 }
 
-use polars::prelude::DataType;
 
 /// Calc Value At Price
 /// group by unit price and order_side
@@ -443,7 +442,7 @@ pub fn vap_df(df: &DataFrame, start_time: MicroSec, end_time: MicroSec, size: i6
     let floor_price = (floor_price.floor_div(size.into()) * size.into()).floor();
     let vap_gb = df.group_by([col(KEY::order_side), floor_price]);
 
-    let mut vap = vap_gb
+    let vap = vap_gb
         .agg([col(KEY::size).sum().alias(KEY::volume)])
         .collect()
         .unwrap();
@@ -577,12 +576,11 @@ pub fn convert_timems_to_datetime(df: &mut DataFrame) -> &DataFrame {
 
 use polars::prelude::*;
 use rust_decimal::prelude::ToPrimitive;
-use rust_decimal::Decimal;
 
 #[cfg(test)]
 mod test_df {
     use super::*;
-    use crate::{common::DAYS, db::df};
+    use crate::common::DAYS;
 
     #[test]
     fn test_simple_dynamic_group() {
@@ -725,11 +723,11 @@ mod test_df {
     #[test]
     fn test_make_ohlcv_datetime() {
         use polars::datatypes::TimeUnit;
-        use polars::datatypes::TimeZone;
 
-        let mut time = Series::new(KEY::time_stamp, Vec::<MicroSec>::new());
 
-        let mut t64 = time.i64().unwrap().clone();
+        let time = Series::new(KEY::time_stamp, Vec::<MicroSec>::new());
+
+        let t64 = time.i64().unwrap().clone();
         let date_time = t64.into_datetime(TimeUnit::Microseconds, None);
 
         let t = Series::new("time", date_time);
@@ -752,7 +750,7 @@ mod test_df {
         println!("{:?}", df);
 
         let time = df.column("time_stamp").unwrap().i64().unwrap().clone();
-        let mut date_time = time.into_datetime(TimeUnit::Microseconds, None);
+        let date_time = time.into_datetime(TimeUnit::Microseconds, None);
         let df = df.with_column(date_time).unwrap();
 
         println!("{:?}", df);
diff --git a/src/exchange/binance/config.rs b/src/exchange/binance/config.rs
index c1cab24b..ca003e49 100644
--- a/src/exchange/binance/config.rs
+++ b/src/exchange/binance/config.rs
@@ -1,3 +1,5 @@
+// Copyright(c) 2022-2023. yasstake. All rights reserved.
+
 use pyo3::{pyclass, pymethods};
 use rust_decimal_macros::dec;
 use serde_derive::{Serialize, Deserialize};
@@ -5,8 +7,6 @@ use serde_json::json;
 
 use crate::{fs::db_full_path, common::MarketConfig};
 
-
-
 #[derive(Clone, Debug, Serialize, Deserialize)]
 #[pyclass]
 pub struct BinanceConfig {
@@ -41,12 +41,14 @@ pub struct BinanceConfig {
 
 #[pymethods]
 impl BinanceConfig {
+    #[allow(non_snake_case)]
     #[classattr]
     pub fn BTCUSDT() -> Self {
         return BinanceConfig::SPOT("BTC", "USDT");
     }
 
     #[classattr]
+    #[allow(non_snake_case)]    
     pub fn TEST_BTCUSDT() -> Self {
         let mut config = BinanceConfig::TESTSPOT("BTC", "USDT");
 
@@ -56,6 +58,7 @@ impl BinanceConfig {
         return config;
     }
 
+    #[allow(non_snake_case)]    
     #[staticmethod]
     pub fn TESTSPOT(foreign_symbol: &str, home_symbol: &str) -> Self {
         let mut config = BinanceConfig::SPOT(foreign_symbol, home_symbol);
@@ -70,12 +73,7 @@ impl BinanceConfig {
         return config;
     }
 
-
-    // TODO: implement        
-    pub fn load_key(&mut self, file: &str) {
-
-    }
-
+    #[allow(non_snake_case)]    
     #[staticmethod]
     pub fn SPOT(foreign_symbol: &str, home_symbol: &str) -> Self {
 
@@ -100,7 +98,7 @@ impl BinanceConfig {
             "".to_string()
         };
 
-        let mut market_config = MarketConfig::new(
+        let market_config = MarketConfig::new(
             home_symbol,
             foreign_symbol,
             2,
@@ -160,16 +158,16 @@ impl BinanceConfig {
     pub fn __repr__(&self) -> String {
         let mut printobj = self.clone();
 
-        if printobj.api_key.len() > 4 {
-            printobj.api_key = format!("{}*******************", printobj.api_key[0..4].to_string());
+        if printobj.api_key.len() > 2 {
+            printobj.api_key = format!("{}*******************", printobj.api_key[0..2].to_string());
         } else {
             printobj.api_key = "!! NO KEY !!".to_string();
         }
 
-        if printobj.api_secret.len() > 4 {
+        if printobj.api_secret.len() > 2 {
             printobj.api_secret = format!(
                 "{}*******************",
-                printobj.api_secret[0..4].to_string()
+                printobj.api_secret[0..2].to_string()
             );
         } else {
             printobj.api_secret = "!! NO SECRET !!".to_string();
diff --git a/src/exchange/binance/market.rs b/src/exchange/binance/market.rs
index 1b65dc60..037fc814 100644
--- a/src/exchange/binance/market.rs
+++ b/src/exchange/binance/market.rs
@@ -1,4 +1,4 @@
-// Copyright(c) 2022. yasstake. All rights reserved.
+// Copyright(c) 2022-2023. yasstake. All rights reserved.
 
 use chrono::Datelike;
 use csv::StringRecord;
@@ -26,9 +26,10 @@ use crate::exchange::binance::message::{BinancePublicWsMessage, BinanceWsRespond
 
 use super::message::BinanceUserStreamMessage;
 use super::message::{
-    BinanceListOrdersResponse, BinanceOrderResponse, BinanceOrderStatus, BinanceWsBoardUpdate,
+    BinanceListOrdersResponse, BinanceOrderStatus, BinanceWsBoardUpdate,
+    BinanceAccountInformation
 };
-use super::rest::cancel_order;
+use super::rest::{cancel_order, get_balance};
 use super::rest::cancell_all_orders;
 use super::rest::open_orders;
 use super::rest::{insert_trade_db, new_limit_order, new_market_order, order_status, trade_list};
@@ -50,7 +51,6 @@ pub struct BinanceAccount {
     pub subaccount: String,
 }
 
-
 #[derive(Debug)]
 pub struct BinanceOrderBook {
     config: BinanceConfig,
@@ -349,6 +349,7 @@ impl BinanceMarket {
 
     // TODO: implment retry logic
     pub fn start_market_stream(&mut self) {
+
         let endpoint = &self.config.public_ws_endpoint;
         let subscribe_message: Value =
             serde_json::from_str(&self.config.public_subscribe_message).unwrap();
@@ -391,10 +392,19 @@ impl BinanceMarket {
                     match message.clone() {
                         BinancePublicWsMessage::Trade(trade) => {
                             log::debug!("Trade: {:?}", trade);
-                            db_channel.send(vec![trade.to_trade()]);
+                            let r = db_channel.send(vec![trade.to_trade()]);
+                            
+                            if r.is_err() {
+                                log::error!("Error in db_channel.send: {:?} {:?}", trade, r);
+                            }
 
                             let multi_agent_channel = agent_channel.borrow_mut();
-                            multi_agent_channel.lock().unwrap().send(message.into());
+                            
+                            let r = multi_agent_channel.lock().unwrap().send(message.into());
+
+                            if r.is_err() {
+                                log::error!("Error in agent_channel.send: {:?} {:?}", trade, r);
+                            }
                         }
                         BinancePublicWsMessage::BoardUpdate(board_update) => {
                             board.lock().unwrap().update(&board_update);
@@ -414,6 +424,7 @@ impl BinanceMarket {
         log::info!("start_market_stream");
     }
 
+    /*
     // TODO: 単に待っているだけなので、終了処理を実装する。
     pub fn stop_market_stream(&mut self) {
         match self.public_handler.take() {
@@ -423,6 +434,7 @@ impl BinanceMarket {
             None => {}
         }
     }
+    */
 
     pub fn start_user_stream(&mut self) {
         let mut agent_channel = self.channel.clone();
@@ -442,6 +454,7 @@ impl BinanceMarket {
         log::info!("start_user_stream");
     }
 
+    /*
     pub fn stop_user_stream(&mut self) {
         match self.user_handler.take() {
             Some(h) => {
@@ -450,6 +463,7 @@ impl BinanceMarket {
             None => {}
         }
     }
+    */
 
     pub fn is_user_stream_running(&self) -> bool {
         if let Some(handler) = &self.user_handler {
@@ -496,29 +510,32 @@ impl BinanceMarket {
         return channel;
     }
 
+    /*
     #[pyo3(signature = (side, price, size, client_order_id=None))]
     pub fn new_limit_order_raw(
         &self,
-        side: OrderSide,
+        side: &str,
         price: Decimal,
         size: Decimal,
         client_order_id: Option<&str>,
     ) -> PyResult<BinanceOrderResponse> {
         let price_scale = self.config.market_config.price_scale;
         let size_scale = self.config.market_config.size_scale;
+        let order_side = OrderSide::from(side);
 
         let price = price.round_dp(price_scale);
         let size = size.round_dp(size_scale);
 
-        let response = new_limit_order(&self.config, side, price, size, client_order_id);
+        let response = new_limit_order(&self.config, order_side, price, size, client_order_id);
 
         convert_pyresult(response)
     }
+    */
 
     #[pyo3(signature = (side, price, size, client_order_id=None))]
     pub fn limit_order(
         &self,
-        side: OrderSide,
+        side: &str,
         price: Decimal,
         size: Decimal,
         client_order_id: Option<&str>,
@@ -528,8 +545,9 @@ impl BinanceMarket {
 
         let size_scale = self.config.market_config.size_scale;
         let size_dp = size.round_dp(size_scale);
+        let order_side = OrderSide::from(side);
 
-        let response = new_limit_order(&self.config, side, price_dp, size_dp, client_order_id);
+        let response = new_limit_order(&self.config, order_side, price_dp, size_dp, client_order_id);
 
         if response.is_err() {
             log::error!(
@@ -559,30 +577,36 @@ impl BinanceMarket {
         convert_pyresult(response)
     }
 
+    /*
     pub fn new_market_order_raw(
         &self,
-        side: OrderSide,
+        side: &str,
         size: Decimal,
         client_order_id: Option<&str>,
     ) -> PyResult<BinanceOrderResponse> {
         let size_scale = self.config.market_config.size_scale;
         let size = size.round_dp(size_scale);
 
-        let response = new_market_order(&self.config, side, size, client_order_id);
+        let order_side = OrderSide::from(side);
+
+        let response = new_market_order(&self.config, order_side, size, client_order_id);
 
         convert_pyresult(response)
     }
+    */
 
     pub fn market_order(
         &self,
-        side: OrderSide,
+        side: &str,
         size: Decimal,
         client_order_id: Option<&str>,
     ) -> PyResult<Vec<Order>> {
         let size_scale = self.config.market_config.size_scale;
         let size = size.round_dp(size_scale);
+        
+        let order_side = OrderSide::from(side);
 
-        let response = new_market_order(&self.config, side, size, client_order_id);
+        let response = new_market_order(&self.config, order_side, size, client_order_id);
 
         if response.is_err() {
             log::error!(
@@ -650,6 +674,13 @@ impl BinanceMarket {
     pub fn get_market_config(&self) -> MarketConfig {
         return self.config.market_config.clone();
     }
+
+    #[getter]
+    pub fn get_account(&self) -> PyResult<BinanceAccountInformation> {
+        let status = get_balance(&self.config);
+
+        convert_pyresult(status)
+    }
 }
 
 use crate::exchange::binance::rest::get_board_snapshot;
@@ -761,9 +792,6 @@ impl BinanceMarket {
             }
         }
     }
-
-    fn write_message_to_channel(&mut self, message: MarketMessage) {
-    }
 }
 
 #[cfg(test)]
@@ -777,7 +805,6 @@ mod binance_test {
     #[test]
     fn test_make_historical_data_url_timestamp() {
         init_log();
-        let market = BinanceMarket::new(&BinanceConfig::BTCUSDT());
         println!(
             "{}",
             BinanceMarket::make_historical_data_url_timestamp("BTCUSD", 1)
diff --git a/src/exchange/binance/message.rs b/src/exchange/binance/message.rs
index 1e43ebed..4f51e885 100644
--- a/src/exchange/binance/message.rs
+++ b/src/exchange/binance/message.rs
@@ -1,18 +1,17 @@
-use std::str::FromStr;
+// Copyright(c) 2022-2023. yasstake. All rights reserved.
 
+use std::str::FromStr;
 use pyo3::{pyclass, pymethods};
 use rust_decimal::Decimal;
 use rust_decimal_macros::dec;
-use serde::de::{self, Deserialize, Deserializer};
 use serde_derive::{Deserialize, Serialize};
-use strum_macros::Display;
 
 use crate::{
     common::{
-        AccountChange, MarketMessage, MicroSec,
-        {Order, OrderFill, OrderSide, OrderStatus, OrderType, Trade}, AccountStatus, string_to_side, orderside_deserialize, ordertype_deserialize, orderstatus_deserialize, string_to_status,
+        MarketMessage, 
+        Order, OrderSide, OrderStatus, OrderType, Trade, AccountStatus, string_to_side, orderside_deserialize, ordertype_deserialize, orderstatus_deserialize,
     },
-    exchange::{string_to_decimal, BoardItem, binance},
+    exchange::{string_to_decimal, BoardItem},
 };
 
 use super::{super::string_to_f64, binance_to_microsec, BinanceConfig, Market};
@@ -264,6 +263,7 @@ struct BinanceOrderResponse will parse below json.
     ]
   }
 */
+#[allow(non_snake_case)]
 #[pyclass]
 #[derive(Debug, Serialize, Deserialize)]
 pub struct BinanceOrderFill {
@@ -350,7 +350,7 @@ impl From<BinanceOrderResponse> for Vec<Order> {
     }
 }
 
-
+#[allow(non_snake_case)]
 #[pyclass]
 #[derive(Debug, Serialize, Deserialize)]
 pub struct BinanceOrderResponse {
@@ -407,6 +407,7 @@ BinaceCanceOrderResponse will parse below json.
 }
 */
 
+#[allow(non_snake_case)]
 #[pyclass]
 #[derive(Debug, Serialize, Deserialize)]
 pub struct BinanceCancelOrderResponse {
@@ -453,7 +454,7 @@ impl From<BinanceCancelOrderResponse> for Order {
             order.clientOrderId,
             order_side,
             order_type,
-            OrderStatus::Canceled,
+            order_status,
             order.price,
             order.origQty,
         )
@@ -485,6 +486,7 @@ BiannceListOrderResponse will parse json below
 
 */
 
+#[allow(non_snake_case)]
 #[pyclass]
 #[derive(Debug, Clone, Serialize, Deserialize)]
 pub struct BinanceListOrdersResponse {
@@ -927,6 +929,7 @@ impl From<&BinanceExecutionReport> for Order {
     */
 }
 
+#[allow(non_snake_case)]
 #[derive(Debug, Serialize, Deserialize)]
 #[serde(tag = "e")]
 pub enum BinanceUserStreamMessage {
@@ -1033,29 +1036,62 @@ BinanceAccountInformation is parse json as blow
 }
 
 */
+#[allow(non_snake_case)]
 #[pyclass]
-#[derive(Debug, Serialize, Deserialize)]
+#[derive(Debug, Serialize, Deserialize, Clone)]
 pub struct BinanceAccountInformation {
-    makerCommission: i64,
-    takerCommission: i64,
-    buyerCommission: i64,
-    sellerCommission: i64,
-    commissionRates: BinanceCommissionRates,
-    canTrade: bool,
-    canWithdraw: bool,
-    canDeposit: bool,
-    brokered: bool,
-    requireSelfTradePrevention: bool,
-    preventSor: bool,
-    updateTime: u64,
-    accountType: String,
-    balances: Vec<BinanceAccountBalance>,
-    permissions: Vec<String>,
-    uid: i64,
+    #[pyo3(get)]
+    pub makerCommission: i64,
+    #[pyo3(get)]    
+    pub takerCommission: i64,
+    #[pyo3(get)]    
+    pub buyerCommission: i64,
+    #[pyo3(get)]    
+    pub sellerCommission: i64,
+    #[pyo3(get)]    
+    pub commissionRates: BinanceCommissionRates,
+    #[pyo3(get)]    
+    pub canTrade: bool,
+    #[pyo3(get)]    
+    pub canWithdraw: bool,
+    #[pyo3(get)]    
+    pub canDeposit: bool,
+    #[pyo3(get)]    
+    pub brokered: bool,
+    #[pyo3(get)]    
+    pub requireSelfTradePrevention: bool,
+    #[pyo3(get)]    
+    pub preventSor: bool,
+    #[pyo3(get)]    
+    pub updateTime: u64,
+    #[pyo3(get)]    
+    pub accountType: String,
+    #[pyo3(get)]
+    pub balances: Vec<BinanceAccountBalance>,
+    #[pyo3(get)]    
+    pub permissions: Vec<String>,
+    #[pyo3(get)]    
+    pub uid: i64,
 }
 
+
+
 #[pymethods]
 impl BinanceAccountInformation {
+    pub fn __getitem__(&self, asset: String) -> BinanceAccountBalance {
+        for balance in &self.balances {
+            if balance.asset.to_uppercase() == asset.to_uppercase() {
+                return balance.clone();
+            }
+        }
+
+        BinanceAccountBalance {
+            asset: "".to_string(),
+            free: dec![0.0],
+            locked: dec![0.0],
+        }
+    }
+
     pub fn __repr__(&self) -> String {
         serde_json::to_string(self).unwrap()
         // format!("{:?}", self)
@@ -1063,22 +1099,78 @@ impl BinanceAccountInformation {
 }
 
 #[pyclass]
-#[derive(Debug, Serialize, Deserialize)]
+#[derive(Debug, Serialize, Deserialize, Clone)]
+pub struct BinanceAccountBalances {
+    #[pyo3(get)]    
+    pub balances: Vec<BinanceAccountBalance>,
+}
+
+#[pymethods]
+impl BinanceAccountBalances {
+    /*
+    #[getter]
+    pub fn __getitem__(&self, asset: String) -> BinanceAccountBalance {
+        print!("asset: {}", asset);
+
+        for balance in &self.balances {
+            if balance.asset == asset {
+                return balance.clone();
+            }
+        }
+
+        BinanceAccountBalance {
+            asset: "".to_string(),
+            free: dec![0.0],
+            locked: dec![0.0],
+        }
+    }
+*/
+    pub fn __repr__(&self) -> String {
+        serde_json::to_string(self).unwrap()
+    }
+}
+
+#[pyclass]
+#[derive(Debug, Serialize, Deserialize, Clone)]
 pub struct BinanceCommissionRates {
+    #[pyo3(get)]    
     maker: Decimal,
+    #[pyo3(get)]    
     taker: Decimal,
+    #[pyo3(get)]    
     buyer: Decimal,
+    #[pyo3(get)]    
     seller: Decimal,
 }
 
+#[pymethods]
+impl BinanceCommissionRates {
+    pub fn __repr__(&self) -> String {
+        serde_json::to_string(self).unwrap()
+        // format!("{:?}", self)
+    }
+}
+
+
 #[pyclass]
-#[derive(Debug, Serialize, Deserialize)]
+#[derive(Debug, Serialize, Deserialize, Clone)]
 pub struct BinanceAccountBalance {
-    asset: String,
-    free: Decimal,
-    locked: Decimal,
+    #[pyo3(get)]    
+    pub asset: String,
+    #[pyo3(get)]
+    pub free: Decimal,
+    #[pyo3(get)]    
+    pub locked: Decimal,
+}
+
+#[pymethods]
+impl BinanceAccountBalance {
+    pub fn __repr__(&self) -> String {
+        serde_json::to_string(self).unwrap()
+    }
 }
 
+
 /*
 BinanceOrderStatus is parse json as blow
 
@@ -1105,6 +1197,7 @@ BinanceOrderStatus is parse json as blow
   "selfTradePreventionMode": "NONE"
 }
 */
+#[allow(non_snake_case)]
 #[pyclass]
 #[derive(Debug, Serialize, Deserialize)]
 pub struct BinanceOrderStatus {
@@ -1224,7 +1317,7 @@ impl BinanceOrderStatus {
 mod binance_message_test {
     use super::*;
     use crate::exchange::binance::message::{
-        BinanceCancelOrderResponse, BinanceExecutionReport, BinanceOrderResponse,
+        BinanceCancelOrderResponse, BinanceOrderResponse,
         BinancePublicWsMessage, BinanceTradeMessage, BinanceWsBoardUpdate, BinanceWsTradeMessage,
     };
 
diff --git a/src/exchange/binance/rest.rs b/src/exchange/binance/rest.rs
index 196b3d26..de945e5d 100644
--- a/src/exchange/binance/rest.rs
+++ b/src/exchange/binance/rest.rs
@@ -1,3 +1,5 @@
+// Copyright(c) 2022-2023. yasstake. All rights reserved.
+
 use std::thread::sleep;
 use std::time::Duration;
 
diff --git a/src/exchange/orderbook.rs b/src/exchange/orderbook.rs
index 2672b1cc..8460199b 100644
--- a/src/exchange/orderbook.rs
+++ b/src/exchange/orderbook.rs
@@ -1,19 +1,20 @@
+// Copyright(c) 2023. yasstake. All rights reserved.
+// Abloultely no warranty.
+
 use std::{collections::HashMap, sync::Mutex};
 
-use ndarray::Array2;
-use numpy::{IntoPyArray, PyArray2};
+
 use polars_core::{
     prelude::{DataFrame, NamedFrom},
     series::Series,
 };
-use pyo3::{pyclass, Py, PyResult, Python};
-use pyo3_polars::PyDataFrame;
+use pyo3::pyclass;
 use rust_decimal::prelude::*;
 use rust_decimal_macros::dec;
 use serde::{de, Deserialize, Deserializer};
 use serde_derive::{Deserialize, Serialize};
 
-use crate::{common::MarketConfig, exchange::binance::Market};
+use crate::common::MarketConfig;
 
 pub fn string_to_f64<'de, D>(deserializer: D) -> Result<f64, D::Error>
 where
diff --git a/src/exchange/rest.rs b/src/exchange/rest.rs
index 07b0ebd7..47a9c124 100644
--- a/src/exchange/rest.rs
+++ b/src/exchange/rest.rs
@@ -1,39 +1,19 @@
 // Copyright(c) 2023. yasstake. All rights reserved.
 // Abloultely no warranty.
 
-//pub mod bb;
-//pub mod binance;
-//pub mod orderbook;
-
-//pub use orderbook::*;
-
-// pub mod ftx;
-
-use core::panic;
 use std::{
     fs::File,
     io::{copy, BufReader, Cursor, Write},
-    net::TcpStream,
     path::Path,
 };
 
 use csv::{self, StringRecord};
 use flate2::bufread::GzDecoder;
 use reqwest::Method;
-use serde_json::Value;
 use tempfile::tempdir;
-use url::Url;
 use zip::ZipArchive;
-
-
-use crate::common::{Trade,MicroSec, HHMM, MICRO_SECOND, NOW, SEC};
-
+use crate::common::Trade;
 use crossbeam_channel::Sender;
-// use crossbeam_channel::Receiver;
-
-use tungstenite::Message;
-use tungstenite::{connect, stream::MaybeTlsStream};
-use tungstenite::{http::request, protocol::WebSocket};
 
 
 pub fn log_download_tmp(url: &str, tmp_dir: &Path) -> Result<String, String> {
@@ -524,8 +504,6 @@ pub fn check_exist(url: &str) -> bool {
 
 #[cfg(test)]
 mod test_exchange {
-    use serde_json::json;
-
     use super::*;
     use crate::common::init_debug_log;
 
diff --git a/src/exchange/ws.rs b/src/exchange/ws.rs
index 352ba8ed..ba1bee41 100644
--- a/src/exchange/ws.rs
+++ b/src/exchange/ws.rs
@@ -1,36 +1,15 @@
-//pub mod bb;
-//pub mod binance;
-//pub mod orderbook;
-
-//pub use orderbook::*;
-
-// pub mod ftx;
+// Copyright(c) 2022-2023. yasstake. All rights reserved.
 
 use core::panic;
-use std::{
-    fs::File,
-    io::{copy, BufReader, Cursor, Write},
-    net::TcpStream,
-    path::Path,
-};
-
-use csv::{self, StringRecord};
-use flate2::bufread::GzDecoder;
-use reqwest::Method;
+use std::net::TcpStream;
 use serde_json::Value;
-use tempfile::tempdir;
 use url::Url;
-use zip::ZipArchive;
-
-
-use crate::common::{Trade,MicroSec, HHMM, MICRO_SECOND, NOW, SEC};
 
-use crossbeam_channel::Sender;
-// use crossbeam_channel::Receiver;
 
+use crate::common::{MicroSec, MICRO_SECOND, NOW};
 use tungstenite::Message;
 use tungstenite::{connect, stream::MaybeTlsStream};
-use tungstenite::{http::request, protocol::WebSocket};
+use tungstenite::protocol::WebSocket;
 
 
 pub struct WebSocketClient {
diff --git a/src/session/orderlist.rs b/src/session/orderlist.rs
index 4b5de361..7d91a8f1 100644
--- a/src/session/orderlist.rs
+++ b/src/session/orderlist.rs
@@ -1,7 +1,7 @@
+// Copyright(c) 2022-2023. yasstake. All rights reserved.
+
 use crate::common::{Order, OrderSide, OrderStatus, Trade};
-use polars_lazy::dsl::first;
-use pyo3::{pyclass, pymethods, PyResult};
-use pyo3_polars::PyDataFrame;
+use pyo3::{pyclass, pymethods};
 use rust_decimal::Decimal;
 use rust_decimal_macros::dec;
 use serde_derive::Serialize;
@@ -149,7 +149,7 @@ impl OrderList {
     /// For Buy Trade, it consumes the Sell order list which below the trade price only.
     /// For Sell Trade, it consumes the Buy order list which above the trade price only.
 
-    pub fn consume_trade(&mut self, mut trade: &Trade) -> Vec<Order> {
+    pub fn consume_trade(&mut self, trade: &Trade) -> Vec<Order> {
         // first check if the order is in the list. If not return emply list.
         let order_len = self.len();
 
diff --git a/src/session/python_if.rs b/src/session/python_if.rs
index 5253241f..d31d3d94 100644
--- a/src/session/python_if.rs
+++ b/src/session/python_if.rs
@@ -1,4 +1,6 @@
-use pyo3::{PyAny, PyObject, Python};
+// Copyright(c) 2022-2023. yasstake. All rights reserved.
+
+use pyo3::PyAny;
 
 /// Checks if a given Python object has a method with the specified name.
 pub fn has_method(agent: &PyAny, method_name: &str) -> bool {
diff --git a/src/session/runner.rs b/src/session/runner.rs
index f019df83..38193d8e 100644
--- a/src/session/runner.rs
+++ b/src/session/runner.rs
@@ -1,18 +1,11 @@
-use std::borrow::BorrowMut;
-use std::f32::consts::E;
-use std::sync::Arc;
-use std::thread;
+// Copyright(c) 2022-2023. yasstake. All rights reserved.
 
-use pyo3::exceptions::PyValueError;
 use pyo3::{pyclass, pymethods, Py, PyAny, PyErr, PyObject, Python};
-use rusqlite::ffi::SQLITE_FCNTL_CKSM_FILE;
 use rust_decimal::prelude::ToPrimitive;
 
 use crate::common::{
-    MarketConfig, MarketMessage, MarketStream, MicroSec, Order, Trade, FLOOR_SEC, SEC,
+    MarketConfig, MarketMessage, MarketStream, MicroSec, FLOOR_SEC, SEC,
 };
-use crate::exchange::binance::config;
-
 use crossbeam_channel::Receiver;
 
 use super::{has_method, Session};
diff --git a/src/session/session.rs b/src/session/session.rs
index e657c46b..8ee3a38f 100644
--- a/src/session/session.rs
+++ b/src/session/session.rs
@@ -1,29 +1,26 @@
+// Copyright(c) 2022-2023. yasstake. All rights reserved.
+
 use std::collections::VecDeque;
 use std::io::Write;
 use std::sync::Mutex;
 use std::{fs::OpenOptions, path::Path};
 
-
 use pyo3::{pyclass, pymethods, PyAny, PyObject, Python};
 use pyo3_polars::PyDataFrame;
 
 use rust_decimal::{prelude::ToPrimitive, Decimal};
 use rust_decimal_macros::dec;
-use serde_derive::Serialize;
 
-use crate::exchange::BoardItem;
-use crate::{
-    common::{
-        date_string, hour_string, min_string, AccountStatus, MarketConfig, MarketStream, MicroSec,
-        OrderSide, OrderStatus, NOW,
-    },
-    exchange::binance::Market,
+use crate::common::{
+    date_string, hour_string, min_string, AccountStatus, MarketConfig, MarketStream, MicroSec,
+    OrderSide, OrderStatus, NOW,
 };
+use crate::exchange::BoardItem;
 
-use super::{has_method, OrderList};
+use super::OrderList;
 use pyo3::prelude::*;
 
-use crate::common::{Trade, ordervec_to_dataframe};
+use crate::common::{ordervec_to_dataframe, Trade};
 use crate::common::{MarketMessage, SEC};
 use crate::common::{Order, OrderType};
 
@@ -32,7 +29,7 @@ use crate::common::{Order, OrderType};
 pub struct ExecuteLog {
     on_memory: bool,
     memory: Vec<Order>,
-    log_file: Option<std::fs::File>,    
+    log_file: Option<std::fs::File>,
 }
 
 impl ExecuteLog {
@@ -56,7 +53,7 @@ impl ExecuteLog {
         Ok(())
     }
 
-    pub fn log(&mut self, order: &Order) -> Result<(), std::io::Error>{
+    pub fn log(&mut self, order: &Order) -> Result<(), std::io::Error> {
         if self.on_memory {
             self.memory.push(order.clone());
         } else {
@@ -299,7 +296,7 @@ impl Session {
 
     #[getter]
     pub fn get_buy_edge(&self) -> f64 {
-        self.buy_edge.to_f64().unwrap()        
+        self.buy_edge.to_f64().unwrap()
     }
 
     #[getter]
@@ -371,7 +368,11 @@ impl Session {
         }
     }
 
-    pub fn real_market_order(&mut self, side: OrderSide, size: Decimal) -> Result<Py<PyAny>, PyErr> {
+    pub fn real_market_order(
+        &mut self,
+        side: OrderSide,
+        size: Decimal,
+    ) -> Result<Py<PyAny>, PyErr> {
         let size_scale = self.market_config.size_scale;
         let size = size.round_dp(size_scale);
 
@@ -385,7 +386,6 @@ impl Session {
         })
     }
 
-
     pub fn dummy_market_order(
         &mut self,
         side: OrderSide,
@@ -399,7 +399,7 @@ impl Session {
         let execute_price = if side == OrderSide::Buy {
             self.sell_edge + self.market_config.market_order_price_slip
         } else {
-            self.buy_edge - self.market_config.market_order_price_slip            
+            self.buy_edge - self.market_config.market_order_price_slip
         };
 
         let mut order = Order::new(
@@ -589,17 +589,16 @@ impl Session {
 
         if tick.order_side == OrderSide::Buy {
             self.sell_edge = tick.price;
-            if self.sell_edge <= self.buy_edge{
+            if self.sell_edge <= self.buy_edge {
                 self.buy_edge = self.sell_edge - self.market_config.price_unit;
             }
         } else if tick.order_side == OrderSide::Sell {
             self.buy_edge = tick.price;
-            if self.sell_edge <= self.buy_edge{
+            if self.sell_edge <= self.buy_edge {
                 self.sell_edge = self.buy_edge + self.market_config.price_unit;
             }
         }
 
-
         if self.dummy == false {
             return vec![];
         }
@@ -696,8 +695,7 @@ impl Session {
     }
 }
 
-
-impl Session {    
+impl Session {
     pub fn log(&mut self, order: &Order) -> Result<(), std::io::Error> {
         self.log.log(order)
     }


Test patch:
diff --git a/src/test/manual/binance_order.ipynb b/src/test/manual/binance_order.ipynb
new file mode 100644
index 00000000..6ffdbf37
--- /dev/null
+++ b/src/test/manual/binance_order.ipynb
@@ -0,0 +1,394 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "# Binance用オーダー発行API\n",
+    "\n",
+    "`BinanceMarket`は、通過ペアー毎に以下の機能を提供します。\n",
+    "\n",
+    "* 蓄積用データベースの生成（Sqlite)\n",
+    "* 約定データのダウンロードと更新\n",
+    "  * 過去データのダウンロード(Binance Webサイト)\n",
+    "  * リアルタイム更新(WebSocket)\n",
+    "* 約定データのDBからの取得と足の作成\n",
+    "  * 任意の期間の足の作成(`ohlcv`メソッド)\n",
+    "  * VAP(Value At Price)の計算(`vap`メソッド)\n",
+    "* オーダーの発行・キャンセル（REST API)　KEYとSECRETの設定が必要です。\n",
+    "\n",
+    "また通過ペアーの設定は`BinanceConfig`クラスに定義してあります。パラーメータを修正することで任意の通過ペアーに対応可能ですが、テスト完了して提供しているものは以下になります。\n",
+    "* `BinanceConfig.BTCUSDT` 本番用BTCUSDTペアー（現物）\n",
+    "* `BinanceConfig.TEST_BTCUSDT`　テストネット用BTCUSDTペアー（現物）\n",
+    "\n",
+    "## 本サンプルの機能\n",
+    "\n",
+    "本サンプルでは以下を行います。\n",
+    "\n",
+    "* オーダーの発行(Limit, Market)\n",
+    "* オーダーの検索\n",
+    "* オーダーのキャンセル\n",
+    "* 資産残高の確認\n",
+    "\n",
+    "### 利用している関数\n",
+    "* オーダー発行\n",
+    "  * `limit_order(side, price, size)` リミットオーダーの発行\n",
+    "  * `market_order(side, size)`　マーケットオーダーの発行\n",
+    "* オーダー状況確認\n",
+    "  * `order_status`　オーダーステータスの確認（約定済みも含めた直近のもの）\n",
+    "  * `open_orders`　未約定一覧\n",
+    "* オーダーキャンセル\n",
+    "  * `cancel_order(order_id)`　指定したIDのオーダキャンセル\n",
+    "  * `cancel_all_orders()`　未約定のオーダーのキャンセル\n",
+    "* アカウント情報\n",
+    "  * `account`　アカウント情報（残高など）\n",
+    "\n",
+    "## API KEYについて（注：まずはテストネットで試してください）\n",
+    "動作させるためにはAPI KEYが必要です。\n",
+    "ローカル環境では、以下の値を環境変数に指定してください。\n",
+    "* BINANCE_API_KEY   APIキー\n",
+    "* BINANCE_API_SERECT  シークレット\n",
+    "\n",
+    "Google Clabでは、userdataに設定してください（Colabのページの左側ツールバーにある🔑マークをクリック）。"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## 必要ライブラリのインストール\n",
+    "\n",
+    "`rbot`がBotFrameWorkの本体です。必要なライブラリを合わせてインストールします。２回目は実行不要です。"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# 必要ライブラリのインストール\n",
+    "! pip install --upgrade pip\n",
+    "\n",
+    "# rbotがbot frameworkになります。PyPiに登録されているので、pipでインストールできます。\n",
+    "# まだ開発初期段階なので、インターフェースが変わる可能性があります。そのためバージョン指定しています。\n",
+    "#! pip install --upgrade rbot==0.2.4\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# 必要ライブラリのインストール。環境によっては要・不要があるので適宜修正してください。\n",
+    "! pip install json2html"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## Python コード本体\n",
+    "\n",
+    "### 必要ライブラリのインポート"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import rbot\n",
+    "# BinanceMarketクラスは、BinanceのAPIを利用して、取引所の情報を取得するクラス\n",
+    "from rbot import BinanceMarket\n",
+    "\n",
+    "# BinanceConfigクラスは、BinanceMarketクラスのコンストラクタに渡す設定クラス\n",
+    "from rbot import BinanceConfig\n",
+    "\n",
+    "from rbot import init_log, init_debug_log\n",
+    "#init_debug_log()\n",
+    "\n",
+    "print(\"rbot version =\", rbot.__version__)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# 必要ライブラリーのインポート\n",
+    "from json2html import *\n",
+    "from IPython.display import HTML"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### BinanceMarketオブジェクトの生成\n",
+    "\n",
+    "引数にBinanceConfigを設定してオブジェクトを生成します。"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# BinanceMarketクラスのインスタンスを生成(テストネットのBTCUSDT現物取引の設定)\n",
+    "config = BinanceConfig.TEST_BTCUSDT\n",
+    "\n",
+    "# Google Colabの場合は、userdataからAPIキーを取得\n",
+    "# 通常は、環境変数に設定してください。\n",
+    "if 'google.colab' in str(get_ipython()):\n",
+    "    from google.colab import userdata\n",
+    "    # Google Colabの場合は、APIキーを入力してください。\n",
+    "    config.api_key = userdata.get(\"BINANCE_API_KEY\")\n",
+    "    config.api_secret = userdata.get(\"BINANCE_API_SECRET\")\n",
+    "\n",
+    "# json2htmlを利用して、設定情報を表示\n",
+    "HTML(json2html.convert(config.__str__()))"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# BinanceMarketクラスのインスタンスを生成(BTCUSDT現物取引の設定)\n",
+    "market = BinanceMarket(config)\n",
+    "\n",
+    "# BinanceMarketのインスタンスを表示すると格納されているデータの情報が表示されます。\n",
+    "market"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "from time import sleep\n",
+    "\n",
+    "# WebSocketを利用して、取引所の情報を取得する\n",
+    "market.start_market_stream()\n",
+    "\n",
+    "sleep(1) # データが揃うまで少し待つ"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# 一旦　過去のオーダーを全部キャンセルする\n",
+    "market.cancel_all_orders()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## オーダー発行テスト\n",
+    "\n",
+    "### Limit order"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# 現在のアカウント情報を取り出す\n",
+    "account = market.account\n",
+    "account"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# accountにはすべての通貨の残高が入っているので、BTCとUSDTの残高を表示する\n",
+    "print(\"BTC 残高 =\", account['BTC'])\n",
+    "print(\"USDT残高 =\", account['USDT'])"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# 現在の板情報を取り出す\n",
+    "bids, asks, = market.board\n",
+    "\n",
+    "bid_edge = bids['price'][0]\n",
+    "ask_edge = asks['price'][0]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# 板より１００ドル安いところへ0.0001BTCの買い注文を出す\n",
+    "buy_limit_order = market.limit_order(\"BUY\", bid_edge - 100, 0.001)\n",
+    "buy_limit_order"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# 未約定のオーダーを表示する。オーダーが１つ増えているはず。\n",
+    "market.open_orders"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# 板より１００ドル高いところへ0.0001BTCの売り注文を出す\n",
+    "sell_limit_order = market.limit_order(\"SELL\", ask_edge + 100, 0.001)\n",
+    "sell_limit_order"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# 未約定のオーダーを表示する。オーダーが１つ増えているはず（合計２つ）\n",
+    "market.open_orders"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# 最新の残高を確認。注文中の資産がLockされているはず。\n",
+    "account = market.account\n",
+    "print(\"BTC 残高 =\", account['BTC'])\n",
+    "print(\"USDT残高 =\", account['USDT'])"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# 売りオーダーをキャンセルする\n",
+    "\n",
+    "id_to_cancel = buy_limit_order[0].order_id\n",
+    "\n",
+    "print(\"キャンセルするオーダーID =\", id_to_cancel)\n",
+    "\n",
+    "market.cancel_order(sell_limit_order[0].order_id)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# キャンセルしたオーダーがなくなっていることを確認する\n",
+    "market.open_orders"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# 最新の残高を確認。キャンセルされた分の資産のLockが解放される。\n",
+    "account = market.account\n",
+    "print(\"BTC 残高 =\", account['BTC'])\n",
+    "print(\"USDT残高 =\", account['USDT'])"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## Market order"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# market orderを出す\n",
+    "\n",
+    "market_order = market.market_order(\"BUY\", 0.001)   # 0.001BTCを市場価格で買う\n",
+    "market_order"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# 直近のオーダーを表示する。status \"Filled\"のオーダーが１つ追加されているはず。\n",
+    "# なお大きなオーダーを出すと複数に分割される場合がある。\n",
+    "\n",
+    "market.order_status"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# 最新の残高を確認。約定した分だけBTCが増えて、USDTの残高が減っているはず。\n",
+    "account = market.account\n",
+    "print(\"BTC 残高 =\", account['BTC'])\n",
+    "print(\"USDT残高 =\", account['USDT'])"
+   ]
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python 3",
+   "language": "python",
+   "name": "python3"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": "3.11.6"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}