279 lines
10 KiB
Rust
279 lines
10 KiB
Rust
pub mod strategy_001;
|
|
pub mod strategy_002;
|
|
pub mod strategy_003;
|
|
pub mod strategy_004;
|
|
pub mod strategy_005;
|
|
pub mod strategy_006;
|
|
pub mod strategy_007;
|
|
pub mod strategy_008;
|
|
pub mod strategy_009;
|
|
pub mod strategy_010;
|
|
pub mod future_strategy_short;
|
|
pub mod future_strategy_long;
|
|
// pub mod strategy_test;
|
|
pub mod strategy_manager;
|
|
|
|
use crate::coex::exchange_team::get_server_epoch;
|
|
use crate::coex::order_team::{limit_order_sell, select_filled_buy_orders};
|
|
use crate::coin_health_check_team::request_others::{ExchangeInfo, TradeFee};
|
|
use crate::database_control::*;
|
|
use crate::decimal_funcs::*;
|
|
use crate::value_estimation_team::datapoints::price_data::{CandleType, RealtimePriceData};
|
|
use crate::value_estimation_team::indicators::adx::{adx, AdxData};
|
|
use crate::value_estimation_team::indicators::bollingerband::{bollingerband, BollingerBandData};
|
|
use crate::value_estimation_team::indicators::dema::{dema, DemaData};
|
|
use crate::value_estimation_team::indicators::ema::{ema, ema_opclo, EmaData};
|
|
use crate::value_estimation_team::indicators::heatmap_volume::{
|
|
heatmap_volume, HeatMapLevel, HeatmapVolumeData,
|
|
};
|
|
use crate::value_estimation_team::indicators::macd::{ema_macd, MacdData};
|
|
use crate::value_estimation_team::indicators::rsi::{rsi, RsiData};
|
|
use crate::value_estimation_team::indicators::sma::{sma, sma_opclo,sma_open, SmaData};
|
|
use crate::value_estimation_team::indicators::stoch_rsi::{stoch_rsi, StochRsiData};
|
|
use crate::value_estimation_team::indicators::supertrend::{
|
|
supertrend, SuperTrendArea, SuperTrendSignal, SupertrendData,
|
|
};
|
|
use crate::value_estimation_team::indicators::tema::{tema, TemaData};
|
|
use crate::value_estimation_team::indicators::wiliams_percent_r::{
|
|
wiliams_percent_r, WiliamsPercentR,
|
|
};
|
|
use crate::future::Position;
|
|
use futures::future::try_join_all;
|
|
use reqwest::{Client, ClientBuilder};
|
|
use rust_decimal::prelude::Zero;
|
|
use rust_decimal::{prelude::FromPrimitive, prelude::ToPrimitive, Decimal, RoundingStrategy};
|
|
use rust_decimal_macros::dec;
|
|
use sqlx::FromRow;
|
|
use std::collections::{HashMap, HashSet};
|
|
use std::sync::Arc;
|
|
use strategy_manager::{insert_pre_suggested_coins, insert_future_coins};
|
|
use tokio::sync::Mutex;
|
|
use crate::future::FuturesExchangeInfo;
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct AllData {
|
|
pub valid_symbol_vec: HashSet<String>,
|
|
pub rt_price_1m_vec: HashMap<String, Vec<RealtimePriceData>>,
|
|
pub rt_price_30m_vec: HashMap<String, Vec<RealtimePriceData>>,
|
|
pub rt_price_1d_vec: HashMap<String, Vec<RealtimePriceData>>,
|
|
pub rt_price_1w_vec: HashMap<String, Vec<RealtimePriceData>>,
|
|
pub rt_price_1mon_vec: HashMap<String, Vec<RealtimePriceData>>,
|
|
}
|
|
impl AllData {
|
|
pub fn new() -> AllData {
|
|
let a = AllData {
|
|
valid_symbol_vec: HashSet::new(),
|
|
rt_price_1m_vec: HashMap::new(),
|
|
rt_price_30m_vec: HashMap::new(),
|
|
rt_price_1d_vec: HashMap::new(),
|
|
rt_price_1w_vec: HashMap::new(),
|
|
rt_price_1mon_vec: HashMap::new(),
|
|
};
|
|
a
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, FromRow, Clone)]
|
|
pub struct TimeData {
|
|
pub server_epoch: u64,
|
|
pub local_epoch: u64,
|
|
pub epoch_difference: i64,
|
|
pub server_ymdhs: String,
|
|
pub local_ymdhs: String,
|
|
pub last_server_epoch: u64,
|
|
pub last_server_ymdhs: String,
|
|
}
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub struct FilteredDataValue {
|
|
pub closetime: i64,
|
|
pub stoploss: Decimal,
|
|
pub target_price: Decimal,
|
|
pub current_price: Decimal,
|
|
}
|
|
|
|
impl FilteredDataValue {
|
|
fn new() -> FilteredDataValue {
|
|
let a = FilteredDataValue {
|
|
closetime: 0,
|
|
stoploss: Decimal::new(0, 8),
|
|
target_price: Decimal::new(0, 8),
|
|
current_price: Decimal::new(0, 8),
|
|
};
|
|
a
|
|
}
|
|
}
|
|
|
|
pub async fn duplicate_filter(
|
|
registerer: i32,
|
|
original_filtered_data: &HashMap<String, FilteredDataValue>,
|
|
) -> Result<HashMap<String, FilteredDataValue>, Box<dyn std::error::Error + Send + Sync>> {
|
|
let inspect_table_name_1 = String::from("buy_ordered_coin_list");
|
|
let inspect_table_name_2 = String::from("sell_ordered_coin_list");
|
|
let inspect_table_name_3 = String::from("pre_suggested_coin_list");
|
|
let inspect_table_name_4 = String::from("suggested_coin_list");
|
|
|
|
let mut filtered_data: HashMap<String, FilteredDataValue> = HashMap::new();
|
|
let mut filtered_data_arc: Arc<Mutex<HashMap<String, FilteredDataValue>>> =
|
|
Arc::new(Mutex::new(filtered_data));
|
|
let mut task_vec = Vec::new();
|
|
|
|
for (symbol, filtered_data) in original_filtered_data {
|
|
let mut exists_condition_build = String::from("symbol=\'");
|
|
exists_condition_build.push_str(symbol.as_str());
|
|
exists_condition_build.push_str("\' AND registerer=");
|
|
exists_condition_build.push_str(registerer.to_string().as_str());
|
|
// exists_condition_build.push_str("\' AND close_time=");
|
|
// exists_condition_build.push_str(element.1.to_string().as_str());
|
|
let exists_condition = Some(exists_condition_build);
|
|
let exists_condition_c = exists_condition.clone();
|
|
let inspect_table_name_1_c = inspect_table_name_1.clone();
|
|
let inspect_table_name_2_c = inspect_table_name_2.clone();
|
|
let inspect_table_name_3_c = inspect_table_name_3.clone();
|
|
let inspect_table_name_4_c = inspect_table_name_4.clone();
|
|
let symbol_c = symbol.clone();
|
|
let filtered_data_c = filtered_data.clone();
|
|
let filtered_data_arc_c = Arc::clone(&filtered_data_arc);
|
|
task_vec.push(tokio::spawn(async move {
|
|
let inspect_result_1 =
|
|
exists_record(&inspect_table_name_1_c, &exists_condition_c).await;
|
|
let inspect_result_2 =
|
|
exists_record(&inspect_table_name_2_c, &exists_condition_c).await;
|
|
let inspect_result_3 =
|
|
exists_record(&inspect_table_name_3_c, &exists_condition_c).await;
|
|
let inspect_result_4 =
|
|
exists_record(&inspect_table_name_4_c, &exists_condition_c).await;
|
|
|
|
if inspect_result_1 == false
|
|
&& inspect_result_2 == false
|
|
&& inspect_result_3 == false
|
|
&& inspect_result_4 == false
|
|
{
|
|
let mut filtered_data_lock = filtered_data_arc_c.lock().await;
|
|
filtered_data_lock.insert(symbol_c, filtered_data_c);
|
|
}
|
|
}));
|
|
}
|
|
try_join_all(task_vec).await?;
|
|
let filtered_data_c = filtered_data_arc.lock().await.clone();
|
|
Ok(filtered_data_c)
|
|
}
|
|
|
|
pub async fn future_duplicate_filter(
|
|
position: Position,
|
|
original_filtered_data: &HashMap<String, FilteredDataValue>,
|
|
future_exchange_info_map: &HashMap<String, FuturesExchangeInfo>
|
|
) -> Result<HashMap<String, FilteredDataValue>, Box<dyn std::error::Error + Send + Sync>> {
|
|
let inspect_table_name_1 = String::from("future_ordered_coin_list");
|
|
|
|
let mut filtered_data: HashMap<String, FilteredDataValue> = HashMap::new();
|
|
let mut filtered_data_arc: Arc<Mutex<HashMap<String, FilteredDataValue>>> =
|
|
Arc::new(Mutex::new(filtered_data));
|
|
let mut task_vec = Vec::new();
|
|
|
|
for (symbol, filtered_data) in original_filtered_data {
|
|
|
|
let mut exists_condition_build = String::from("symbol=\'");
|
|
exists_condition_build.push_str(symbol.as_str());
|
|
// exists_condition_build.push_str("\' AND close_time=");
|
|
// exists_condition_build.push_str(filtered_data.closetime.to_string().as_str());
|
|
exists_condition_build.push_str("\' AND position=");
|
|
exists_condition_build.push_str("\'");
|
|
exists_condition_build.push_str(position.to_string().as_str());
|
|
exists_condition_build.push_str("\'");
|
|
|
|
let exists_condition = Some(exists_condition_build);
|
|
let exists_condition_c = exists_condition.clone();
|
|
let inspect_table_name_1_c = inspect_table_name_1.clone();
|
|
let future_exchange_info_map_c = future_exchange_info_map.clone();
|
|
let symbol_c = symbol.clone();
|
|
let filtered_data_c = filtered_data.clone();
|
|
let filtered_data_arc_c = Arc::clone(&filtered_data_arc);
|
|
task_vec.push(tokio::spawn(async move {
|
|
if future_exchange_info_map_c.contains_key(&symbol_c) {
|
|
let inspect_result_1 =
|
|
exists_record(&inspect_table_name_1_c, &exists_condition_c).await;
|
|
|
|
if inspect_result_1 == false
|
|
{
|
|
let mut filtered_data_lock = filtered_data_arc_c.lock().await;
|
|
filtered_data_lock.insert(symbol_c, filtered_data_c);
|
|
}
|
|
}
|
|
}));
|
|
}
|
|
try_join_all(task_vec).await?;
|
|
let filtered_data_c = filtered_data_arc.lock().await.clone();
|
|
Ok(filtered_data_c)
|
|
}
|
|
|
|
pub async fn remove_keys(
|
|
filtered_data: &mut HashMap<String, FilteredDataValue>,
|
|
keys_to_remove: HashSet<String>,
|
|
) {
|
|
let len_prev = filtered_data.len();
|
|
// remove key-value in filtered_data
|
|
for symbol in keys_to_remove {
|
|
filtered_data.remove(&symbol);
|
|
}
|
|
let len_now = filtered_data.len();
|
|
|
|
// shrink capacity of filtered_data
|
|
if len_now != len_prev {
|
|
filtered_data.shrink_to_fit();
|
|
}
|
|
}
|
|
|
|
// useful functions for strategists
|
|
pub async fn get_current_price_f64(
|
|
symbol: &String,
|
|
rt_price_map: &HashMap<String, Vec<RealtimePriceData>>,
|
|
) -> Option<f64> {
|
|
if let Some(rt_vec) = rt_price_map.get(symbol) {
|
|
if rt_vec.last().is_some_and(|a| a.close_price.is_normal()) {
|
|
return Some(rt_vec.last().unwrap().close_price);
|
|
}
|
|
}
|
|
None
|
|
}
|
|
|
|
pub async fn get_current_price_decimal(
|
|
symbol: &String,
|
|
rt_price_map: &HashMap<String, Vec<RealtimePriceData>>,
|
|
) -> Option<(Decimal, i64)> {
|
|
if let Some(rt_vec) = rt_price_map.get(symbol) {
|
|
if rt_vec.last().is_some_and(|a| a.close_price.is_normal()) {
|
|
let current_price = rust_decimal::prelude::FromPrimitive::from_f64(
|
|
rt_vec.last().unwrap().close_price,
|
|
)
|
|
.unwrap();
|
|
let close_time = rt_vec.last().unwrap().close_time;
|
|
return Some((current_price, close_time));
|
|
}
|
|
}
|
|
None
|
|
}
|
|
|
|
pub async fn get_time_data() -> TimeData {
|
|
|
|
let table_name = String::from("time");
|
|
let columns = String::from("*");
|
|
let condition = None;
|
|
|
|
let mut time_info = TimeData {
|
|
server_epoch: 0,
|
|
local_epoch: 0,
|
|
epoch_difference: 0,
|
|
server_ymdhs: String::new(),
|
|
local_ymdhs: String::new(),
|
|
last_server_epoch: 0,
|
|
last_server_ymdhs: String::new() };
|
|
|
|
let select_result = select_record(&table_name, &columns, &condition, &time_info)
|
|
.await
|
|
.unwrap();
|
|
|
|
let a = select_result.first().unwrap().clone();
|
|
a
|
|
}
|