Add kelly criterion
This commit is contained in:
parent
819453aee5
commit
bc1e429377
|
|
@ -1,4 +1,4 @@
|
|||
// assets_managing_team manages [asset_manage_announcement] and [wallet] ([wallet_testnet] as well)
|
||||
// assets_managing_team manages [asset_manage_announcement], [kelly_criterion], and[wallet] ([wallet_testnet] as well)
|
||||
|
||||
use crate::coex::exchange_team::*;
|
||||
use crate::database_control::*;
|
||||
|
|
@ -10,7 +10,27 @@ use rust_decimal::{prelude::ToPrimitive, Decimal, RoundingStrategy};
|
|||
use rust_decimal_macros::dec;
|
||||
use serde_json::{Result, Value};
|
||||
use sqlx::FromRow;
|
||||
use crate::coex::order_team::DBlist;
|
||||
use crate::coex::order_team::{DBlist, SellHistoryList};
|
||||
|
||||
#[derive(Debug, FromRow)]
|
||||
pub struct AchievementEvaluationInfo {
|
||||
pub strategist: u16,
|
||||
pub invested_usdt: Decimal,
|
||||
pub usdt_profit: Decimal,
|
||||
pub profit_percent: f64,
|
||||
}
|
||||
|
||||
impl DBlist for AchievementEvaluationInfo {
|
||||
fn new() -> AchievementEvaluationInfo {
|
||||
let a = AchievementEvaluationInfo {
|
||||
strategist: 0,
|
||||
invested_usdt: Decimal::new(0, 8),
|
||||
usdt_profit: Decimal::new(0, 8),
|
||||
profit_percent: 0.0,
|
||||
};
|
||||
a
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, FromRow)]
|
||||
pub struct AssetInfo {
|
||||
|
|
@ -58,37 +78,34 @@ impl DBlist for WalletInfo {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, FromRow)]
|
||||
pub struct KellyCriterionInfo {
|
||||
pub betting_rate: f64,
|
||||
pub win_rate: f64,
|
||||
pub lose_rate: f64,
|
||||
pub profit_rate: f64,
|
||||
pub loss_rate: f64,
|
||||
}
|
||||
|
||||
impl DBlist for KellyCriterionInfo {
|
||||
fn new() -> KellyCriterionInfo {
|
||||
let a = KellyCriterionInfo {
|
||||
betting_rate: 0.0,
|
||||
win_rate: 0.0,
|
||||
lose_rate: 0.0,
|
||||
profit_rate: 0.0,
|
||||
loss_rate: 0.0,
|
||||
};
|
||||
a
|
||||
}
|
||||
}
|
||||
|
||||
// set unit_trade_usdt
|
||||
pub async fn set_unit_usdt() {
|
||||
let asset_info = select_asset_manage_announcement().await;
|
||||
let mut set_unit_trade_usdt = Decimal::new(0, 8);
|
||||
|
||||
if RUNNING_MODE == SIMUL {
|
||||
set_unit_trade_usdt = dec!(100.0); // $100 for each trade
|
||||
} else if RUNNING_MODE == REAL {
|
||||
// define protect_rate and unit_trade_usdt as high as total_usdt_amount
|
||||
if dec!(0.0) <= asset_info.current_total_usdt && asset_info.current_total_usdt < dec!(1000.0) {
|
||||
set_unit_trade_usdt = dec!(50.0); // $100 for each trade
|
||||
// set_unit_trade_usdt = decimal_mul(asset_info.current_total_usdt, dec!(0.8)); // 80% of total usdt
|
||||
} else if dec!(1000.0) <= asset_info.current_total_usdt
|
||||
{
|
||||
// set_unit_trade_usdt = dec!(150.0); // $150 for each trade
|
||||
set_unit_trade_usdt = decimal_mul(asset_info.current_total_usdt, dec!(0.05));
|
||||
|
||||
if set_unit_trade_usdt <= dec!(20) {
|
||||
set_unit_trade_usdt = dec!(0);
|
||||
} else {
|
||||
let truncated = decimal_mul(decimal_mul(set_unit_trade_usdt, dec!(0.1)).trunc(), dec!(10));
|
||||
let difference = decimal_sub(set_unit_trade_usdt, truncated);
|
||||
|
||||
if difference >= dec!(5) {
|
||||
set_unit_trade_usdt = decimal_add(truncated, dec!(5));
|
||||
} else {
|
||||
set_unit_trade_usdt = truncated;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
set_unit_trade_usdt = dec!(30.0); // $30 for each trade
|
||||
|
||||
// update fields in [asset_manage_announcement] table
|
||||
let update_table_name = String::from("asset_manage_announcement");
|
||||
|
|
@ -177,20 +194,19 @@ pub async fn update_current_total_usdt() {
|
|||
];
|
||||
} else {
|
||||
let asset_info = select_asset_manage_announcement().await;
|
||||
let mut profit: Decimal;
|
||||
if asset_info.initial_usdt.is_zero() {
|
||||
profit = dec!(0.0);
|
||||
} else {
|
||||
profit = decimal_sub(
|
||||
decimal_div(asset_info.current_total_usdt, asset_info.initial_usdt),
|
||||
dec!(1),
|
||||
);
|
||||
}
|
||||
|
||||
let achievement_evaluation = select_achievement_evaluation().await;
|
||||
let balance = decimal_sub(achievement_evaluation.usdt_profit, achievement_evaluation.invested_usdt);
|
||||
let current_total_usdt = decimal_add(asset_info.initial_usdt, balance);
|
||||
|
||||
let profit = decimal_sub(
|
||||
decimal_div(current_total_usdt, asset_info.initial_usdt),
|
||||
dec!(1));
|
||||
|
||||
update_values = vec![
|
||||
(
|
||||
String::from("current_total_usdt"),
|
||||
asset_info.available_usdt.to_string(),
|
||||
current_total_usdt.to_string(),
|
||||
),
|
||||
(String::from("profit"), profit.to_string()),
|
||||
(
|
||||
|
|
@ -205,7 +221,6 @@ pub async fn update_current_total_usdt() {
|
|||
update_record3(&update_table_name, &update_values, &update_condition)
|
||||
.await
|
||||
.unwrap();
|
||||
set_unit_usdt().await;
|
||||
}
|
||||
|
||||
// monitor whether [buy_ordered_coin_list] is empty to update current_total_usdt and available_usdt in [asset_manage_announcement]
|
||||
|
|
@ -235,8 +250,10 @@ pub async fn monitoring_asset_usdt(previous_result: &mut bool, client: &Client)
|
|||
// (/api, Weight(IP) 10)
|
||||
}
|
||||
}
|
||||
// FIXME: 아래 함수들을 고쳐야함. 순환 오류 빠지는 듯
|
||||
update_current_total_usdt().await;
|
||||
set_available_usdt().await;
|
||||
set_unit_usdt().await;
|
||||
} else if buy_list_result == false
|
||||
&& sell_list_result == false
|
||||
&& *previous_result == true
|
||||
|
|
@ -253,6 +270,60 @@ pub async fn monitoring_asset_usdt(previous_result: &mut bool, client: &Client)
|
|||
Ok(())
|
||||
}
|
||||
|
||||
// update kelly_criterion table and kelly_betting_usdt
|
||||
pub async fn update_kelly_criterion() -> Result<()> {
|
||||
let table_name = String::from("sell_history");
|
||||
let condition = None;
|
||||
let is_exist = exists_record(&table_name, &condition).await;
|
||||
|
||||
if is_exist == true {
|
||||
let select_columns = String::from("*");
|
||||
let select_condition = None;
|
||||
let data_struct = SellHistoryList::new();
|
||||
|
||||
let sell_history_vec = select_record(
|
||||
&table_name,
|
||||
&select_columns,
|
||||
&select_condition,
|
||||
&data_struct,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let least_number = 50; // the least number of sell hostory to calculate kelly criterion
|
||||
|
||||
if sell_history_vec.len() >= least_number {
|
||||
let lose_collection_vec = sell_history_vec.iter().filter(|&a| a.pure_profit_percent < 0.0).collect::<Vec<_>>();
|
||||
let win_collection_vec = sell_history_vec.iter().filter(|&a| a.pure_profit_percent >= 0.0).collect::<Vec<_>>();
|
||||
let win_rate: f64 = (win_collection_vec.len() as f64)/(sell_history_vec.len() as f64);
|
||||
let lose_rate: f64 = 1.0 - win_rate;
|
||||
let loss_sum = lose_collection_vec.iter().fold(0.0, |acc, x| acc + x.pure_profit_percent);
|
||||
let loss_rate_avg = (loss_sum * 0.01) / (lose_collection_vec.len() as f64) * -1.0;
|
||||
let profit_sum = win_collection_vec.iter().fold(0.0, |acc, x| acc + x.pure_profit_percent);
|
||||
let profit_rate_avg = (profit_sum * 0.01) / (win_collection_vec.len() as f64);
|
||||
|
||||
let betting_rate = (win_rate / loss_rate_avg) - (lose_rate / profit_rate_avg);
|
||||
|
||||
// update kelly_criterion
|
||||
let update_table_name = String::from("kelly_criterion");
|
||||
let update_value = vec![
|
||||
(String::from("betting_rate"), betting_rate.to_string()),
|
||||
(String::from("win_rate"), win_rate.to_string()),
|
||||
(String::from("lose_rate"), lose_rate.to_string()),
|
||||
(String::from("profit_rate"), profit_rate_avg.to_string()),
|
||||
(String::from("loss_rate"), loss_rate_avg.to_string()),
|
||||
]
|
||||
;
|
||||
let update_condition = vec![(String::from("id"), String::from("1"))];
|
||||
update_record3(&update_table_name, &update_value, &update_condition)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// update realtime_expected_total_usdt and realtime_profit
|
||||
pub async fn update_realtime_asset() {
|
||||
let asset_info = select_asset_manage_announcement().await;
|
||||
|
|
@ -304,8 +375,20 @@ pub async fn set_available_usdt() {
|
|||
let update_table_name = String::from("asset_manage_announcement");
|
||||
// fetch current_total_usdt
|
||||
let mut asset_info = select_asset_manage_announcement().await;
|
||||
let kelly_criterion_info = select_kelly_criterion().await;
|
||||
|
||||
let mut available_usdt: Decimal;
|
||||
if kelly_criterion_info.betting_rate >= 5.0 && kelly_criterion_info.betting_rate < 100.0 {;
|
||||
available_usdt = decimal_mul(asset_info.current_total_usdt, rust_decimal::prelude::FromPrimitive::from_f64(
|
||||
kelly_criterion_info.betting_rate * 0.01,
|
||||
)
|
||||
.unwrap());
|
||||
} else if kelly_criterion_info.betting_rate >= 100.0 {
|
||||
available_usdt = asset_info.current_total_usdt;
|
||||
} else { // default: 5% of current_total_usdt
|
||||
available_usdt = decimal_mul(asset_info.current_total_usdt, dec!(0.05));
|
||||
}
|
||||
|
||||
let available_usdt = asset_info.current_total_usdt;
|
||||
let unit_trade_usdt = asset_info.unit_trade_usdt;
|
||||
|
||||
// set available_usdt with current_total_usdt and update is_tradable
|
||||
|
|
@ -398,6 +481,11 @@ pub async fn get_unit_trade_usdt() -> Decimal {
|
|||
asset_info.unit_trade_usdt
|
||||
}
|
||||
|
||||
pub async fn get_current_total_usdt() -> Decimal {
|
||||
let asset_info = select_asset_manage_announcement().await;
|
||||
asset_info.current_total_usdt
|
||||
}
|
||||
|
||||
pub async fn select_asset_manage_announcement() -> AssetInfo {
|
||||
let mut asset_info = AssetInfo::new();
|
||||
|
||||
|
|
@ -446,3 +534,44 @@ pub async fn fetch_free_usdt() -> Decimal {
|
|||
.unwrap();
|
||||
select_result.first().unwrap().free
|
||||
}
|
||||
|
||||
pub async fn select_kelly_criterion() -> KellyCriterionInfo {
|
||||
let mut kelly_criterion_info = KellyCriterionInfo::new();
|
||||
|
||||
let table_name = String::from("kelly_criterion");
|
||||
let columns = String::from("*");
|
||||
let condition = None;
|
||||
|
||||
let select_result = select_record(&table_name, &columns, &condition, &kelly_criterion_info)
|
||||
.await
|
||||
.unwrap();
|
||||
let result_vec = select_result.first().unwrap();
|
||||
|
||||
kelly_criterion_info.betting_rate = result_vec.betting_rate;
|
||||
kelly_criterion_info.win_rate = result_vec.win_rate;
|
||||
kelly_criterion_info.lose_rate = result_vec.lose_rate;
|
||||
kelly_criterion_info.profit_rate = result_vec.profit_rate;
|
||||
kelly_criterion_info.loss_rate = result_vec.loss_rate;
|
||||
|
||||
kelly_criterion_info
|
||||
}
|
||||
|
||||
pub async fn select_achievement_evaluation() -> AchievementEvaluationInfo {
|
||||
let mut achievement_evaluation_info = AchievementEvaluationInfo::new();
|
||||
|
||||
let table_name = String::from("achievement_evaluation");
|
||||
let columns = String::from("*");
|
||||
let condition = None;
|
||||
// FIXME: this code should be general
|
||||
let select_result = select_record(&table_name, &columns, &condition, &achievement_evaluation_info)
|
||||
.await
|
||||
.unwrap();
|
||||
let result_vec = &select_result[2]; //strategist #3
|
||||
|
||||
achievement_evaluation_info.strategist = result_vec.strategist;
|
||||
achievement_evaluation_info.invested_usdt = result_vec.invested_usdt;
|
||||
achievement_evaluation_info.usdt_profit = result_vec.usdt_profit;
|
||||
achievement_evaluation_info.profit_percent = result_vec.profit_percent;
|
||||
|
||||
achievement_evaluation_info
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user