7114 lines
381 KiB
Rust
7114 lines
381 KiB
Rust
use crate::coex::exchange_team::*;
|
|
use crate::coex::order_team::*;
|
|
use crate::coin_health_check_team::request_others::CoinPriceData;
|
|
use crate::database_control::*;
|
|
use crate::value_estimation_team;
|
|
use crate::value_estimation_team::datapoints::price_data::RealtimePriceData;
|
|
use crate::value_estimation_team::indicators::bollingerband::BollingerBandData;
|
|
use crate::value_estimation_team::indicators::ema::EmaData;
|
|
use crate::value_estimation_team::indicators::heatmap_volume::{
|
|
heatmap_volume, HeatMapLevel, HeatmapVolumeData,
|
|
};
|
|
use crate::value_estimation_team::indicators::macd::{ema_macd, EmaMacd};
|
|
use crate::value_estimation_team::indicators::rsi::RsiData;
|
|
use crate::value_estimation_team::indicators::sma::SmaData;
|
|
use crate::value_estimation_team::indicators::stoch_rsi::{StochRsiDData, StochRsiKData};
|
|
use crate::value_estimation_team::indicators::supertrend::{supertrend, SupertrendData};
|
|
use csv::{DeserializeRecordsIter, StringRecord};
|
|
use futures::future::try_join_all;
|
|
use rust_decimal::prelude::ToPrimitive;
|
|
use rust_decimal::Decimal;
|
|
use serde::Deserialize;
|
|
use sqlx::FromRow;
|
|
use std::{cmp::Ordering, sync::Arc};
|
|
use tokio::sync::Mutex;
|
|
use tokio::time::{sleep, Duration, Instant};
|
|
|
|
use crate::signal_association::signal_decision::*;
|
|
|
|
#[derive(PartialEq)]
|
|
pub enum MA {
|
|
Sma,
|
|
Ema,
|
|
Tema,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct AllData {
|
|
pub valid_symbol_vec: Vec<String>,
|
|
|
|
pub rt_price_1m_vec: Vec<(String, Vec<RealtimePriceData>)>,
|
|
pub rt_price_30m_vec: Vec<(String, Vec<RealtimePriceData>)>,
|
|
pub rt_price_1d_vec: Vec<(String, Vec<RealtimePriceData>)>,
|
|
pub rt_price_1w_vec: Vec<(String, Vec<RealtimePriceData>)>,
|
|
pub rt_price_1mon_vec: Vec<(String, Vec<RealtimePriceData>)>,
|
|
// pub sma3_1m_data: Vec<(String, Vec<SmaData>)>,
|
|
// pub sma3_30m_data: Vec<(String, Vec<SmaData>)>,
|
|
// pub sma3_1d_data: Vec<(String, Vec<SmaData>)>,
|
|
// pub sma3_1w_data: Vec<(String, Vec<SmaData>)>,
|
|
// pub sma3_1mon_data: Vec<(String, Vec<SmaData>)>,
|
|
|
|
// pub sma10_1m_data: Vec<(String, Vec<SmaData>)>,
|
|
// pub sma10_30m_data: Vec<(String, Vec<SmaData>)>,
|
|
// pub sma10_1d_data: Vec<(String, Vec<SmaData>)>,
|
|
// pub sma10_1w_data: Vec<(String, Vec<SmaData>)>,
|
|
// pub sma10_1mon_data: Vec<(String, Vec<SmaData>)>,
|
|
|
|
// pub sma30_1m_data: Vec<(String, Vec<SmaData>)>,
|
|
// pub sma30_30m_data: Vec<(String, Vec<SmaData>)>,
|
|
// pub sma30_1d_data: Vec<(String, Vec<SmaData>)>,
|
|
// pub sma30_1w_data: Vec<(String, Vec<SmaData>)>,
|
|
// pub sma30_1mon_data: Vec<(String, Vec<SmaData>)>,
|
|
|
|
// pub ema3_1m_data: Vec<(String, Vec<EmaData>)>,
|
|
// pub ema3_30m_data: Vec<(String, Vec<EmaData>)>,
|
|
// pub ema3_1d_data: Vec<(String, Vec<EmaData>)>,
|
|
// pub ema3_1w_data: Vec<(String, Vec<EmaData>)>,
|
|
// pub ema3_1mon_data: Vec<(String, Vec<EmaData>)>,
|
|
|
|
// pub ema10_1m_data: Vec<(String, Vec<EmaData>)>,
|
|
// pub ema10_30m_data: Vec<(String, Vec<EmaData>)>,
|
|
// pub ema10_1d_data: Vec<(String, Vec<EmaData>)>,
|
|
// pub ema10_1w_data: Vec<(String, Vec<EmaData>)>,
|
|
// pub ema10_1mon_data: Vec<(String, Vec<EmaData>)>,
|
|
|
|
// pub ema30_1m_data: Vec<(String, Vec<EmaData>)>,
|
|
// pub ema30_30m_data: Vec<(String, Vec<EmaData>)>,
|
|
// pub ema30_1d_data: Vec<(String, Vec<EmaData>)>,
|
|
// pub ema30_1w_data: Vec<(String, Vec<EmaData>)>,
|
|
// pub ema30_1mon_data: Vec<(String, Vec<EmaData>)>,
|
|
|
|
// pub rsi3_1m_data: Vec<(String, Vec<RsiData>)>,
|
|
// pub rsi3_30m_data: Vec<(String, Vec<RsiData>)>,
|
|
// pub rsi3_1d_data: Vec<(String, Vec<RsiData>)>,
|
|
// pub rsi3_1w_data: Vec<(String, Vec<RsiData>)>,
|
|
// pub rsi3_1mon_data: Vec<(String, Vec<RsiData>)>,
|
|
|
|
// pub rsi10_1m_data: Vec<(String, Vec<RsiData>)>,
|
|
// pub rsi10_30m_data: Vec<(String, Vec<RsiData>)>,
|
|
// pub rsi10_1d_data: Vec<(String, Vec<RsiData>)>,
|
|
// pub rsi10_1w_data: Vec<(String, Vec<RsiData>)>,
|
|
// pub rsi10_1mon_data: Vec<(String, Vec<RsiData>)>,
|
|
|
|
// pub rsi30_1m_data: Vec<(String, Vec<RsiData>)>,
|
|
// pub rsi30_30m_data: Vec<(String, Vec<RsiData>)>,
|
|
// pub rsi30_1d_data: Vec<(String, Vec<RsiData>)>,
|
|
// pub rsi30_1w_data: Vec<(String, Vec<RsiData>)>,
|
|
// pub rsi30_1mon_data: Vec<(String, Vec<RsiData>)>,
|
|
|
|
// pub stoch_rsi3_1m_3_k_data: Vec<(String, Vec<StochRsiKData>)>,
|
|
// pub stoch_rsi3_1m_3_d_data: Vec<(String, Vec<StochRsiDData>)>,
|
|
// pub stoch_rsi30_1m_30_k_data: Vec<(String, Vec<StochRsiKData>)>,
|
|
// pub stoch_rsi30_1m_30_d_data: Vec<(String, Vec<StochRsiDData>)>,
|
|
|
|
// pub bb3_1m_data: Vec<(String, Vec<BollingerBandData>)>,
|
|
// pub bb3_30m_data: Vec<(String, Vec<BollingerBandData>)>,
|
|
// pub bb3_1d_data: Vec<(String, Vec<BollingerBandData>)>,
|
|
// pub bb3_1w_data: Vec<(String, Vec<BollingerBandData>)>,
|
|
// pub bb3_1mon_data: Vec<(String, Vec<BollingerBandData>)>,
|
|
|
|
// pub bb10_1m_data: Vec<(String, Vec<BollingerBandData>)>,
|
|
// pub bb10_30m_data: Vec<(String, Vec<BollingerBandData>)>, to be deleted
|
|
// pub bb10_1d_data: Vec<(String, Vec<BollingerBandData>)>,
|
|
// pub bb10_1w_data: Vec<(String, Vec<BollingerBandData>)>,
|
|
// pub bb10_1mon_data: Vec<(String, Vec<BollingerBandData>)>,
|
|
|
|
// pub bb30_1m_data: Vec<(String, Vec<BollingerBandData>)>,
|
|
// pub bb30_30m_data: Vec<(String, Vec<BollingerBandData>)>,
|
|
// pub bb30_1d_data: Vec<(String, Vec<BollingerBandData>)>,
|
|
// pub bb30_1w_data: Vec<(String, Vec<BollingerBandData>)>,
|
|
// pub bb30_1mon_data: Vec<(String, Vec<BollingerBandData>)>,
|
|
}
|
|
impl AllData {
|
|
pub fn new() -> AllData {
|
|
let a = AllData {
|
|
valid_symbol_vec: Vec::new(),
|
|
rt_price_1m_vec: Vec::new(),
|
|
rt_price_30m_vec: Vec::new(),
|
|
rt_price_1d_vec: Vec::new(),
|
|
rt_price_1w_vec: Vec::new(),
|
|
rt_price_1mon_vec: Vec::new(),
|
|
// sma3_1m_data: Vec::new(),
|
|
// sma3_30m_data: Vec::new(),
|
|
// sma3_1d_data: Vec::new(),
|
|
// sma3_1w_data: Vec::new(),
|
|
// sma3_1mon_data: Vec::new(),
|
|
|
|
// sma10_1m_data: Vec::new(),
|
|
// sma10_30m_data: Vec::new(),
|
|
// sma10_1d_data: Vec::new(),
|
|
// sma10_1w_data: Vec::new(),
|
|
// sma10_1mon_data: Vec::new(),
|
|
|
|
// sma30_1m_data: Vec::new(),
|
|
// sma30_30m_data: Vec::new(),
|
|
// sma30_1d_data: Vec::new(),
|
|
// sma30_1w_data: Vec::new(),
|
|
// sma30_1mon_data: Vec::new(),
|
|
|
|
// ema3_1m_data: Vec::new(),
|
|
// ema3_30m_data: Vec::new(),
|
|
// ema3_1d_data: Vec::new(),
|
|
// ema3_1w_data: Vec::new(),
|
|
// ema3_1mon_data: Vec::new(),
|
|
|
|
// ema10_1m_data: Vec::new(),
|
|
// ema10_30m_data: Vec::new(),
|
|
// ema10_1d_data: Vec::new(),
|
|
// ema10_1w_data: Vec::new(),
|
|
// ema10_1mon_data: Vec::new(),
|
|
|
|
// ema30_1m_data: Vec::new(),
|
|
// ema30_30m_data: Vec::new(),
|
|
// ema30_1d_data: Vec::new(),
|
|
// ema30_1w_data: Vec::new(),
|
|
// ema30_1mon_data: Vec::new(),
|
|
|
|
// rsi3_1m_data: Vec::new(),
|
|
// rsi3_30m_data: Vec::new(),
|
|
// rsi3_1d_data: Vec::new(),
|
|
// rsi3_1w_data: Vec::new(),
|
|
// rsi3_1mon_data: Vec::new(),
|
|
|
|
// rsi10_1m_data: Vec::new(),
|
|
// rsi10_30m_data: Vec::new(),
|
|
// rsi10_1d_data: Vec::new(),
|
|
// rsi10_1w_data: Vec::new(),
|
|
// rsi10_1mon_data: Vec::new(),
|
|
|
|
// rsi30_1m_data: Vec::new(),
|
|
// rsi30_30m_data: Vec::new(),
|
|
// rsi30_1d_data: Vec::new(),
|
|
// rsi30_1w_data: Vec::new(),
|
|
// rsi30_1mon_data: Vec::new(),
|
|
|
|
// stoch_rsi3_1m_3_k_data: Vec::new(),
|
|
// stoch_rsi3_1m_3_d_data: Vec::new(),
|
|
// stoch_rsi30_1m_30_k_data: Vec::new(),
|
|
// stoch_rsi30_1m_30_d_data: Vec::new(),
|
|
|
|
// bb3_1m_data: Vec::new(),
|
|
// bb3_30m_data: Vec::new(),
|
|
// bb3_1d_data: Vec::new(),
|
|
// bb3_1w_data: Vec::new(),
|
|
// bb3_1mon_data: Vec::new(),
|
|
|
|
// bb10_1m_data: Vec::new(),
|
|
// bb10_30m_data: Vec::new(), to be deleted
|
|
// bb10_1d_data: Vec::new(),
|
|
// bb10_1w_data: Vec::new(),
|
|
// bb10_1mon_data: Vec::new(),
|
|
|
|
// bb30_1m_data: Vec::new(),
|
|
// bb30_30m_data: Vec::new(),
|
|
// bb30_1d_data: Vec::new(),
|
|
// bb30_1w_data: Vec::new(),
|
|
// bb30_1mon_data: Vec::new(),
|
|
};
|
|
a
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Deserialize, Clone)]
|
|
struct OpcloData {
|
|
price: f64,
|
|
server_epoch: u64,
|
|
usdt_volume: f64,
|
|
up_down: String,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize, Clone)]
|
|
struct PriceData {
|
|
opclo_price: f64,
|
|
open_price: f64,
|
|
close_price: f64,
|
|
high_price: f64,
|
|
low_price: f64,
|
|
close_time: u64,
|
|
quote_asset_volume: f64,
|
|
candle_type: String,
|
|
}
|
|
|
|
#[derive(Debug, FromRow)]
|
|
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(Debug, FromRow)]
|
|
struct ServerEpoch {
|
|
server_epoch: u64,
|
|
}
|
|
|
|
#[derive(Debug, FromRow)]
|
|
struct Record {
|
|
symbol: String,
|
|
suggested_price: Decimal,
|
|
close_time: u64,
|
|
registered_server_epoch: u64,
|
|
registerer: u16,
|
|
is_long: u8,
|
|
}
|
|
|
|
pub async fn execute_strategists(
|
|
all_data: &AllData,
|
|
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|
// strategist_001(all_data).await;
|
|
// strategist_002(all_data).await;
|
|
// strategist_003(all_data).await;
|
|
// strategist_004(all_data).await;
|
|
// strategist_005(all_data).await;
|
|
// strategist_006(all_data).await;
|
|
// strategist_007().await;
|
|
// strategist_008().await;
|
|
// strategist_009().await;
|
|
|
|
// strategist_010().await;
|
|
// strategist_011().await;
|
|
// strategist_012().await;
|
|
// strategist_013(all_data).await;
|
|
// strategist_014(all_data).await;
|
|
// strategist_015(all_data).await;
|
|
// strategist_016(all_data).await;
|
|
|
|
execute_strategist_for_test_temp(all_data).await?;
|
|
// execute_strategist_for_test1(all_data).await;
|
|
// execute_strategist_for_test2(all_data).await;
|
|
Ok(())
|
|
}
|
|
|
|
// pub async fn execute_strategist_for_test(alldata: &AllData) -> Result<(), 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 market_cap_index = select_marketcap().await;
|
|
|
|
// let mut filtered_symbols: Vec<String> = Vec::new();
|
|
// // filtered_symbols.push(String::from("BNBUSDT"));
|
|
// filtered_symbols.push(String::from("BTCUSDT"));
|
|
// // filtered_symbols.push(String::from("ETHUSDT"));
|
|
// // filtered_symbols.push(String::from("LTCUSDT"));
|
|
// // filtered_symbols.push(String::from("XRPUSDT"));
|
|
// // filtered_symbols.push(String::from("TRXUSDT"));
|
|
// let current_price = get_current_price(&filtered_symbols.first().unwrap(), &alldata.price_vec).await.unwrap();
|
|
|
|
// let mut filtered_2nd_symbols: Vec<(String, i64)> = Vec::new(); // (symbol, closetime)
|
|
|
|
// let mut rsi3_1m_vec: Vec<RsiData> = Vec::new();
|
|
// let mut rsi30_1m_vec: Vec<RsiData> = Vec::new();
|
|
// let mut stoch_rsi3_1m_k_vec: Vec<StochRsiKData> = Vec::new();
|
|
// let mut stoch_rsi3_1m_d_vec: Vec<StochRsiDData> = Vec::new();
|
|
// let mut stoch_rsi30_1m_k_vec: Vec<StochRsiKData> = Vec::new();
|
|
// let mut stoch_rsi30_1m_d_vec: Vec<StochRsiDData> = Vec::new();
|
|
// let mut opclo_1m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut sma10_1m_vec: Vec<SmaData> = Vec::new();
|
|
// let mut ema3_1m_vec: Vec<EmaData> = Vec::new();
|
|
// let mut ema10_1m_vec: Vec<EmaData> = Vec::new();
|
|
// let mut ema30_1m_vec: Vec<EmaData> = Vec::new();
|
|
// let mut cnt = 0;
|
|
|
|
// for symbol in filtered_symbols {
|
|
// let rsi3_1m_option = alldata.rsi3_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let rsi30_1m_option = alldata.rsi30_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let stoch_rsi3_1m_k_option = alldata.stoch_rsi3_1m_3_k_data.iter().position(|x| *x.0 == *symbol);
|
|
// let stoch_rsi3_1m_d_option = alldata.stoch_rsi3_1m_3_d_data.iter().position(|x| *x.0 == *symbol);
|
|
// let stoch_rsi30_1m_k_option = alldata.stoch_rsi30_1m_30_k_data.iter().position(|x| *x.0 == *symbol);
|
|
// let stoch_rsi30_1m_d_option = alldata.stoch_rsi30_1m_30_d_data.iter().position(|x| *x.0 == *symbol);
|
|
// let opclo_1m_option = alldata.rt_price_1m_vec.iter().position(|x| *x.0 == *symbol);
|
|
// let sma10_1m_option = alldata.sma10_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let ema3_1m_option = alldata.ema3_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let ema10_1m_option = alldata.ema10_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let ema30_1m_option = alldata.ema30_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
|
|
// if rsi3_1m_option.is_some() && rsi30_1m_option.is_some() && opclo_1m_option.is_some() && sma10_1m_option.is_some() && ema3_1m_option.is_some() && ema10_1m_option.is_some() && ema30_1m_option.is_some() && stoch_rsi3_1m_k_option.is_some() && stoch_rsi3_1m_d_option.is_some() && stoch_rsi30_1m_k_option.is_some() && stoch_rsi30_1m_d_option.is_some() {
|
|
// rsi3_1m_vec = alldata.rsi3_1m_data[rsi3_1m_option.unwrap()].1.clone();
|
|
// rsi30_1m_vec = alldata.rsi30_1m_data[rsi30_1m_option.unwrap()].1.clone();
|
|
// stoch_rsi3_1m_k_vec = alldata.stoch_rsi3_1m_3_k_data[stoch_rsi3_1m_k_option.unwrap()].1.clone();
|
|
// stoch_rsi3_1m_d_vec = alldata.stoch_rsi3_1m_3_d_data[stoch_rsi3_1m_d_option.unwrap()].1.clone();
|
|
// stoch_rsi30_1m_k_vec = alldata.stoch_rsi30_1m_30_k_data[stoch_rsi30_1m_k_option.unwrap()].1.clone();
|
|
// stoch_rsi30_1m_d_vec = alldata.stoch_rsi30_1m_30_d_data[stoch_rsi30_1m_d_option.unwrap()].1.clone();
|
|
// opclo_1m_vec = alldata.rt_price_1m_vec[opclo_1m_option.unwrap()].1.clone();
|
|
// sma10_1m_vec = alldata.sma10_1m_data[sma10_1m_option.unwrap()].1.clone();
|
|
// ema3_1m_vec = alldata.ema3_1m_data[ema3_1m_option.unwrap()].1.clone();
|
|
// ema10_1m_vec = alldata.ema10_1m_data[ema10_1m_option.unwrap()].1.clone();
|
|
// ema30_1m_vec = alldata.ema30_1m_data[ema30_1m_option.unwrap()].1.clone();
|
|
|
|
// if rsi3_1m_vec.len() >= 3 && opclo_1m_vec.len() >= 3 && sma10_1m_vec.len() >= 3 && ema3_1m_vec.len() >= 30 && ema10_1m_vec.len() >= 3 && ema30_1m_vec.len() >= 30 && stoch_rsi3_1m_k_vec.len() >= 5 && stoch_rsi3_1m_d_vec.len() >= 5 && stoch_rsi30_1m_k_vec.len() >= 5 && stoch_rsi30_1m_d_vec.len() >= 5 {
|
|
// opclo_1m_vec.reverse();
|
|
// opclo_1m_vec.truncate(3);
|
|
// opclo_1m_vec.reverse();
|
|
// stoch_rsi3_1m_k_vec.reverse();
|
|
// stoch_rsi3_1m_k_vec.truncate(5);
|
|
// stoch_rsi3_1m_k_vec.reverse();
|
|
// stoch_rsi3_1m_d_vec.reverse();
|
|
// stoch_rsi3_1m_d_vec.truncate(5);
|
|
// stoch_rsi3_1m_d_vec.reverse();
|
|
// stoch_rsi30_1m_k_vec.reverse();
|
|
// stoch_rsi30_1m_k_vec.truncate(5);
|
|
// stoch_rsi30_1m_k_vec.reverse();
|
|
// stoch_rsi30_1m_d_vec.reverse();
|
|
// stoch_rsi30_1m_d_vec.truncate(5);
|
|
// stoch_rsi30_1m_d_vec.reverse();
|
|
// let supertrend_vec = supertrend(&symbol, &alldata.rt_price_1m_vec, 60, 1.0, true).await;
|
|
// let macd_vec = ema_macd(&ema10_1m_vec, &ema30_1m_vec, 30).await?;
|
|
// let macd_search_result = macd_vec.binary_search_by_key(&opclo_1m_vec[2].close_time, |&EmaMacd{macd_value, close_time}|close_time);
|
|
|
|
// if macd_search_result.is_ok() {
|
|
// if macd_vec[macd_search_result.unwrap()].macd_value > 0.0 {
|
|
// //check duplicate records
|
|
// 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(opclo_1m_vec.last().unwrap().close_time.to_string().as_str());
|
|
// let exists_condition = Some(exists_condition_build);
|
|
|
|
// let inspect_result_1 = exists_record(&inspect_table_name_1, &exists_condition).await;
|
|
// let inspect_result_2 = exists_record(&inspect_table_name_2, &exists_condition).await;
|
|
// let inspect_result_3 = exists_record(&inspect_table_name_3, &exists_condition).await;
|
|
// let inspect_result_4 = exists_record(&inspect_table_name_4, &exists_condition).await;
|
|
|
|
// if inspect_result_1 == false && inspect_result_2 == false && inspect_result_3 == false && inspect_result_4 == false {
|
|
// let mut sum_stoch_rsi30_1m_k = 0.0;
|
|
// for element in &stoch_rsi30_1m_k_vec {
|
|
// sum_stoch_rsi30_1m_k += element.stoch_rsi_k_value;
|
|
// }
|
|
// let average_stoch_rsi30_1m_k = sum_stoch_rsi30_1m_k / 5.0;
|
|
|
|
// let ema3_3_result = ema3_1m_vec.binary_search_by_key(&opclo_1m_vec[2].close_time, |&EmaData{ema_value, close_time}|close_time);
|
|
// let ema3_2_result = ema3_1m_vec.binary_search_by_key(&opclo_1m_vec[1].close_time, |&EmaData{ema_value, close_time}|close_time);
|
|
// let ema3_1_result = ema3_1m_vec.binary_search_by_key(&opclo_1m_vec[0].close_time, |&EmaData{ema_value, close_time}|close_time);
|
|
// let ema10_result = ema10_1m_vec.binary_search_by_key(&opclo_1m_vec[2].close_time, |&EmaData{ema_value, close_time}|close_time);
|
|
// let sma10_result = sma10_1m_vec.binary_search_by_key(&opclo_1m_vec[2].close_time, |&SmaData{sma_value, close_time}|close_time);
|
|
// if ema3_3_result.is_ok() && ema3_2_result.is_ok() && ema3_1_result.is_ok() && ema10_result.is_ok() && sma10_result.is_ok() {
|
|
// if sma10_1m_vec[sma10_result.unwrap()].sma_value < ema3_1m_vec[ema3_3_result.unwrap()].ema_value {
|
|
// let k_result = stoch_rsi30_1m_k_vec.binary_search_by_key(&opclo_1m_vec[2].close_time, |&StochRsiKData{stoch_rsi_k_value, close_time}|close_time);
|
|
// let k_prev_result = stoch_rsi30_1m_k_vec.binary_search_by_key(&opclo_1m_vec[1].close_time, |&StochRsiKData{stoch_rsi_k_value, close_time}|close_time);
|
|
// let d_result = stoch_rsi30_1m_d_vec.binary_search_by_key(&opclo_1m_vec[2].close_time, |&StochRsiDData{stoch_rsi_d_value, close_time}|close_time);
|
|
// if k_result.is_ok() && k_prev_result.is_ok() {
|
|
// if stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value >= stoch_rsi30_1m_k_vec[k_prev_result.unwrap()].stoch_rsi_k_value
|
|
// && stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value - stoch_rsi30_1m_k_vec[k_prev_result.unwrap()].stoch_rsi_k_value > 5.0
|
|
// && stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value < 80.0
|
|
// && stoch_rsi30_1m_d_vec[d_result.unwrap()].stoch_rsi_d_value < 96.0
|
|
// && stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value - stoch_rsi30_1m_d_vec[d_result.unwrap()].stoch_rsi_d_value > 5.0 {
|
|
// if current_price <= opclo_1m_vec[1].opclo_price * ((((opclo_1m_vec[1].high_price / opclo_1m_vec[1].low_price) - 1.0) / 2.0) + 1.0) {
|
|
// // filtered_2nd_symbols.push((symbol, opclo_1m_vec.last().unwrap().close_time));
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // if ema10_1m_vec[ema10_result.unwrap()].ema_value > sma10_1m_vec[sma10_result.unwrap()].sma_value {
|
|
// // if ema3_1m_vec[ema3_3_result.unwrap()].ema_value > ema10_1m_vec[ema10_result.unwrap()].ema_value {
|
|
// // if ema3_1m_vec[ema3_3_result.unwrap()].ema_value > ema3_1m_vec[ema3_2_result.unwrap()].ema_value
|
|
// // && ema3_1m_vec[ema3_2_result.unwrap()].ema_value > ema3_1m_vec[ema3_1_result.unwrap()].ema_value
|
|
// // {
|
|
// // if average_stoch_rsi30_1m_k < 80.0 {
|
|
// // let k_result = stoch_rsi30_1m_k_vec.binary_search_by_key(&opclo_1m_vec[2].close_time, |&StochRsiKData{stoch_rsi_k_value, close_time}|close_time);
|
|
// // let k_prev_result = stoch_rsi30_1m_k_vec.binary_search_by_key(&opclo_1m_vec[1].close_time, |&StochRsiKData{stoch_rsi_k_value, close_time}|close_time);
|
|
// // let k_prev2_result = stoch_rsi30_1m_k_vec.binary_search_by_key(&opclo_1m_vec[0].close_time, |&StochRsiKData{stoch_rsi_k_value, close_time}|close_time);
|
|
// // let d_result = stoch_rsi30_1m_d_vec.binary_search_by_key(&opclo_1m_vec[2].close_time, |&StochRsiDData{stoch_rsi_d_value, close_time}|close_time);
|
|
// // if k_result.is_ok() && d_result.is_ok() && k_prev_result.is_ok() && k_prev2_result.is_ok() {
|
|
// // if
|
|
// // (stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value > stoch_rsi30_1m_d_vec[d_result.unwrap()].stoch_rsi_d_value)
|
|
// // && (stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value - stoch_rsi30_1m_d_vec[d_result.unwrap()].stoch_rsi_d_value) > 3.0
|
|
// // && stoch_rsi30_1m_d_vec[d_result.unwrap()].stoch_rsi_d_value < 96.0
|
|
// // && (stoch_rsi10_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value > stoch_rsi10_1m_k_vec[k_prev2_result.unwrap()].stoch_rsi_k_value)
|
|
// // && (stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value - stoch_rsi30_1m_k_vec[k_prev_result.unwrap()].stoch_rsi_k_value) < 25.0
|
|
// // && (stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value - stoch_rsi30_1m_k_vec[k_prev_result.unwrap()].stoch_rsi_k_value) > 3.0
|
|
// // // && (stoch_rsi10_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value - stoch_rsi10_1m_d_vec[d_result.unwrap()].stoch_rsi_d_value > 5.0)
|
|
// // // (stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value - stoch_rsi30_1m_k_vec[k_prev_result.unwrap()].stoch_rsi_k_value > 5.0) &&
|
|
// // // ((stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value > stoch_rsi30_1m_k_vec[k_prev_result.unwrap()].stoch_rsi_k_value && stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value <= 80.0)
|
|
// // // || (((opclo_1m_vec[1].open_price - opclo_1m_vec[1].close_price).abs() / (opclo_1m_vec[1].high_price - opclo_1m_vec[1].low_price) > 60.0 && stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value > 80.0) && (stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value > stoch_rsi30_1m_k_vec[k_prev_result.unwrap()].stoch_rsi_k_value)))
|
|
// // {
|
|
// // // if stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value > 80.0 {
|
|
// // // if (opclo_1m_vec[1].open_price - opclo_1m_vec[1].close_price).abs() / (opclo_1m_vec[1].high_price - opclo_1m_vec[1].low_price) > 60.0
|
|
// // // {
|
|
// // // filtered_2nd_symbols.push((symbol, opclo_1m_vec.last().unwrap().close_time));
|
|
// // // }
|
|
// // // } else {
|
|
// // filtered_2nd_symbols.push((symbol, opclo_1m_vec.last().unwrap().close_time));
|
|
// // // }
|
|
// // // filtered_2nd_symbols.push((symbol, opclo_1m_vec.last().unwrap().close_time));
|
|
// // // if opclo_1m_vec[1].candle_type == "DOWN" && opclo_1m_vec[1].opclo_price >= opclo_1m_vec[2].close_price {
|
|
// // // filtered_2nd_symbols.push((symbol, opclo_1m_vec.last().unwrap().close_time));
|
|
// // // } else if opclo_1m_vec[1].candle_type == "UP" {
|
|
// // // filtered_2nd_symbols.push((symbol, opclo_1m_vec.last().unwrap().close_time));
|
|
// // // }
|
|
// // }
|
|
// // // else {
|
|
// // // let result = rsi3_1m_vec.binary_search_by_key(&opclo_1m_vec[1].close_time, |&RsiData{rsi_value, close_time}|close_time);
|
|
// // // if result.is_ok() {
|
|
// // // if rsi3_1m_vec[result.unwrap()].rsi_value < 20.0 && cnt >= 2 && (stoch_rsi10_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value > stoch_rsi10_1m_d_vec[d_result.unwrap()].stoch_rsi_d_value) {
|
|
// // // filtered_2nd_symbols.push((symbol, opclo_1m_vec.last().unwrap().close_time));
|
|
// // // }
|
|
// // // }
|
|
// // // }
|
|
|
|
// // // } else {
|
|
// // // if cnt >= 2 {
|
|
|
|
// // // let result = ema3_1m_vec.binary_search_by_key(&opclo_1m_vec[1].close_time, |&EmaData{ema_value, close_time}|close_time);
|
|
// // // match result {
|
|
// // // Ok(T) => {
|
|
// // // if ema3_1m_vec[T].ema_value > opclo_1m_vec[1].opclo_price {
|
|
// // // let result = rsi3_1m_vec.binary_search_by_key(&opclo_1m_vec[1].close_time, |&RsiData{rsi_value, close_time}|close_time);
|
|
// // // match result {
|
|
// // // Ok(T) => {
|
|
// // // if rsi3_1m_vec[T].rsi_value < 15.0 {
|
|
// // // let k_result = stoch_rsi10_1m_k_vec.binary_search_by_key(&opclo_1m_vec[1].close_time, |&StochRsiKData{stoch_rsi_k_value, close_time}|close_time);
|
|
// // // let d_result = stoch_rsi10_1m_d_vec.binary_search_by_key(&opclo_1m_vec[1].close_time, |&StochRsiDData{stoch_rsi_d_value, close_time}|close_time);
|
|
|
|
// // // if k_result.is_ok() && d_result.is_ok() {
|
|
// // // if stoch_rsi10_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value <= stoch_rsi10_1m_d_vec[d_result.unwrap()].stoch_rsi_d_value {
|
|
// // // if current_price < opclo_1m_vec[1].opclo_price {
|
|
// // // filtered_2nd_symbols.push((symbol, opclo_1m_vec.last().unwrap().close_time));
|
|
// // // }
|
|
// // // }
|
|
// // // }
|
|
// // // }
|
|
// // // },
|
|
// // // Err(E) => {}
|
|
// // // }
|
|
// // // }
|
|
// // // },
|
|
// // // Err(E) => {}
|
|
// // // }
|
|
// // // }
|
|
// // // }
|
|
// // }
|
|
// // } else {
|
|
// // let k_result = stoch_rsi10_1m_k_vec.binary_search_by_key(&opclo_1m_vec[2].close_time, |&StochRsiKData{stoch_rsi_k_value, close_time}|close_time);
|
|
// // let k_prev_result = stoch_rsi10_1m_k_vec.binary_search_by_key(&opclo_1m_vec[1].close_time, |&StochRsiKData{stoch_rsi_k_value, close_time}|close_time);
|
|
// // let k_prev2_result = stoch_rsi10_1m_k_vec.binary_search_by_key(&opclo_1m_vec[0].close_time, |&StochRsiKData{stoch_rsi_k_value, close_time}|close_time);
|
|
// // let d_result = stoch_rsi10_1m_d_vec.binary_search_by_key(&opclo_1m_vec[2].close_time, |&StochRsiDData{stoch_rsi_d_value, close_time}|close_time);
|
|
// // if k_result.is_ok() && d_result.is_ok() && k_prev_result.is_ok() && k_prev2_result.is_ok() {
|
|
// // if (stoch_rsi10_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value > stoch_rsi10_1m_d_vec[d_result.unwrap()].stoch_rsi_d_value)
|
|
// // && (stoch_rsi10_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value - stoch_rsi10_1m_d_vec[d_result.unwrap()].stoch_rsi_d_value) > 3.0
|
|
// // && stoch_rsi10_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value > stoch_rsi10_1m_k_vec[k_prev2_result.unwrap()].stoch_rsi_k_value
|
|
// // && stoch_rsi10_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value > stoch_rsi10_1m_k_vec[k_prev_result.unwrap()].stoch_rsi_k_value
|
|
// // && stoch_rsi10_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value - stoch_rsi10_1m_k_vec[k_prev_result.unwrap()].stoch_rsi_k_value < 30.0
|
|
// // && stoch_rsi10_1m_d_vec[d_result.unwrap()].stoch_rsi_d_value < 95.0
|
|
// // {
|
|
// // // if stoch_rsi10_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value > 80.0 {
|
|
// // // if (opclo_1m_vec[1].open_price - opclo_1m_vec[1].close_price).abs() / (opclo_1m_vec[1].high_price - opclo_1m_vec[1].low_price) > 60.0
|
|
// // // {
|
|
// // // filtered_2nd_symbols.push((symbol, opclo_1m_vec.last().unwrap().close_time));
|
|
// // // }
|
|
// // // } else {
|
|
// // // filtered_2nd_symbols.push((symbol, opclo_1m_vec.last().unwrap().close_time));
|
|
// // // }
|
|
// // filtered_2nd_symbols.push((symbol, opclo_1m_vec.last().unwrap().close_time));
|
|
// // }
|
|
// // }
|
|
// // }
|
|
// // }
|
|
// // }
|
|
// // // else {
|
|
// // // let k_result = stoch_rsi30_1m_k_vec.binary_search_by_key(&opclo_1m_vec[2].close_time, |&StochRsiKData{stoch_rsi_k_value, close_time}|close_time);
|
|
// // // let k_prev_result = stoch_rsi30_1m_k_vec.binary_search_by_key(&opclo_1m_vec[1].close_time, |&StochRsiKData{stoch_rsi_k_value, close_time}|close_time);
|
|
// // // let d_result = stoch_rsi30_1m_d_vec.binary_search_by_key(&opclo_1m_vec[2].close_time, |&StochRsiDData{stoch_rsi_d_value, close_time}|close_time);
|
|
// // // if k_result.is_ok() && k_prev_result.is_ok() {
|
|
// // // if (stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value > stoch_rsi30_1m_k_vec[k_prev_result.unwrap()].stoch_rsi_k_value)
|
|
// // // && (stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value - stoch_rsi30_1m_k_vec[k_prev_result.unwrap()].stoch_rsi_k_value) > 5.0
|
|
// // // {
|
|
// // // filtered_2nd_symbols.push((symbol, opclo_1m_vec.last().unwrap().close_time));
|
|
// // // }
|
|
|
|
// // // // if ema3_1m_vec[ema3_3_result.unwrap()].ema_value < ema3_1m_vec[ema3_2_result.unwrap()].ema_value {
|
|
// // // // if opclo_1m_vec[1].candle_type == "DOWN" && opclo_1m_vec[1].open_price > ema3_1m_vec[ema3_2_result.unwrap()].ema_value
|
|
// // // // && opclo_1m_vec[2].open_price < ema3_1m_vec[ema3_3_result.unwrap()].ema_value
|
|
// // // // && opclo_1m_vec[2].high_price < ema3_1m_vec[ema3_3_result.unwrap()].ema_value
|
|
// // // // && opclo_1m_vec[2].candle_type == "UP" {
|
|
// // // // if (stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value < stoch_rsi30_1m_d_vec[d_result.unwrap()].stoch_rsi_d_value)
|
|
// // // // {
|
|
// // // // filtered_2nd_symbols.push((symbol, opclo_1m_vec.last().unwrap().close_time));
|
|
// // // // }
|
|
// // // // }
|
|
// // // // } else if ema3_1m_vec[ema3_3_result.unwrap()].ema_value > ema3_1m_vec[ema3_2_result.unwrap()].ema_value
|
|
// // // // {
|
|
// // // // if opclo_1m_vec[1].candle_type == "UP"
|
|
// // // // && (stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value > stoch_rsi30_1m_d_vec[d_result.unwrap()].stoch_rsi_d_value) {
|
|
// // // // filtered_2nd_symbols.push((symbol, opclo_1m_vec.last().unwrap().close_time));
|
|
// // // // }
|
|
// // // // }
|
|
// // // }
|
|
// // // }
|
|
// // }
|
|
// }
|
|
// }
|
|
// }
|
|
// // else if macd_vec[macd_search_result.unwrap()].macd_value > macd_vec[macd_search_result.unwrap()-1].macd_value && macd_vec[macd_search_result.unwrap()].macd_value > -3.0{
|
|
// // let k_result = stoch_rsi30_1m_k_vec.binary_search_by_key(&opclo_1m_vec[2].close_time, |&StochRsiKData{stoch_rsi_k_value, close_time}|close_time);
|
|
// // let k_prev_result = stoch_rsi30_1m_k_vec.binary_search_by_key(&opclo_1m_vec[1].close_time, |&StochRsiKData{stoch_rsi_k_value, close_time}|close_time);
|
|
// // let d_result = stoch_rsi30_1m_d_vec.binary_search_by_key(&opclo_1m_vec[2].close_time, |&StochRsiDData{stoch_rsi_d_value, close_time}|close_time);
|
|
// // if k_result.is_ok() && k_prev_result.is_ok() && d_result.is_ok() {
|
|
// // if stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value >= stoch_rsi30_1m_k_vec[k_prev_result.unwrap()].stoch_rsi_k_value
|
|
// // && stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value > stoch_rsi30_1m_d_vec[d_result.unwrap()].stoch_rsi_d_value
|
|
// // && stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value - stoch_rsi30_1m_d_vec[d_result.unwrap()].stoch_rsi_d_value > 5.0{
|
|
// // filtered_2nd_symbols.push((symbol, opclo_1m_vec.last().unwrap().close_time));
|
|
// // }
|
|
// // }
|
|
// // }
|
|
// }
|
|
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // let mut filtered_2nd_symbols: Vec<(String, i64)> = Vec::new(); // (symbol, closetime)
|
|
// // if market_cap_index.first().unwrap().negative_buy_signal == 1 || (market_cap_index.first().unwrap().liquidation_signal == 0 && market_cap_index.first().unwrap().market_cap_index <= 20.0 && market_cap_index.first().unwrap().market_cap_index >= 0.0) {
|
|
// // let mut rsi3_1m_vec: Vec<RsiData> = Vec::new();
|
|
// // let mut opclo_1m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// // let mut ema3_1m_vec: Vec<EmaData> = Vec::new();
|
|
// // let mut cnt = 0;
|
|
// // for symbol in filtered_symbols {
|
|
// // let rsi3_1m_option = alldata.rsi3_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// // let opclo_1m_option = alldata.rt_price_1m_vec.iter().position(|x| *x.0 == *symbol);
|
|
// // let ema3_1m_option = alldata.ema3_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
|
|
// // if rsi3_1m_option.is_some() && opclo_1m_option.is_some() && ema3_1m_option.is_some() {
|
|
// // rsi3_1m_vec = alldata.rsi3_1m_data[rsi3_1m_option.unwrap()].1.clone();
|
|
// // opclo_1m_vec = alldata.rt_price_1m_vec[opclo_1m_option.unwrap()].1.clone();
|
|
// // ema3_1m_vec = alldata.ema3_1m_data[ema3_1m_option.unwrap()].1.clone();
|
|
|
|
// // if rsi3_1m_vec.len() >= 3 && opclo_1m_vec.len() >= 3 && ema3_1m_vec.len() >= 3 {
|
|
// // opclo_1m_vec.reverse();
|
|
// // opclo_1m_vec.truncate(3);
|
|
// // opclo_1m_vec.reverse();
|
|
|
|
// // if opclo_1m_vec.last().unwrap().candle_type == "UP" {
|
|
// // cnt = 0;
|
|
// // for element in &opclo_1m_vec {
|
|
// // if element.candle_type == "DOWN" {
|
|
// // cnt += 1;
|
|
// // }
|
|
// // }
|
|
|
|
// // if cnt >= 2 {
|
|
// // let result = ema3_1m_vec.binary_search_by_key(&opclo_1m_vec[1].close_time, |&EmaData{ema_value, close_time}|close_time);
|
|
// // match result {
|
|
// // Ok(T) => {
|
|
// // if ema3_1m_vec[T].ema_value > opclo_1m_vec[1].opclo_price {
|
|
// // let result = rsi3_1m_vec.binary_search_by_key(&opclo_1m_vec[1].close_time, |&RsiData{rsi_value, close_time}|close_time);
|
|
// // match result {
|
|
// // Ok(T) => {
|
|
// // if rsi3_1m_vec[T].rsi_value < 30.0 {
|
|
// // if current_price < opclo_1m_vec[1].opclo_price {
|
|
// // filtered_2nd_symbols.push((symbol, opclo_1m_vec.last().unwrap().close_time));
|
|
// // }
|
|
// // }
|
|
// // },
|
|
// // Err(E) => {}
|
|
// // }
|
|
// // }
|
|
// // },
|
|
// // Err(E) => {}
|
|
// // }
|
|
// // }
|
|
|
|
// // }
|
|
|
|
// // }
|
|
// // }
|
|
// // }
|
|
// // } else if market_cap_index.first().unwrap().liquidation_signal == 1 && market_cap_index.first().unwrap().market_cap_index < - 10.0 {
|
|
// // let mut rsi3_1m_vec: Vec<RsiData> = Vec::new();
|
|
// // let mut rsi10_1m_vec: Vec<RsiData> = Vec::new();
|
|
// // let mut rsi30_1m_vec: Vec<RsiData> = Vec::new();
|
|
// // let mut op_low_1m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// // let mut ema3_1m_vec: Vec<EmaData> = Vec::new();
|
|
// // let mut bb30_1m_vec: Vec<BollingerBandData> = Vec::new();
|
|
// // let mut cnt = 0;
|
|
// // for symbol in filtered_symbols {
|
|
// // let rsi3_1m_option = alldata.rsi3_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// // let rsi10_1m_option = alldata.rsi10_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// // let rsi30_1m_option = alldata.rsi30_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// // let op_low_1m_option = alldata.rt_price_1m_vec.iter().position(|x| *x.0 == *symbol);
|
|
// // let ema3_1m_option = alldata.ema3_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// // let bb30_1m_option = alldata.bb30_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
|
|
// // if rsi3_1m_option.is_some() && rsi10_1m_option.is_some() && rsi30_1m_option.is_some() && op_low_1m_option.is_some() && ema3_1m_option.is_some() && bb30_1m_option.is_some() {
|
|
// // rsi3_1m_vec = alldata.rsi3_1m_data[rsi3_1m_option.unwrap()].1.clone();
|
|
// // rsi10_1m_vec = alldata.rsi10_1m_data[rsi10_1m_option.unwrap()].1.clone();
|
|
// // rsi30_1m_vec = alldata.rsi30_1m_data[rsi30_1m_option.unwrap()].1.clone();
|
|
// // op_low_1m_vec = alldata.rt_price_1m_vec[op_low_1m_option.unwrap()].1.clone();
|
|
// // ema3_1m_vec = alldata.ema3_1m_data[ema3_1m_option.unwrap()].1.clone();
|
|
// // bb30_1m_vec = alldata.bb30_1m_data[bb30_1m_option.unwrap()].1.clone();
|
|
|
|
// // if rsi3_1m_vec.len() >= 3 && rsi10_1m_vec.len() >= 3 && rsi30_1m_vec.len() >= 3 && op_low_1m_vec.len() >= 3 && ema3_1m_vec.len() >= 3 && bb30_1m_vec.len() >= 3 {
|
|
// // op_low_1m_vec.reverse();
|
|
// // op_low_1m_vec.truncate(5);
|
|
// // op_low_1m_vec.reverse();
|
|
|
|
// // if op_low_1m_vec.last().unwrap().candle_type == "DOWN" {
|
|
// // cnt = 0;
|
|
// // for element in &op_low_1m_vec {
|
|
// // if element.candle_type == "DOWN" {
|
|
// // cnt += 1;
|
|
// // }
|
|
// // }
|
|
|
|
// // if cnt >= 4 {
|
|
// // let result = ema3_1m_vec.binary_search_by_key(&op_low_1m_vec.last().unwrap().close_time, |&EmaData{ema_value, close_time}|close_time);
|
|
// // match result {
|
|
// // Ok(T) => {
|
|
// // if ema3_1m_vec[T].ema_value > (op_low_1m_vec.last().unwrap().open_price + op_low_1m_vec.last().unwrap().low_price) / 2.0 {
|
|
// // let result = rsi3_1m_vec.binary_search_by_key(&op_low_1m_vec.last().unwrap().close_time, |&RsiData{rsi_value, close_time}|close_time);
|
|
// // match result {
|
|
// // Ok(T) => {
|
|
// // if rsi3_1m_vec[T].rsi_value < 10.0 {
|
|
// // let result = rsi10_1m_vec.binary_search_by_key(&op_low_1m_vec.last().unwrap().close_time, |&RsiData{rsi_value, close_time}|close_time);
|
|
// // match result {
|
|
// // Ok(T) => {
|
|
// // if rsi10_1m_vec[T].rsi_value < 15.0 {
|
|
// // let result = rsi30_1m_vec.binary_search_by_key(&op_low_1m_vec.last().unwrap().close_time, |&RsiData{rsi_value, close_time}|close_time);
|
|
// // match result {
|
|
// // Ok(T) => {
|
|
// // if rsi30_1m_vec[T].rsi_value < 35.0 {
|
|
// // let result = bb30_1m_vec.binary_search_by_key(&op_low_1m_vec.first().unwrap().close_time, |&BollingerBandData{sma, upperband, lowerband, close_time}|close_time);
|
|
// // match result {
|
|
// // Ok(T) => {
|
|
// // if bb30_1m_vec[T].lowerband > (op_low_1m_vec.last().unwrap().open_price + op_low_1m_vec.last().unwrap().low_price) / 2.0 {
|
|
// // filtered_2nd_symbols.push((symbol, op_low_1m_vec.last().unwrap().close_time));
|
|
// // }
|
|
// // },
|
|
// // Err(E) => {},
|
|
// // }
|
|
// // }
|
|
// // },
|
|
// // Err(E) => {}
|
|
// // }
|
|
// // }
|
|
// // },
|
|
// // Err(E) => {}
|
|
// // }
|
|
// // }
|
|
// // },
|
|
// // Err(E) => {}
|
|
// // }
|
|
// // }
|
|
// // },
|
|
// // Err(E) => {}
|
|
// // }
|
|
// // }
|
|
|
|
// // }
|
|
|
|
// // }
|
|
// // }
|
|
// // }
|
|
// // }
|
|
|
|
// insert_pre_suggested_coins(1, &filtered_2nd_symbols, alldata).await;
|
|
|
|
// Ok(())
|
|
// }
|
|
|
|
// pub async fn execute_strategist_for_test(
|
|
// alldata: &AllData,
|
|
// ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|
// // 1st filtering: supertrend(ATR period 10, multiplier: 1.3, 30m close price), the area should be in SELL area.
|
|
// let mut filtered_2nd_symbols: Vec<(String, i64)> = Vec::new(); // (symbol, closetime)
|
|
// let mut opclo_30m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut supertrend_vec: Vec<SupertrendData> = Vec::new();
|
|
// for symbol in &alldata.valid_symbol_vec {
|
|
// let opclo_30m_option = alldata
|
|
// .rt_price_30m_vec
|
|
// .iter()
|
|
// .position(|x| *x.0 == *symbol);
|
|
// let supertrend_option_30m =
|
|
// supertrend(&symbol, &alldata.rt_price_30m_vec, 10, 1.3, true).await;
|
|
|
|
// if opclo_30m_option.is_some() && supertrend_option_30m.is_some() {
|
|
// opclo_30m_vec = alldata.rt_price_30m_vec[opclo_30m_option.unwrap()]
|
|
// .1
|
|
// .clone();
|
|
// supertrend_vec = supertrend_option_30m.unwrap();
|
|
|
|
// if opclo_30m_vec.len() >= 3 && supertrend_vec.len() >= 3 {
|
|
// let supertrend_search_result = supertrend_vec.binary_search_by_key(
|
|
// &opclo_30m_vec.last().unwrap().close_time,
|
|
// |SupertrendData {
|
|
// band_value,
|
|
// signal,
|
|
// area,
|
|
// close_time,
|
|
// }| *close_time,
|
|
// );
|
|
// if supertrend_search_result.is_ok() {
|
|
// if supertrend_vec[supertrend_search_result.unwrap()]
|
|
// .area
|
|
// .contains("DOWN")
|
|
// {
|
|
// filtered_2nd_symbols
|
|
// .push((symbol.clone(), opclo_30m_vec.last().unwrap().close_time));
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 2nd filtering: lookup tables if the tradepair is already there
|
|
// 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_3rd_symbols: Vec<(String, i64)> = Vec::new(); // (symbol, closetime)
|
|
|
|
// for element in filtered_2nd_symbols {
|
|
// let mut exists_condition_build = String::from("symbol=\'");
|
|
// exists_condition_build.push_str(element.0.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 inspect_result_1 = exists_record(&inspect_table_name_1, &exists_condition).await;
|
|
// let inspect_result_2 = exists_record(&inspect_table_name_2, &exists_condition).await;
|
|
// let inspect_result_3 = exists_record(&inspect_table_name_3, &exists_condition).await;
|
|
// let inspect_result_4 = exists_record(&inspect_table_name_4, &exists_condition).await;
|
|
|
|
// if inspect_result_1 == false
|
|
// && inspect_result_2 == false
|
|
// && inspect_result_3 == false
|
|
// && inspect_result_4 == false
|
|
// {
|
|
// filtered_3rd_symbols.push(element);
|
|
// }
|
|
// }
|
|
|
|
// // 3rd filtering: BollingerBand (length 10, stddev: 3.0, 30m close price) the current price should be under the lowerband of BB.
|
|
// let mut bb10_30m_vec: Vec<BollingerBandData> = Vec::new();
|
|
// let mut filtered_4th_symbols: Vec<(String, i64)> = Vec::new(); // (symbol, closetime)
|
|
// for element in filtered_3rd_symbols {
|
|
// let bb10_30m_option = alldata.bb10_30m_data.iter().position(|x| *x.0 == element.0);
|
|
|
|
// if bb10_30m_option.is_some() {
|
|
// bb10_30m_vec = alldata.bb10_30m_data[bb10_30m_option.unwrap()].1.clone();
|
|
|
|
// if bb10_30m_vec.len() >= 3 {
|
|
// let bb_search_result = bb10_30m_vec.binary_search_by_key(
|
|
// &element.1,
|
|
// |&BollingerBandData {
|
|
// sma,
|
|
// upperband,
|
|
// lowerband,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// if bb_search_result.is_ok() {
|
|
// let current_price = get_current_price(&element.0, &alldata.price_vec)
|
|
// .await
|
|
// .unwrap();
|
|
// if bb10_30m_vec[bb_search_result.unwrap()].lowerband > current_price {
|
|
// filtered_4th_symbols.push(element);
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 4th filtering: RSI (length: 10, 30m close price) the current index should be lower than 30.
|
|
// let mut rsi10_30m_vec: Vec<RsiData> = Vec::new();
|
|
// let mut filtered_5th_symbols: Vec<(String, i64)> = Vec::new(); // (symbol, closetime)
|
|
// for element in filtered_4th_symbols {
|
|
// let rsi10_30m_option = alldata
|
|
// .rsi10_30m_data
|
|
// .iter()
|
|
// .position(|x| *x.0 == element.0);
|
|
|
|
// if rsi10_30m_option.is_some() {
|
|
// rsi10_30m_vec = alldata.rsi10_30m_data[rsi10_30m_option.unwrap()].1.clone();
|
|
|
|
// if rsi10_30m_vec.len() >= 3 {
|
|
// let rsi_search_result = rsi10_30m_vec.binary_search_by_key(
|
|
// &element.1,
|
|
// |&RsiData {
|
|
// rsi_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// if rsi_search_result.is_ok() {
|
|
// if rsi10_30m_vec[rsi_search_result.unwrap()].rsi_value <= 30.0 {
|
|
// filtered_5th_symbols.push(element);
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 5th filtering: heatmap volume(MA length 10, std length 10, 30m close price), the current candle should be over than high at least.
|
|
// let mut filtered_6th_symbols: Vec<(String, i64)> = Vec::new(); // (symbol, closetime)
|
|
// for element in filtered_5th_symbols {
|
|
// let opclo_30m_option = alldata
|
|
// .rt_price_30m_vec
|
|
// .iter()
|
|
// .position(|x| *x.0 == element.0);
|
|
// if opclo_30m_option.is_some() {
|
|
// opclo_30m_vec = alldata.rt_price_30m_vec[opclo_30m_option.unwrap()]
|
|
// .1
|
|
// .clone();
|
|
|
|
// if opclo_30m_vec.len() >= 3 {
|
|
// let heatmap_volume_option = heatmap_volume(
|
|
// &element.0,
|
|
// &alldata.rt_price_30m_vec,
|
|
// 10,
|
|
// 10,
|
|
// 4.0,
|
|
// 2.5,
|
|
// 1.0,
|
|
// -0.5,
|
|
// )
|
|
// .await;
|
|
// if heatmap_volume_option.is_some() {
|
|
// let heatmap_volume_vec = heatmap_volume_option.unwrap();
|
|
// let heatmap_search_result = heatmap_volume_vec.binary_search_by_key(
|
|
// &element.1,
|
|
// |HeatmapVolumeData {
|
|
// heatmap_value,
|
|
// heatmap_level,
|
|
// close_time,
|
|
// }| *close_time,
|
|
// );
|
|
// if heatmap_search_result.is_ok() {
|
|
// if heatmap_volume_vec[heatmap_search_result.unwrap()].heatmap_level
|
|
// == HeatMapLevel::Medium
|
|
// || heatmap_volume_vec[heatmap_search_result.unwrap()].heatmap_level
|
|
// == HeatMapLevel::High
|
|
// || heatmap_volume_vec[heatmap_search_result.unwrap()].heatmap_level
|
|
// == HeatMapLevel::ExtraHigh
|
|
// {
|
|
// filtered_6th_symbols.push(element);
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 6th filtering condition: MACD
|
|
// // let mut opclo_30m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// // let mut ema3_1d_vec: &Vec<EmaData> = &Vec::new();
|
|
// // let mut ema10_1d_vec: &Vec<EmaData> = &Vec::new();
|
|
|
|
// // let mut filtered_7th_symbols: Vec<(String, i64)> = Vec::new(); // (symbol, closetime)
|
|
// // for element in filtered_6th_symbols {
|
|
// // let ema3_1d_option = alldata.ema3_1d_data.iter().position(|x| *x.0 == *element.0);
|
|
// // let ema10_1d_option = alldata.ema10_1d_data.iter().position(|x| *x.0 == *element.0);
|
|
|
|
// // if ema3_1d_option.is_some() && ema10_1d_option.is_some() {
|
|
// // ema3_1d_vec = &alldata.ema3_1d_data[ema3_1d_option.unwrap()].1;
|
|
// // ema10_1d_vec = &alldata.ema10_1d_data[ema10_1d_option.unwrap()].1;
|
|
|
|
// // if ema3_1d_vec.len() > 20 && ema10_1d_vec.len() > 20 {
|
|
// // let macd_vec = ema_macd(&ema3_1d_vec, &ema10_1d_vec, 10).await?;
|
|
// // // let macd_search_result = macd_vec.binary_search_by_key(&element.1, |&EmaMacd{macd_value, close_time}|close_time);
|
|
|
|
// // // if macd_search_result.is_ok() {
|
|
// // if macd_vec.last().unwrap().macd_value - macd_vec[macd_vec.len() -2].macd_value >= 0.0 {
|
|
// // filtered_7th_symbols.push(element);
|
|
// // }
|
|
// // // }
|
|
// // }
|
|
// // }
|
|
// // }
|
|
|
|
// insert_pre_suggested_coins(1, &filtered_6th_symbols, alldata).await;
|
|
|
|
// Ok(())
|
|
// }
|
|
|
|
pub async fn execute_strategist_for_test_temp(
|
|
alldata: &AllData,
|
|
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|
// print rt_price for debugging
|
|
// let a = alldata.rt_price_30m_vec.iter().position(|a| a.0 == "BTCUSDT");
|
|
// println!("BTCUSDT: {:?}", alldata.rt_price_30m_vec[a.unwrap()].1.last().unwrap());
|
|
|
|
// 1st filtering: supertrend(ATR period 10, multiplier: 1.3, 30m close price), the area should be in SELL area.
|
|
let mut filtered_2nd_symbols: Vec<(String, i64)> = Vec::new();
|
|
let mut filtered_2nd_symbols_arc: Arc<Mutex<Vec<(String, i64)>>> =
|
|
Arc::new(Mutex::new(filtered_2nd_symbols)); // (symbol, closetime)
|
|
let mut task_vec = Vec::new();
|
|
let valid_symbol_vec_c = alldata.valid_symbol_vec.clone();
|
|
for symbol in valid_symbol_vec_c {
|
|
let mut opclo_30m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
let mut supertrend_vec: Vec<SupertrendData> = Vec::new();
|
|
let rt_price_30m_vec_c = alldata.rt_price_30m_vec.clone();
|
|
let filtered_2nd_symbols_arc_c = Arc::clone(&filtered_2nd_symbols_arc);
|
|
task_vec.push(tokio::spawn(async move {
|
|
let opclo_30m_option = rt_price_30m_vec_c.iter().position(|x| *x.0 == symbol);
|
|
let supertrend_option_30m =
|
|
supertrend(&symbol, &rt_price_30m_vec_c, 10, 1.3, true).await;
|
|
|
|
if opclo_30m_option.is_some() && supertrend_option_30m.is_some() {
|
|
opclo_30m_vec = rt_price_30m_vec_c[opclo_30m_option.unwrap()].1.clone();
|
|
supertrend_vec = supertrend_option_30m.unwrap();
|
|
|
|
if opclo_30m_vec.len() >= 3 && supertrend_vec.len() >= 3 {
|
|
let supertrend_search_result = supertrend_vec.binary_search_by_key(
|
|
&opclo_30m_vec.last().unwrap().close_time,
|
|
|SupertrendData {
|
|
band_value,
|
|
signal,
|
|
area,
|
|
close_time,
|
|
}| *close_time,
|
|
);
|
|
if supertrend_search_result.is_ok() {
|
|
if supertrend_vec[supertrend_search_result.unwrap()]
|
|
.area
|
|
.contains("DOWN")
|
|
{
|
|
let mut filtered_2nd_symbols_lock =
|
|
filtered_2nd_symbols_arc_c.lock().await;
|
|
filtered_2nd_symbols_lock
|
|
.push((symbol.clone(), opclo_30m_vec.last().unwrap().close_time));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}));
|
|
}
|
|
try_join_all(task_vec).await?;
|
|
|
|
// 2nd filtering: lookup tables if the tradepair is already there
|
|
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_3rd_symbols: Vec<(String, i64)> = Vec::new();
|
|
let mut filtered_3rd_symbols_arc: Arc<Mutex<Vec<(String, i64)>>> =
|
|
Arc::new(Mutex::new(filtered_3rd_symbols)); // (symbol, closetime)
|
|
let mut task_vec = Vec::new();
|
|
|
|
let filtered_2nd_iter = filtered_2nd_symbols_arc.lock().await.clone().into_iter();
|
|
for element in filtered_2nd_iter {
|
|
let mut exists_condition_build = String::from("symbol=\'");
|
|
exists_condition_build.push_str(element.0.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 element_c = element.clone();
|
|
let filtered_3rd_symbols_arc_c = Arc::clone(&filtered_3rd_symbols_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_3rd_symbols_lock = filtered_3rd_symbols_arc_c.lock().await;
|
|
filtered_3rd_symbols_lock.push(element_c);
|
|
}
|
|
}));
|
|
}
|
|
try_join_all(task_vec).await?;
|
|
|
|
// 3rd filtering: BollingerBand (length 10, stddev: 2.5, 30m close price) the current price should be under the lowerband of BB.
|
|
let filtered_3rd_symbols_c = filtered_3rd_symbols_arc.lock().await.clone();
|
|
let sma10_30m_data: Vec<(String, Vec<SmaData>)> = value_estimation_team::indicators::sma::sma(
|
|
10,
|
|
&alldata.rt_price_30m_vec,
|
|
&filtered_3rd_symbols_c,
|
|
)
|
|
.await?;
|
|
|
|
let bb10_30m_data: Vec<(String, Vec<BollingerBandData>)> =
|
|
value_estimation_team::indicators::bollingerband::bollingerband(
|
|
10,
|
|
2.5,
|
|
&sma10_30m_data,
|
|
&alldata.rt_price_30m_vec,
|
|
&filtered_3rd_symbols_c,
|
|
)
|
|
.await?;
|
|
|
|
let mut task_vec = Vec::new();
|
|
let mut filtered_4th_symbols: Vec<(String, i64)> = Vec::new();
|
|
let mut filtered_4th_symbols_arc: Arc<Mutex<Vec<(String, i64)>>> =
|
|
Arc::new(Mutex::new(filtered_4th_symbols)); // (symbol, closetime)
|
|
for element in filtered_3rd_symbols_c {
|
|
let mut bb10_30m_vec: Vec<BollingerBandData> = Vec::new();
|
|
let bb10_30m_option = bb10_30m_data.iter().position(|x| *x.0 == element.0);
|
|
let bb10_30m_option_c = bb10_30m_option.clone();
|
|
let element_c = element.clone();
|
|
let filtered_4th_symbols_arc_c = Arc::clone(&filtered_4th_symbols_arc);
|
|
|
|
if bb10_30m_option_c.is_some() {
|
|
bb10_30m_vec = bb10_30m_data[bb10_30m_option_c.unwrap()].1.clone();
|
|
|
|
if bb10_30m_vec.len() >= 3 {
|
|
let bb10_30m_vec_c = bb10_30m_vec.clone();
|
|
let current_price = get_current_price(&element_c.0, &alldata.rt_price_30m_vec)
|
|
.await
|
|
.unwrap();
|
|
task_vec.push(tokio::spawn(async move {
|
|
let bb_search_result = bb10_30m_vec_c.binary_search_by_key(
|
|
&element_c.1,
|
|
|&BollingerBandData {
|
|
sma,
|
|
upperband,
|
|
lowerband,
|
|
close_time,
|
|
}| close_time,
|
|
);
|
|
if bb_search_result.is_ok() {
|
|
if bb10_30m_vec_c[bb_search_result.unwrap()].lowerband > current_price {
|
|
let mut filtered_4th_symbols_lock =
|
|
filtered_4th_symbols_arc_c.lock().await;
|
|
filtered_4th_symbols_lock.push(element_c);
|
|
}
|
|
}
|
|
}));
|
|
}
|
|
}
|
|
}
|
|
try_join_all(task_vec).await?;
|
|
|
|
// 4th filtering: RSI (length: 10, 30m close price) the current index should be lower than 30.
|
|
let filtered_4th_symbol_c = filtered_4th_symbols_arc.lock().await.clone();
|
|
let mut rsi10_30m_data: Vec<(String, Vec<RsiData>)> = Vec::new();
|
|
value_estimation_team::indicators::rsi::rsi(
|
|
10,
|
|
&alldata.rt_price_30m_vec,
|
|
&mut rsi10_30m_data,
|
|
&filtered_4th_symbol_c,
|
|
)
|
|
.await?;
|
|
let mut rsi10_30m_vec: Vec<RsiData> = Vec::new();
|
|
let mut filtered_5th_symbols: Vec<(String, i64)> = Vec::new(); // (symbol, closetime)
|
|
for element in filtered_4th_symbol_c {
|
|
let rsi10_30m_option = rsi10_30m_data.iter().position(|x| *x.0 == element.0);
|
|
|
|
if rsi10_30m_option.is_some() {
|
|
rsi10_30m_vec = rsi10_30m_data[rsi10_30m_option.unwrap()].1.clone();
|
|
|
|
if rsi10_30m_vec.len() >= 3 {
|
|
let rsi_search_result = rsi10_30m_vec.binary_search_by_key(
|
|
&element.1,
|
|
|&RsiData {
|
|
rsi_value,
|
|
close_time,
|
|
}| close_time,
|
|
);
|
|
if rsi_search_result.is_ok() {
|
|
if rsi10_30m_vec[rsi_search_result.unwrap()].rsi_value <= 30.0 {
|
|
filtered_5th_symbols.push(element);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 5th filtering: heatmap volume(MA length 10, std length 10, 30m close price), the current candle should be over than high at least.
|
|
let mut filtered_6th_symbols: Vec<(String, i64)> = Vec::new(); // (symbol, closetime)
|
|
for element in filtered_5th_symbols {
|
|
let rt_price_30m_vec_c = alldata.rt_price_30m_vec.clone();
|
|
let opclo_30m_option = rt_price_30m_vec_c.iter().position(|x| *x.0 == element.0);
|
|
if opclo_30m_option.is_some() {
|
|
let opclo_30m_vec = rt_price_30m_vec_c[opclo_30m_option.unwrap()].1.clone();
|
|
|
|
if opclo_30m_vec.len() >= 3 {
|
|
let heatmap_volume_option =
|
|
heatmap_volume(&element.0, &rt_price_30m_vec_c, 10, 10, 4.0, 2.5, 1.0, -0.5)
|
|
.await;
|
|
if heatmap_volume_option.is_some() {
|
|
let heatmap_volume_vec = heatmap_volume_option.unwrap();
|
|
let heatmap_search_result = heatmap_volume_vec.binary_search_by_key(
|
|
&element.1,
|
|
|HeatmapVolumeData {
|
|
heatmap_value,
|
|
heatmap_level,
|
|
close_time,
|
|
}| *close_time,
|
|
);
|
|
if heatmap_search_result.is_ok() {
|
|
if heatmap_volume_vec[heatmap_search_result.unwrap()].heatmap_level
|
|
== HeatMapLevel::Medium
|
|
|| heatmap_volume_vec[heatmap_search_result.unwrap()].heatmap_level
|
|
== HeatMapLevel::High
|
|
|| heatmap_volume_vec[heatmap_search_result.unwrap()].heatmap_level
|
|
== HeatMapLevel::ExtraHigh
|
|
{
|
|
filtered_6th_symbols.push(element);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// final job: adding price information to filtered results
|
|
let mut filtered_symbols: Vec<(String, i64, f64)> = Vec::new(); // (symbol, closetime, current price)
|
|
let mut filtered_symbols_arc = Arc::new(Mutex::new(filtered_symbols));
|
|
let mut task_vec = Vec::new();
|
|
for element in filtered_6th_symbols {
|
|
let mut filtered_symbols_arc_c = Arc::clone(&filtered_symbols_arc);
|
|
let rt_price_30m_vec_c = alldata.rt_price_30m_vec.clone();
|
|
|
|
let elememt_c = element.clone();
|
|
task_vec.push(tokio::spawn(async move {
|
|
let opclo_30m_option = rt_price_30m_vec_c.iter().position(|x| *x.0 == element.0);
|
|
if opclo_30m_option.is_some() {
|
|
if rt_price_30m_vec_c[opclo_30m_option.unwrap()].1.last().is_some() {
|
|
let mut filtered_symbols_lock: tokio::sync::MutexGuard<'_, Vec<(String, i64, f64)>> = filtered_symbols_arc_c.lock().await;
|
|
filtered_symbols_lock.push((elememt_c.0, elememt_c.1, rt_price_30m_vec_c[opclo_30m_option.unwrap()].1.last().unwrap().close_price));
|
|
}
|
|
}
|
|
}));
|
|
}
|
|
|
|
try_join_all(task_vec).await?;
|
|
|
|
// 6th filtering condition: MACD
|
|
// let mut opclo_30m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut ema3_1d_vec: &Vec<EmaData> = &Vec::new();
|
|
// let mut ema10_1d_vec: &Vec<EmaData> = &Vec::new();
|
|
|
|
// let mut filtered_7th_symbols: Vec<(String, i64)> = Vec::new(); // (symbol, closetime)
|
|
// for element in filtered_6th_symbols {
|
|
// let ema3_1d_option = alldata.ema3_1d_data.iter().position(|x| *x.0 == *element.0);
|
|
// let ema10_1d_option = alldata.ema10_1d_data.iter().position(|x| *x.0 == *element.0);
|
|
|
|
// if ema3_1d_option.is_some() && ema10_1d_option.is_some() {
|
|
// ema3_1d_vec = &alldata.ema3_1d_data[ema3_1d_option.unwrap()].1;
|
|
// ema10_1d_vec = &alldata.ema10_1d_data[ema10_1d_option.unwrap()].1;
|
|
|
|
// if ema3_1d_vec.len() > 20 && ema10_1d_vec.len() > 20 {
|
|
// let macd_vec = ema_macd(&ema3_1d_vec, &ema10_1d_vec, 10).await?;
|
|
// // let macd_search_result = macd_vec.binary_search_by_key(&element.1, |&EmaMacd{macd_value, close_time}|close_time);
|
|
|
|
// // if macd_search_result.is_ok() {
|
|
// if macd_vec.last().unwrap().macd_value - macd_vec[macd_vec.len() -2].macd_value >= 0.0 {
|
|
// filtered_7th_symbols.push(element);
|
|
// }
|
|
// // }
|
|
// }
|
|
// }
|
|
// }
|
|
let a = filtered_symbols_arc.lock().await.clone();
|
|
insert_pre_suggested_coins(1, &a, alldata).await;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
// pub async fn execute_strategist_for_test1(
|
|
// alldata: &AllData,
|
|
// ) -> Result<(), 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 market_cap_index = select_marketcap().await;
|
|
|
|
// let mut filtered_symbols: Vec<String> = Vec::new();
|
|
// // filtered_symbols.push(String::from("BNBUSDT"));
|
|
// filtered_symbols.push(String::from("BTCUSDT"));
|
|
// // filtered_symbols.push(String::from("ETHUSDT"));
|
|
// // filtered_symbols.push(String::from("LTCUSDT"));
|
|
// // filtered_symbols.push(String::from("XRPUSDT"));
|
|
// // filtered_symbols.push(String::from("TRXUSDT"));
|
|
// // let current_price = get_current_price(&filtered_symbols.first().unwrap(), &alldata.price_vec).await.unwrap();
|
|
|
|
// let mut filtered_2nd_symbols: Vec<(String, i64)> = Vec::new(); // (symbol, closetime)
|
|
// let mut ema3_1m_vec: &Vec<EmaData> = &Vec::new();
|
|
// let mut ema3_30m_vec: &Vec<EmaData> = &Vec::new();
|
|
// let mut ema10_1m_vec: &Vec<EmaData> = &Vec::new();
|
|
// let mut ema30_1m_vec: &Vec<EmaData> = &Vec::new();
|
|
// let mut sma10_1m_vec: &Vec<SmaData> = &Vec::new();
|
|
// let mut sma3_30m_vec: &Vec<SmaData> = &Vec::new();
|
|
// let mut sma30_1m_vec: &Vec<SmaData> = &Vec::new();
|
|
// let mut rsi3_1m_vec: &Vec<RsiData> = &Vec::new();
|
|
// let mut rsi30_1m_vec: &Vec<RsiData> = &Vec::new();
|
|
// let mut stoch_rsi3_1m_k_vec: &Vec<StochRsiKData> = &Vec::new();
|
|
// let mut stoch_rsi3_1m_d_vec: &Vec<StochRsiDData> = &Vec::new();
|
|
// let mut stoch_rsi30_1m_k_vec: &Vec<StochRsiKData> = &Vec::new();
|
|
// let mut stoch_rsi30_1m_d_vec: &Vec<StochRsiDData> = &Vec::new();
|
|
// let mut rt_price_1m_vec: &Vec<RealtimePriceData> = &Vec::new();
|
|
// let mut is_filtering_passed: bool = false;
|
|
|
|
// let mut cnt = 0;
|
|
// let exists_condition = Some(String::from("used_usdt >= 10.0 AND registerer = 1"));
|
|
// let inspect_result_1 = exists_record(&inspect_table_name_1, &exists_condition).await;
|
|
// let inspect_result_2 = exists_record(&inspect_table_name_2, &exists_condition).await;
|
|
// let mut is_buy_period_30m = false;
|
|
|
|
// if inspect_result_1 == false && inspect_result_2 == false {
|
|
// for symbol in filtered_symbols {
|
|
// is_filtering_passed = false;
|
|
// let ema3_1m_option = alldata.ema3_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let ema3_30m_option = alldata.ema3_30m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let ema10_1m_option = alldata.ema10_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let ema30_1m_option = alldata.ema30_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let sma10_1m_option = alldata.sma10_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let sma3_30m_option = alldata.sma3_30m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let sma30_1m_option = alldata.sma30_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let rsi3_1m_option = alldata.rsi3_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let rsi30_1m_option = alldata.rsi30_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let stoch_rsi3_1m_k_option = alldata
|
|
// .stoch_rsi3_1m_3_k_data
|
|
// .iter()
|
|
// .position(|x| *x.0 == *symbol);
|
|
// let stoch_rsi3_1m_d_option = alldata
|
|
// .stoch_rsi3_1m_3_d_data
|
|
// .iter()
|
|
// .position(|x| *x.0 == *symbol);
|
|
// let stoch_rsi30_1m_k_option = alldata
|
|
// .stoch_rsi30_1m_30_k_data
|
|
// .iter()
|
|
// .position(|x| *x.0 == *symbol);
|
|
// let stoch_rsi30_1m_d_option = alldata
|
|
// .stoch_rsi30_1m_30_d_data
|
|
// .iter()
|
|
// .position(|x| *x.0 == *symbol);
|
|
// let rt_price_1m_option = alldata.rt_price_1m_vec.iter().position(|x| *x.0 == *symbol);
|
|
|
|
// let supertrend_option_30m =
|
|
// supertrend(&symbol, &alldata.rt_price_30m_vec, 3, 0.5, true).await;
|
|
|
|
// if supertrend_option_30m.is_some() {
|
|
// let supertrend_vec = supertrend_option_30m.unwrap();
|
|
// if supertrend_vec.last().unwrap().area.contains("UP") {
|
|
// is_buy_period_30m = true;
|
|
// }
|
|
// }
|
|
|
|
// if is_buy_period_30m == true
|
|
// && ema3_1m_option.is_some()
|
|
// && ema3_30m_option.is_some()
|
|
// && ema10_1m_option.is_some()
|
|
// && ema30_1m_option.is_some()
|
|
// && sma10_1m_option.is_some()
|
|
// && sma3_30m_option.is_some()
|
|
// && sma30_1m_option.is_some()
|
|
// && rsi3_1m_option.is_some()
|
|
// && rsi30_1m_option.is_some()
|
|
// && stoch_rsi3_1m_k_option.is_some()
|
|
// && stoch_rsi3_1m_d_option.is_some()
|
|
// && stoch_rsi30_1m_k_option.is_some()
|
|
// && stoch_rsi30_1m_d_option.is_some()
|
|
// && rt_price_1m_option.is_some()
|
|
// {
|
|
// ema3_1m_vec = &alldata.ema3_1m_data[ema3_1m_option.unwrap()].1;
|
|
// ema3_30m_vec = &alldata.ema3_30m_data[ema3_30m_option.unwrap()].1;
|
|
// ema10_1m_vec = &alldata.ema10_1m_data[ema10_1m_option.unwrap()].1;
|
|
// ema30_1m_vec = &alldata.ema30_1m_data[ema30_1m_option.unwrap()].1;
|
|
// sma10_1m_vec = &alldata.sma10_1m_data[sma10_1m_option.unwrap()].1;
|
|
// sma3_30m_vec = &alldata.sma3_30m_data[sma3_30m_option.unwrap()].1;
|
|
// sma30_1m_vec = &alldata.sma30_1m_data[sma30_1m_option.unwrap()].1;
|
|
// rsi3_1m_vec = &alldata.rsi3_1m_data[rsi3_1m_option.unwrap()].1;
|
|
// rsi30_1m_vec = &alldata.rsi30_1m_data[rsi30_1m_option.unwrap()].1;
|
|
// stoch_rsi3_1m_k_vec =
|
|
// &alldata.stoch_rsi3_1m_3_k_data[stoch_rsi3_1m_k_option.unwrap()].1;
|
|
// stoch_rsi3_1m_d_vec =
|
|
// &alldata.stoch_rsi3_1m_3_d_data[stoch_rsi3_1m_d_option.unwrap()].1;
|
|
// stoch_rsi30_1m_k_vec =
|
|
// &alldata.stoch_rsi30_1m_30_k_data[stoch_rsi30_1m_k_option.unwrap()].1;
|
|
// stoch_rsi30_1m_d_vec =
|
|
// &alldata.stoch_rsi30_1m_30_d_data[stoch_rsi30_1m_d_option.unwrap()].1;
|
|
// rt_price_1m_vec = &alldata.rt_price_1m_vec[rt_price_1m_option.unwrap()].1;
|
|
|
|
// // filtering condition: data are ready
|
|
// if ema3_1m_vec.len() >= 3
|
|
// && ema3_30m_vec.len() >= 3
|
|
// && ema10_1m_vec.len() >= 3
|
|
// && ema30_1m_vec.len() >= 3
|
|
// && sma10_1m_vec.len() >= 3
|
|
// && sma3_30m_vec.len() >= 3
|
|
// && sma30_1m_vec.len() >= 3
|
|
// && rsi3_1m_vec.len() >= 3
|
|
// && rsi30_1m_vec.len() >= 3
|
|
// && stoch_rsi3_1m_k_vec.len() >= 5
|
|
// && stoch_rsi3_1m_d_vec.len() >= 5
|
|
// && stoch_rsi30_1m_k_vec.len() >= 5
|
|
// && stoch_rsi30_1m_d_vec.len() >= 5
|
|
// && rt_price_1m_vec.len() >= 50
|
|
// {
|
|
// is_filtering_passed = true;
|
|
// }
|
|
|
|
// // // filtering condition: SuperTrend & EMA & SMA
|
|
// // if is_filtering_passed == true {
|
|
// // let supertrend_option = supertrend(&symbol, &alldata.rt_price_1m_vec, 10, 1.0, false).await;
|
|
// // if supertrend_option.is_some() {
|
|
// // let supertrend_vec = supertrend_option.unwrap();
|
|
// // let supertrend_result = supertrend_vec.binary_search_by_key(&rt_price_1m_vec.last().unwrap().close_time, |SupertrendData{band_value, signal, area, close_time}| *close_time);
|
|
// // let ema3_result = ema3_1m_vec.binary_search_by_key(&rt_price_1m_vec.last().unwrap().close_time, |&EmaData{ema_value, close_time}|close_time);
|
|
// // let sma10_result = sma10_1m_vec.binary_search_by_key(&rt_price_1m_vec.last().unwrap().close_time, |&SmaData{sma_value, close_time}|close_time);
|
|
|
|
// // if supertrend_vec.last().unwrap().signal.is_some() && ema3_result.is_ok() && sma10_result.is_ok() {
|
|
// // if (((supertrend_vec.last().unwrap().signal.as_ref().unwrap().contains("BUY") && ema3_1m_vec[ema3_result.unwrap()].ema_value > sma10_1m_vec[sma10_result.unwrap()].sma_value) && rt_price_1m_vec.last().unwrap().close_price <= supertrend_vec[supertrend_vec.len()-2].band_value * 1.0005)
|
|
// // || (supertrend_vec.last().unwrap().area.contains("UP") && ema3_1m_vec[ema3_result.unwrap()-1].ema_value < sma10_1m_vec[sma10_result.unwrap()-1].sma_value && ema3_1m_vec[ema3_result.unwrap()].ema_value > sma10_1m_vec[sma10_result.unwrap()].sma_value))
|
|
// // && sma10_1m_vec[sma10_result.unwrap()-2].sma_value < sma10_1m_vec[sma10_result.unwrap()].sma_value {
|
|
// // is_filtering_passed = true;
|
|
// // } else { is_filtering_passed = false; }
|
|
// // } else { is_filtering_passed = false; }
|
|
// // } else { is_filtering_passed = false; }
|
|
// // }
|
|
|
|
// // filtering condition: SuperTrend
|
|
// if is_filtering_passed == true {
|
|
// let supertrend_option =
|
|
// supertrend(&symbol, &alldata.rt_price_1m_vec, 30, 1.5, false).await;
|
|
// if supertrend_option.is_some() {
|
|
// let supertrend_vec = supertrend_option.unwrap();
|
|
// let supertrend_result = supertrend_vec.binary_search_by_key(
|
|
// &rt_price_1m_vec.last().unwrap().close_time,
|
|
// |SupertrendData {
|
|
// band_value,
|
|
// signal,
|
|
// area,
|
|
// close_time,
|
|
// }| *close_time,
|
|
// );
|
|
|
|
// if supertrend_result.is_ok() {
|
|
// if supertrend_vec[supertrend_result.unwrap()]
|
|
// .signal
|
|
// .as_ref()
|
|
// .is_some()
|
|
// {
|
|
// if supertrend_vec[supertrend_result.unwrap()]
|
|
// .signal
|
|
// .as_ref()
|
|
// .unwrap()
|
|
// .contains("BUY")
|
|
// && supertrend_vec[supertrend_result.unwrap() - 1].band_value
|
|
// + ((rt_price_1m_vec[rt_price_1m_vec.len() - 2].high_price
|
|
// - rt_price_1m_vec[rt_price_1m_vec.len() - 2].low_price)
|
|
// * 0.1)
|
|
// > rt_price_1m_vec.last().unwrap().close_price
|
|
// {
|
|
// is_filtering_passed = true;
|
|
// } else {
|
|
// is_filtering_passed = false;
|
|
// }
|
|
// } else {
|
|
// is_filtering_passed = false;
|
|
// }
|
|
// } else {
|
|
// is_filtering_passed = false;
|
|
// }
|
|
// } else {
|
|
// is_filtering_passed = false;
|
|
// }
|
|
// }
|
|
|
|
// // filtering condition: SMA & EMA
|
|
// if is_filtering_passed == true {
|
|
// let sma10_1m_result = sma10_1m_vec.binary_search_by_key(
|
|
// &rt_price_1m_vec.last().unwrap().close_time,
|
|
// |&SmaData {
|
|
// sma_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// let sma30_1m_result = sma30_1m_vec.binary_search_by_key(
|
|
// &rt_price_1m_vec.last().unwrap().close_time,
|
|
// |&SmaData {
|
|
// sma_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// let ema3_1m_result = ema3_1m_vec.binary_search_by_key(
|
|
// &rt_price_1m_vec.last().unwrap().close_time,
|
|
// |&EmaData {
|
|
// ema_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// let ema3_30m_result = ema3_30m_vec.binary_search_by_key(
|
|
// &sma3_30m_vec.last().unwrap().close_time,
|
|
// |&EmaData {
|
|
// ema_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// let ema10_1m_result = ema10_1m_vec.binary_search_by_key(
|
|
// &rt_price_1m_vec.last().unwrap().close_time,
|
|
// |&EmaData {
|
|
// ema_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// let ema30_1m_result = ema30_1m_vec.binary_search_by_key(
|
|
// &rt_price_1m_vec.last().unwrap().close_time,
|
|
// |&EmaData {
|
|
// ema_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// if sma10_1m_result.is_ok()
|
|
// && sma30_1m_result.is_ok()
|
|
// && ema3_1m_result.is_ok()
|
|
// && ema10_1m_result.is_ok()
|
|
// && ema30_1m_result.is_ok()
|
|
// && ema3_30m_result.is_ok()
|
|
// {
|
|
// if ema3_1m_vec[ema3_1m_result.unwrap()].ema_value
|
|
// >= ema10_1m_vec[ema10_1m_result.unwrap()].ema_value
|
|
// {
|
|
// is_filtering_passed = true;
|
|
// } else {
|
|
// is_filtering_passed = false;
|
|
// }
|
|
// } else {
|
|
// is_filtering_passed = false;
|
|
// }
|
|
// }
|
|
|
|
// // filtering condition: current price limitation
|
|
// // if is_filtering_passed == true {
|
|
// // if rt_price_1m_vec[rt_price_1m_vec.len()-2].close_price + ((rt_price_1m_vec[rt_price_1m_vec.len()-2].high_price - rt_price_1m_vec[rt_price_1m_vec.len()-2].low_price) * 0.1) > rt_price_1m_vec.last().unwrap().close_price {
|
|
// // is_filtering_passed = true;
|
|
// // } else { is_filtering_passed = false; }
|
|
// // }
|
|
|
|
// // filtering condition: Heatmap Volume
|
|
// // if is_filtering_passed == true {
|
|
// // let heatmap_volume_option = heatmap_volume(&symbol, &alldata.rt_price_1m_vec, 30, 30, 4.0, 2.5, 1.0, -0.5).await;
|
|
// // if heatmap_volume_option.is_some() {
|
|
// // let heatmap_volume_vec = heatmap_volume_option.unwrap();
|
|
// // let heatmap_search_result = heatmap_volume_vec.binary_search_by_key(&rt_price_1m_vec.last().unwrap().close_time, |HeatmapVolumeData{heatmap_value, heatmap_level, close_time}|*close_time);
|
|
// // if heatmap_search_result.is_ok() {
|
|
// // let heatmap_volume_trunc_vec_option = heatmap_volume_vec.get(heatmap_search_result.unwrap()-11..heatmap_search_result.unwrap()-1);
|
|
// // if heatmap_volume_trunc_vec_option.is_some() {
|
|
// // let heatmap_volume_trunc_vec = heatmap_volume_trunc_vec_option.unwrap();
|
|
// // let mut heat_value_summation = 0.0;
|
|
// // for element in heatmap_volume_trunc_vec {
|
|
// // if element.heatmap_level == HeatMapLevel::ExtraHigh {
|
|
// // heat_value_summation += 2.0;
|
|
// // } else if element.heatmap_level == HeatMapLevel::High {
|
|
// // heat_value_summation += 1.5;
|
|
// // } else if element.heatmap_level == HeatMapLevel::Medium {
|
|
// // heat_value_summation += 1.0;
|
|
// // } else if element.heatmap_level == HeatMapLevel::Normal {
|
|
// // heat_value_summation += 0.5;
|
|
// // } else {
|
|
// // heat_value_summation += 0.0;
|
|
// // }
|
|
// // }
|
|
// // if heat_value_summation >= 2.0 {
|
|
// // is_filtering_passed = true;
|
|
// // } else { is_filtering_passed = false; }
|
|
// // }
|
|
// // }
|
|
// // } else { is_filtering_passed = false; }
|
|
// // }
|
|
|
|
// // filtering condition: Stoch RSI
|
|
// if is_filtering_passed == true {
|
|
// // let sample_length: usize = 5;
|
|
// // stoch_rsi10_1m_k_vec.reverse();
|
|
// // stoch_rsi10_1m_k_vec.truncate(5);
|
|
// // stoch_rsi10_1m_k_vec.reverse();
|
|
// // stoch_rsi10_1m_d_vec.reverse();
|
|
// // stoch_rsi10_1m_d_vec.truncate(5);
|
|
// // stoch_rsi10_1m_d_vec.reverse();
|
|
// let rsi3_k_result = stoch_rsi3_1m_k_vec.binary_search_by_key(
|
|
// &rt_price_1m_vec.last().unwrap().close_time,
|
|
// |&StochRsiKData {
|
|
// stoch_rsi_k_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// let rsi3_d_result = stoch_rsi3_1m_d_vec.binary_search_by_key(
|
|
// &rt_price_1m_vec.last().unwrap().close_time,
|
|
// |&StochRsiDData {
|
|
// stoch_rsi_d_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// let rsi30_k_result = stoch_rsi30_1m_k_vec.binary_search_by_key(
|
|
// &rt_price_1m_vec.last().unwrap().close_time,
|
|
// |&StochRsiKData {
|
|
// stoch_rsi_k_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// let rsi30_d_result = stoch_rsi30_1m_d_vec.binary_search_by_key(
|
|
// &rt_price_1m_vec.last().unwrap().close_time,
|
|
// |&StochRsiDData {
|
|
// stoch_rsi_d_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// if rsi30_k_result.is_ok()
|
|
// && rsi30_d_result.is_ok()
|
|
// && rsi3_k_result.is_ok()
|
|
// && rsi3_d_result.is_ok()
|
|
// {
|
|
// if stoch_rsi30_1m_k_vec[rsi30_k_result.unwrap()].stoch_rsi_k_value
|
|
// >= stoch_rsi30_1m_d_vec[rsi30_d_result.unwrap()].stoch_rsi_d_value
|
|
// && stoch_rsi30_1m_k_vec[rsi30_k_result.unwrap() - 1].stoch_rsi_k_value
|
|
// >= stoch_rsi30_1m_d_vec[rsi30_d_result.unwrap() - 1]
|
|
// .stoch_rsi_d_value
|
|
// && stoch_rsi30_1m_k_vec[rsi30_k_result.unwrap()].stoch_rsi_k_value
|
|
// <= 50.0
|
|
// // (stoch_rsi30_1m_k_vec[rsi30_k_result.unwrap()].stoch_rsi_k_value >= stoch_rsi30_1m_d_vec[rsi30_d_result.unwrap()].stoch_rsi_d_value
|
|
// // && stoch_rsi30_1m_d_vec[rsi30_d_result.unwrap()].stoch_rsi_d_value > stoch_rsi30_1m_d_vec[rsi30_d_result.unwrap()-1].stoch_rsi_d_value
|
|
// // && stoch_rsi30_1m_k_vec[rsi30_k_result.unwrap()].stoch_rsi_k_value < 80.0)
|
|
// // ||
|
|
// // && (stoch_rsi3_1m_k_vec[rsi3_k_result.unwrap()-1].stoch_rsi_k_value <= 60.0
|
|
// // && stoch_rsi3_1m_k_vec[rsi3_k_result.unwrap()-2].stoch_rsi_k_value >= stoch_rsi3_1m_k_vec[rsi3_k_result.unwrap()-1].stoch_rsi_k_value
|
|
// // && stoch_rsi3_1m_k_vec[rsi3_k_result.unwrap()-1].stoch_rsi_k_value <= stoch_rsi3_1m_d_vec[rsi3_d_result.unwrap()-1].stoch_rsi_d_value
|
|
// // && stoch_rsi30_1m_k_vec[rsi30_k_result.unwrap()-1].stoch_rsi_k_value <= stoch_rsi30_1m_d_vec[rsi30_d_result.unwrap()-1].stoch_rsi_d_value)
|
|
// // // && stoch_rsi30_1m_k_vec[rsi30_k_result.unwrap()].stoch_rsi_k_value < 80.0)
|
|
// // || (stoch_rsi3_1m_k_vec[rsi3_k_result.unwrap()].stoch_rsi_k_value == 100.0
|
|
// // && stoch_rsi3_1m_k_vec[rsi3_k_result.unwrap()].stoch_rsi_k_value == 100.0
|
|
// // && stoch_rsi30_1m_k_vec[rsi30_k_result.unwrap()].stoch_rsi_k_value >= stoch_rsi30_1m_d_vec[rsi30_d_result.unwrap()].stoch_rsi_d_value
|
|
// // && stoch_rsi30_1m_k_vec[rsi30_k_result.unwrap()].stoch_rsi_k_value < 80.0)
|
|
// {
|
|
// is_filtering_passed = true;
|
|
// } else {
|
|
// is_filtering_passed = false;
|
|
// }
|
|
// } else {
|
|
// is_filtering_passed = false;
|
|
// }
|
|
// }
|
|
|
|
// // filtering condition: MACD
|
|
// if is_filtering_passed == true {
|
|
// let macd_vec = ema_macd(&ema3_1m_vec, &ema10_1m_vec, 10).await?;
|
|
// let macd_search_result = macd_vec.binary_search_by_key(
|
|
// &rt_price_1m_vec.last().unwrap().close_time,
|
|
// |&EmaMacd {
|
|
// macd_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
|
|
// if macd_search_result.is_ok() {
|
|
// if macd_vec[macd_search_result.unwrap()].macd_value
|
|
// > macd_vec[macd_search_result.unwrap() - 1].macd_value
|
|
// {
|
|
// is_filtering_passed = true;
|
|
// } else {
|
|
// is_filtering_passed = false;
|
|
// }
|
|
// } else {
|
|
// is_filtering_passed = false;
|
|
// }
|
|
// }
|
|
|
|
// // filtering condition: Ratio between amplitude and body of candles
|
|
// if is_filtering_passed == true {
|
|
// let sample_length: usize = 5; // 5 candle samsples
|
|
// let rt_price_1m_partial_vec_option = rt_price_1m_vec
|
|
// .get(rt_price_1m_vec.len() - sample_length - 1..rt_price_1m_vec.len() - 1);
|
|
// if rt_price_1m_partial_vec_option.is_some() {
|
|
// let rt_price_1m_partial_vec = rt_price_1m_partial_vec_option.unwrap();
|
|
|
|
// let mut sum_ratio_amp_body = 0.0;
|
|
// for element in rt_price_1m_partial_vec {
|
|
// sum_ratio_amp_body += (element.close_price - element.open_price).abs()
|
|
// / (element.high_price - element.low_price);
|
|
// }
|
|
// let average_ratio_amp_body = sum_ratio_amp_body / sample_length as f64;
|
|
// if average_ratio_amp_body > 0.3 {
|
|
// is_filtering_passed = true;
|
|
// } else {
|
|
// is_filtering_passed = false;
|
|
// }
|
|
// } else {
|
|
// is_filtering_passed = false;
|
|
// }
|
|
// }
|
|
|
|
// // check all filterings are passed
|
|
// if is_filtering_passed == true {
|
|
// filtered_2nd_symbols.push((symbol, rt_price_1m_vec.last().unwrap().close_time));
|
|
// }
|
|
|
|
// // if ema3_1m_vec.len() >= 3 && ema10_1m_vec.len() >= 3 && ema30_1m_vec.len() >= 3 && sma10_1m_vec.len() >= 3 && rsi3_1m_vec.len() >= 3 && stoch_rsi10_1m_k_vec.len() >= 5 && stoch_rsi10_1m_d_vec.len() >= 5 && stoch_rsi30_1m_k_vec.len() >= 5 && stoch_rsi30_1m_d_vec.len() >= 5 && rt_price_1m_vec.len() >= 10 {
|
|
// // stoch_rsi10_1m_k_vec.reverse();
|
|
// // stoch_rsi10_1m_k_vec.truncate(5);
|
|
// // stoch_rsi10_1m_k_vec.reverse();
|
|
// // stoch_rsi10_1m_d_vec.reverse();
|
|
// // stoch_rsi10_1m_d_vec.truncate(5);
|
|
// // stoch_rsi10_1m_d_vec.reverse();
|
|
// // stoch_rsi30_1m_k_vec.reverse();
|
|
// // stoch_rsi30_1m_k_vec.truncate(5);
|
|
// // stoch_rsi30_1m_k_vec.reverse();
|
|
// // stoch_rsi30_1m_d_vec.reverse();
|
|
// // stoch_rsi30_1m_d_vec.truncate(5);
|
|
// // stoch_rsi30_1m_d_vec.reverse();
|
|
// // let supertrend_option = supertrend(&symbol, &alldata.rt_price_1m_vec, 10, 1.0, false).await;
|
|
// // let heatmap_volume_option = heatmap_volume(&symbol, &alldata.rt_price_1m_vec, 30, 30, 4.0, 2.5, 1.0, -0.5).await;
|
|
// // let macd_vec = ema_macd(&ema10_1m_vec, &ema30_1m_vec, 30).await?;
|
|
|
|
// // if supertrend_option.is_some() && heatmap_volume_option.is_some() {
|
|
// // let supertrend_vec = supertrend_option.unwrap();
|
|
// // let heatmap_volume_vec = heatmap_volume_option.unwrap();
|
|
// // let heatmap_search_result = heatmap_volume_vec.binary_search_by_key(&supertrend_vec.last().unwrap().close_time, |HeatmapVolumeData{heatmap_value, heatmap_level, close_time}|*close_time);
|
|
// // let macd_search_result = macd_vec.binary_search_by_key(&supertrend_vec.last().unwrap().close_time, |&EmaMacd{macd_value, close_time}|close_time);
|
|
// // let ema3_result = ema3_1m_vec.binary_search_by_key(&supertrend_vec.last().unwrap().close_time, |&EmaData{ema_value, close_time}|close_time);
|
|
// // let ema10_result = ema10_1m_vec.binary_search_by_key(&supertrend_vec.last().unwrap().close_time, |&EmaData{ema_value, close_time}|close_time);
|
|
// // let ema30_result = ema30_1m_vec.binary_search_by_key(&supertrend_vec.last().unwrap().close_time, |&EmaData{ema_value, close_time}|close_time);
|
|
// // let sma10_result = sma10_1m_vec.binary_search_by_key(&supertrend_vec.last().unwrap().close_time, |&SmaData{sma_value, close_time}|close_time);
|
|
|
|
// // if supertrend_vec.last().unwrap().signal.is_some() && heatmap_search_result.is_ok() && macd_search_result.is_ok() && ema3_result.is_ok() && ema10_result.is_ok() && ema30_result.is_ok() && sma10_result.is_ok() {
|
|
// // // if supertrend_vec.last().unwrap().signal.as_ref().unwrap().contains("BUY")
|
|
// // // && macd_vec[macd_search_result.unwrap()].macd_value > macd_vec[macd_search_result.unwrap()-1].macd_value {
|
|
// // // {
|
|
// // if ((supertrend_vec.last().unwrap().signal.as_ref().unwrap().contains("BUY") && ema3_1m_vec[ema3_result.unwrap()].ema_value > sma10_1m_vec[sma10_result.unwrap()].sma_value) && current_price <= supertrend_vec[supertrend_vec.len()-2].band_value * 1.0005)
|
|
// // || (supertrend_vec.last().unwrap().area.contains("UP") && ema3_1m_vec[ema3_result.unwrap()-1].ema_value < sma10_1m_vec[sma10_result.unwrap()-1].sma_value && ema3_1m_vec[ema3_result.unwrap()].ema_value > sma10_1m_vec[sma10_result.unwrap()].sma_value)
|
|
// // // && current_price >= ema30_1m_vec[ema30_result.unwrap()].ema_value
|
|
// // // && ema10_1m_vec[ema10_result.unwrap()-1].ema_value < ema10_1m_vec[ema10_result.unwrap()].ema_value
|
|
|
|
// // // && ema10_1m_vec[ema10_result.unwrap()].ema_value >= ema30_1m_vec[ema30_result.unwrap()].ema_value
|
|
// // {
|
|
// // let k_result = stoch_rsi30_1m_k_vec.binary_search_by_key(&supertrend_vec.last().unwrap().close_time, |&StochRsiKData{stoch_rsi_k_value, close_time}|close_time);
|
|
// // let d_result = stoch_rsi30_1m_d_vec.binary_search_by_key(&supertrend_vec.last().unwrap().close_time, |&StochRsiDData{stoch_rsi_d_value, close_time}|close_time);
|
|
// // if k_result.is_ok() && d_result.is_ok() {
|
|
// // if stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value > stoch_rsi30_1m_d_vec[d_result.unwrap()].stoch_rsi_d_value {
|
|
// // let heatmap_volume_trunc_vec_option = heatmap_volume_vec.get(heatmap_search_result.unwrap()-11..heatmap_search_result.unwrap()-1);
|
|
// // if heatmap_volume_trunc_vec_option.is_some() {
|
|
// // let heatmap_volume_trunc_vec = heatmap_volume_trunc_vec_option.unwrap();
|
|
// // let mut heat_value_summation = 0.0;
|
|
// // for element in heatmap_volume_trunc_vec {
|
|
// // if element.heatmap_level == HeatMapLevel::ExtraHigh {
|
|
// // heat_value_summation += 2.0;
|
|
// // } else if element.heatmap_level == HeatMapLevel::High {
|
|
// // heat_value_summation += 1.5;
|
|
// // } else if element.heatmap_level == HeatMapLevel::Medium {
|
|
// // heat_value_summation += 1.0;
|
|
// // } else if element.heatmap_level == HeatMapLevel::Normal {
|
|
// // heat_value_summation += 0.5;
|
|
// // } else {
|
|
// // heat_value_summation += 0.0;
|
|
// // }
|
|
// // }
|
|
// // if heat_value_summation >= 3.0 {
|
|
// // filtered_2nd_symbols.push((symbol, supertrend_vec.last().unwrap().close_time));
|
|
// // }
|
|
// // }
|
|
// // }
|
|
// // }
|
|
// // }
|
|
// // // }
|
|
// // }
|
|
// // }
|
|
// // // if macd_search_result.is_ok() {
|
|
// // // if macd_vec[macd_search_result.unwrap()].macd_value > 0.0 {
|
|
// // // //check duplicate records
|
|
// // // 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(opclo_1m_vec.last().unwrap().close_time.to_string().as_str());
|
|
// // // let exists_condition = Some(exists_condition_build);
|
|
|
|
// // // let inspect_result_1 = exists_record(&inspect_table_name_1, &exists_condition).await;
|
|
// // // let inspect_result_2 = exists_record(&inspect_table_name_2, &exists_condition).await;
|
|
// // // let inspect_result_3 = exists_record(&inspect_table_name_3, &exists_condition).await;
|
|
// // // let inspect_result_4 = exists_record(&inspect_table_name_4, &exists_condition).await;
|
|
|
|
// // // if inspect_result_1 == false && inspect_result_2 == false && inspect_result_3 == false && inspect_result_4 == false {
|
|
// // // let mut sum_stoch_rsi30_1m_k = 0.0;
|
|
// // // for element in &stoch_rsi30_1m_k_vec {
|
|
// // // sum_stoch_rsi30_1m_k += element.stoch_rsi_k_value;
|
|
// // // }
|
|
// // // let average_stoch_rsi30_1m_k = sum_stoch_rsi30_1m_k / 5.0;
|
|
|
|
// // // let ema3_3_result = ema3_1m_vec.binary_search_by_key(&opclo_1m_vec[2].close_time, |&EmaData{ema_value, close_time}|close_time);
|
|
// // // let ema3_2_result = ema3_1m_vec.binary_search_by_key(&opclo_1m_vec[1].close_time, |&EmaData{ema_value, close_time}|close_time);
|
|
// // // let ema3_1_result = ema3_1m_vec.binary_search_by_key(&opclo_1m_vec[0].close_time, |&EmaData{ema_value, close_time}|close_time);
|
|
// // // let ema10_result = ema10_1m_vec.binary_search_by_key(&opclo_1m_vec[2].close_time, |&EmaData{ema_value, close_time}|close_time);
|
|
// // // let sma10_result = sma10_1m_vec.binary_search_by_key(&opclo_1m_vec[2].close_time, |&SmaData{sma_value, close_time}|close_time);
|
|
// // // if ema3_3_result.is_ok() && ema3_2_result.is_ok() && ema3_1_result.is_ok() && ema10_result.is_ok() && sma10_result.is_ok() {
|
|
// // // if sma10_1m_vec[sma10_result.unwrap()].sma_value < ema3_1m_vec[ema3_3_result.unwrap()].ema_value {
|
|
// // // let k_result = stoch_rsi30_1m_k_vec.binary_search_by_key(&opclo_1m_vec[2].close_time, |&StochRsiKData{stoch_rsi_k_value, close_time}|close_time);
|
|
// // // let k_prev_result = stoch_rsi30_1m_k_vec.binary_search_by_key(&opclo_1m_vec[1].close_time, |&StochRsiKData{stoch_rsi_k_value, close_time}|close_time);
|
|
// // // let d_result = stoch_rsi30_1m_d_vec.binary_search_by_key(&opclo_1m_vec[2].close_time, |&StochRsiDData{stoch_rsi_d_value, close_time}|close_time);
|
|
// // // if k_result.is_ok() && k_prev_result.is_ok() {
|
|
// // // if stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value >= stoch_rsi30_1m_k_vec[k_prev_result.unwrap()].stoch_rsi_k_value
|
|
// // // && stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value - stoch_rsi30_1m_k_vec[k_prev_result.unwrap()].stoch_rsi_k_value > 5.0
|
|
// // // && stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value < 80.0
|
|
// // // && stoch_rsi30_1m_d_vec[d_result.unwrap()].stoch_rsi_d_value < 96.0
|
|
// // // && stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value - stoch_rsi30_1m_d_vec[d_result.unwrap()].stoch_rsi_d_value > 5.0 {
|
|
// // // if current_price <= opclo_1m_vec[1].opclo_price * ((((opclo_1m_vec[1].high_price / opclo_1m_vec[1].low_price) - 1.0) / 2.0) + 1.0) {
|
|
// // // // filtered_2nd_symbols.push((symbol, opclo_1m_vec.last().unwrap().close_time));
|
|
// // // }
|
|
// // // }
|
|
// // // }
|
|
// // // }
|
|
|
|
// // // // if ema10_1m_vec[ema10_result.unwrap()].ema_value > sma10_1m_vec[sma10_result.unwrap()].sma_value {
|
|
// // // // if ema3_1m_vec[ema3_3_result.unwrap()].ema_value > ema10_1m_vec[ema10_result.unwrap()].ema_value {
|
|
// // // // if ema3_1m_vec[ema3_3_result.unwrap()].ema_value > ema3_1m_vec[ema3_2_result.unwrap()].ema_value
|
|
// // // // && ema3_1m_vec[ema3_2_result.unwrap()].ema_value > ema3_1m_vec[ema3_1_result.unwrap()].ema_value
|
|
// // // // {
|
|
// // // // if average_stoch_rsi30_1m_k < 80.0 {
|
|
// // // // let k_result = stoch_rsi30_1m_k_vec.binary_search_by_key(&opclo_1m_vec[2].close_time, |&StochRsiKData{stoch_rsi_k_value, close_time}|close_time);
|
|
// // // // let k_prev_result = stoch_rsi30_1m_k_vec.binary_search_by_key(&opclo_1m_vec[1].close_time, |&StochRsiKData{stoch_rsi_k_value, close_time}|close_time);
|
|
// // // // let k_prev2_result = stoch_rsi30_1m_k_vec.binary_search_by_key(&opclo_1m_vec[0].close_time, |&StochRsiKData{stoch_rsi_k_value, close_time}|close_time);
|
|
// // // // let d_result = stoch_rsi30_1m_d_vec.binary_search_by_key(&opclo_1m_vec[2].close_time, |&StochRsiDData{stoch_rsi_d_value, close_time}|close_time);
|
|
// // // // if k_result.is_ok() && d_result.is_ok() && k_prev_result.is_ok() && k_prev2_result.is_ok() {
|
|
// // // // if
|
|
// // // // (stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value > stoch_rsi30_1m_d_vec[d_result.unwrap()].stoch_rsi_d_value)
|
|
// // // // && (stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value - stoch_rsi30_1m_d_vec[d_result.unwrap()].stoch_rsi_d_value) > 3.0
|
|
// // // // && stoch_rsi30_1m_d_vec[d_result.unwrap()].stoch_rsi_d_value < 96.0
|
|
// // // // && (stoch_rsi10_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value > stoch_rsi10_1m_k_vec[k_prev2_result.unwrap()].stoch_rsi_k_value)
|
|
// // // // && (stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value - stoch_rsi30_1m_k_vec[k_prev_result.unwrap()].stoch_rsi_k_value) < 25.0
|
|
// // // // && (stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value - stoch_rsi30_1m_k_vec[k_prev_result.unwrap()].stoch_rsi_k_value) > 3.0
|
|
// // // // // && (stoch_rsi10_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value - stoch_rsi10_1m_d_vec[d_result.unwrap()].stoch_rsi_d_value > 5.0)
|
|
// // // // // (stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value - stoch_rsi30_1m_k_vec[k_prev_result.unwrap()].stoch_rsi_k_value > 5.0) &&
|
|
// // // // // ((stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value > stoch_rsi30_1m_k_vec[k_prev_result.unwrap()].stoch_rsi_k_value && stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value <= 80.0)
|
|
// // // // // || (((opclo_1m_vec[1].open_price - opclo_1m_vec[1].close_price).abs() / (opclo_1m_vec[1].high_price - opclo_1m_vec[1].low_price) > 60.0 && stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value > 80.0) && (stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value > stoch_rsi30_1m_k_vec[k_prev_result.unwrap()].stoch_rsi_k_value)))
|
|
// // // // {
|
|
// // // // // if stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value > 80.0 {
|
|
// // // // // if (opclo_1m_vec[1].open_price - opclo_1m_vec[1].close_price).abs() / (opclo_1m_vec[1].high_price - opclo_1m_vec[1].low_price) > 60.0
|
|
// // // // // {
|
|
// // // // // filtered_2nd_symbols.push((symbol, opclo_1m_vec.last().unwrap().close_time));
|
|
// // // // // }
|
|
// // // // // } else {
|
|
// // // // filtered_2nd_symbols.push((symbol, opclo_1m_vec.last().unwrap().close_time));
|
|
// // // // // }
|
|
// // // // // filtered_2nd_symbols.push((symbol, opclo_1m_vec.last().unwrap().close_time));
|
|
// // // // // if opclo_1m_vec[1].candle_type == "DOWN" && opclo_1m_vec[1].opclo_price >= opclo_1m_vec[2].close_price {
|
|
// // // // // filtered_2nd_symbols.push((symbol, opclo_1m_vec.last().unwrap().close_time));
|
|
// // // // // } else if opclo_1m_vec[1].candle_type == "UP" {
|
|
// // // // // filtered_2nd_symbols.push((symbol, opclo_1m_vec.last().unwrap().close_time));
|
|
// // // // // }
|
|
// // // // }
|
|
// // // // // else {
|
|
// // // // // let result = rsi3_1m_vec.binary_search_by_key(&opclo_1m_vec[1].close_time, |&RsiData{rsi_value, close_time}|close_time);
|
|
// // // // // if result.is_ok() {
|
|
// // // // // if rsi3_1m_vec[result.unwrap()].rsi_value < 20.0 && cnt >= 2 && (stoch_rsi10_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value > stoch_rsi10_1m_d_vec[d_result.unwrap()].stoch_rsi_d_value) {
|
|
// // // // // filtered_2nd_symbols.push((symbol, opclo_1m_vec.last().unwrap().close_time));
|
|
// // // // // }
|
|
// // // // // }
|
|
// // // // // }
|
|
|
|
// // // // // } else {
|
|
// // // // // if cnt >= 2 {
|
|
|
|
// // // // // let result = ema3_1m_vec.binary_search_by_key(&opclo_1m_vec[1].close_time, |&EmaData{ema_value, close_time}|close_time);
|
|
// // // // // match result {
|
|
// // // // // Ok(T) => {
|
|
// // // // // if ema3_1m_vec[T].ema_value > opclo_1m_vec[1].opclo_price {
|
|
// // // // // let result = rsi3_1m_vec.binary_search_by_key(&opclo_1m_vec[1].close_time, |&RsiData{rsi_value, close_time}|close_time);
|
|
// // // // // match result {
|
|
// // // // // Ok(T) => {
|
|
// // // // // if rsi3_1m_vec[T].rsi_value < 15.0 {
|
|
// // // // // let k_result = stoch_rsi10_1m_k_vec.binary_search_by_key(&opclo_1m_vec[1].close_time, |&StochRsiKData{stoch_rsi_k_value, close_time}|close_time);
|
|
// // // // // let d_result = stoch_rsi10_1m_d_vec.binary_search_by_key(&opclo_1m_vec[1].close_time, |&StochRsiDData{stoch_rsi_d_value, close_time}|close_time);
|
|
|
|
// // // // // if k_result.is_ok() && d_result.is_ok() {
|
|
// // // // // if stoch_rsi10_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value <= stoch_rsi10_1m_d_vec[d_result.unwrap()].stoch_rsi_d_value {
|
|
// // // // // if current_price < opclo_1m_vec[1].opclo_price {
|
|
// // // // // filtered_2nd_symbols.push((symbol, opclo_1m_vec.last().unwrap().close_time));
|
|
// // // // // }
|
|
// // // // // }
|
|
// // // // // }
|
|
// // // // // }
|
|
// // // // // },
|
|
// // // // // Err(E) => {}
|
|
// // // // // }
|
|
// // // // // }
|
|
// // // // // },
|
|
// // // // // Err(E) => {}
|
|
// // // // // }
|
|
// // // // // }
|
|
// // // // // }
|
|
// // // // }
|
|
// // // // } else {
|
|
// // // // let k_result = stoch_rsi10_1m_k_vec.binary_search_by_key(&opclo_1m_vec[2].close_time, |&StochRsiKData{stoch_rsi_k_value, close_time}|close_time);
|
|
// // // // let k_prev_result = stoch_rsi10_1m_k_vec.binary_search_by_key(&opclo_1m_vec[1].close_time, |&StochRsiKData{stoch_rsi_k_value, close_time}|close_time);
|
|
// // // // let k_prev2_result = stoch_rsi10_1m_k_vec.binary_search_by_key(&opclo_1m_vec[0].close_time, |&StochRsiKData{stoch_rsi_k_value, close_time}|close_time);
|
|
// // // // let d_result = stoch_rsi10_1m_d_vec.binary_search_by_key(&opclo_1m_vec[2].close_time, |&StochRsiDData{stoch_rsi_d_value, close_time}|close_time);
|
|
// // // // if k_result.is_ok() && d_result.is_ok() && k_prev_result.is_ok() && k_prev2_result.is_ok() {
|
|
// // // // if (stoch_rsi10_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value > stoch_rsi10_1m_d_vec[d_result.unwrap()].stoch_rsi_d_value)
|
|
// // // // && (stoch_rsi10_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value - stoch_rsi10_1m_d_vec[d_result.unwrap()].stoch_rsi_d_value) > 3.0
|
|
// // // // && stoch_rsi10_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value > stoch_rsi10_1m_k_vec[k_prev2_result.unwrap()].stoch_rsi_k_value
|
|
// // // // && stoch_rsi10_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value > stoch_rsi10_1m_k_vec[k_prev_result.unwrap()].stoch_rsi_k_value
|
|
// // // // && stoch_rsi10_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value - stoch_rsi10_1m_k_vec[k_prev_result.unwrap()].stoch_rsi_k_value < 30.0
|
|
// // // // && stoch_rsi10_1m_d_vec[d_result.unwrap()].stoch_rsi_d_value < 95.0
|
|
// // // // {
|
|
// // // // // if stoch_rsi10_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value > 80.0 {
|
|
// // // // // if (opclo_1m_vec[1].open_price - opclo_1m_vec[1].close_price).abs() / (opclo_1m_vec[1].high_price - opclo_1m_vec[1].low_price) > 60.0
|
|
// // // // // {
|
|
// // // // // filtered_2nd_symbols.push((symbol, opclo_1m_vec.last().unwrap().close_time));
|
|
// // // // // }
|
|
// // // // // } else {
|
|
// // // // // filtered_2nd_symbols.push((symbol, opclo_1m_vec.last().unwrap().close_time));
|
|
// // // // // }
|
|
// // // // filtered_2nd_symbols.push((symbol, opclo_1m_vec.last().unwrap().close_time));
|
|
// // // // }
|
|
// // // // }
|
|
// // // // }
|
|
// // // // }
|
|
// // // // }
|
|
// // // // // else {
|
|
// // // // // let k_result = stoch_rsi30_1m_k_vec.binary_search_by_key(&opclo_1m_vec[2].close_time, |&StochRsiKData{stoch_rsi_k_value, close_time}|close_time);
|
|
// // // // // let k_prev_result = stoch_rsi30_1m_k_vec.binary_search_by_key(&opclo_1m_vec[1].close_time, |&StochRsiKData{stoch_rsi_k_value, close_time}|close_time);
|
|
// // // // // let d_result = stoch_rsi30_1m_d_vec.binary_search_by_key(&opclo_1m_vec[2].close_time, |&StochRsiDData{stoch_rsi_d_value, close_time}|close_time);
|
|
// // // // // if k_result.is_ok() && k_prev_result.is_ok() {
|
|
// // // // // if (stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value > stoch_rsi30_1m_k_vec[k_prev_result.unwrap()].stoch_rsi_k_value)
|
|
// // // // // && (stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value - stoch_rsi30_1m_k_vec[k_prev_result.unwrap()].stoch_rsi_k_value) > 5.0
|
|
// // // // // {
|
|
// // // // // filtered_2nd_symbols.push((symbol, opclo_1m_vec.last().unwrap().close_time));
|
|
// // // // // }
|
|
|
|
// // // // // // if ema3_1m_vec[ema3_3_result.unwrap()].ema_value < ema3_1m_vec[ema3_2_result.unwrap()].ema_value {
|
|
// // // // // // if opclo_1m_vec[1].candle_type == "DOWN" && opclo_1m_vec[1].open_price > ema3_1m_vec[ema3_2_result.unwrap()].ema_value
|
|
// // // // // // && opclo_1m_vec[2].open_price < ema3_1m_vec[ema3_3_result.unwrap()].ema_value
|
|
// // // // // // && opclo_1m_vec[2].high_price < ema3_1m_vec[ema3_3_result.unwrap()].ema_value
|
|
// // // // // // && opclo_1m_vec[2].candle_type == "UP" {
|
|
// // // // // // if (stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value < stoch_rsi30_1m_d_vec[d_result.unwrap()].stoch_rsi_d_value)
|
|
// // // // // // {
|
|
// // // // // // filtered_2nd_symbols.push((symbol, opclo_1m_vec.last().unwrap().close_time));
|
|
// // // // // // }
|
|
// // // // // // }
|
|
// // // // // // } else if ema3_1m_vec[ema3_3_result.unwrap()].ema_value > ema3_1m_vec[ema3_2_result.unwrap()].ema_value
|
|
// // // // // // {
|
|
// // // // // // if opclo_1m_vec[1].candle_type == "UP"
|
|
// // // // // // && (stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value > stoch_rsi30_1m_d_vec[d_result.unwrap()].stoch_rsi_d_value) {
|
|
// // // // // // filtered_2nd_symbols.push((symbol, opclo_1m_vec.last().unwrap().close_time));
|
|
// // // // // // }
|
|
// // // // // // }
|
|
// // // // // }
|
|
// // // // // }
|
|
// // // // }
|
|
// // // }
|
|
// // // }
|
|
// // // }
|
|
// // // // else if macd_vec[macd_search_result.unwrap()].macd_value > macd_vec[macd_search_result.unwrap()-1].macd_value && macd_vec[macd_search_result.unwrap()].macd_value > -3.0{
|
|
// // // // let k_result = stoch_rsi30_1m_k_vec.binary_search_by_key(&opclo_1m_vec[2].close_time, |&StochRsiKData{stoch_rsi_k_value, close_time}|close_time);
|
|
// // // // let k_prev_result = stoch_rsi30_1m_k_vec.binary_search_by_key(&opclo_1m_vec[1].close_time, |&StochRsiKData{stoch_rsi_k_value, close_time}|close_time);
|
|
// // // // let d_result = stoch_rsi30_1m_d_vec.binary_search_by_key(&opclo_1m_vec[2].close_time, |&StochRsiDData{stoch_rsi_d_value, close_time}|close_time);
|
|
// // // // if k_result.is_ok() && k_prev_result.is_ok() && d_result.is_ok() {
|
|
// // // // if stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value >= stoch_rsi30_1m_k_vec[k_prev_result.unwrap()].stoch_rsi_k_value
|
|
// // // // && stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value > stoch_rsi30_1m_d_vec[d_result.unwrap()].stoch_rsi_d_value
|
|
// // // // && stoch_rsi30_1m_k_vec[k_result.unwrap()].stoch_rsi_k_value - stoch_rsi30_1m_d_vec[d_result.unwrap()].stoch_rsi_d_value > 5.0{
|
|
// // // // filtered_2nd_symbols.push((symbol, opclo_1m_vec.last().unwrap().close_time));
|
|
// // // // }
|
|
// // // // }
|
|
// // // // }
|
|
// // // }
|
|
|
|
// // }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // let mut filtered_2nd_symbols: Vec<(String, i64)> = Vec::new(); // (symbol, closetime)
|
|
// // if market_cap_index.first().unwrap().negative_buy_signal == 1 || (market_cap_index.first().unwrap().liquidation_signal == 0 && market_cap_index.first().unwrap().market_cap_index <= 20.0 && market_cap_index.first().unwrap().market_cap_index >= 0.0) {
|
|
// // let mut rsi3_1m_vec: Vec<RsiData> = Vec::new();
|
|
// // let mut opclo_1m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// // let mut ema3_1m_vec: Vec<EmaData> = Vec::new();
|
|
// // let mut cnt = 0;
|
|
// // for symbol in filtered_symbols {
|
|
// // let rsi3_1m_option = alldata.rsi3_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// // let opclo_1m_option = alldata.rt_price_1m_vec.iter().position(|x| *x.0 == *symbol);
|
|
// // let ema3_1m_option = alldata.ema3_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
|
|
// // if rsi3_1m_option.is_some() && opclo_1m_option.is_some() && ema3_1m_option.is_some() {
|
|
// // rsi3_1m_vec = alldata.rsi3_1m_data[rsi3_1m_option.unwrap()].1.clone();
|
|
// // opclo_1m_vec = alldata.rt_price_1m_vec[opclo_1m_option.unwrap()].1.clone();
|
|
// // ema3_1m_vec = alldata.ema3_1m_data[ema3_1m_option.unwrap()].1.clone();
|
|
|
|
// // if rsi3_1m_vec.len() >= 3 && opclo_1m_vec.len() >= 3 && ema3_1m_vec.len() >= 3 {
|
|
// // opclo_1m_vec.reverse();
|
|
// // opclo_1m_vec.truncate(3);
|
|
// // opclo_1m_vec.reverse();
|
|
|
|
// // if opclo_1m_vec.last().unwrap().candle_type == "UP" {
|
|
// // cnt = 0;
|
|
// // for element in &opclo_1m_vec {
|
|
// // if element.candle_type == "DOWN" {
|
|
// // cnt += 1;
|
|
// // }
|
|
// // }
|
|
|
|
// // if cnt >= 2 {
|
|
// // let result = ema3_1m_vec.binary_search_by_key(&opclo_1m_vec[1].close_time, |&EmaData{ema_value, close_time}|close_time);
|
|
// // match result {
|
|
// // Ok(T) => {
|
|
// // if ema3_1m_vec[T].ema_value > opclo_1m_vec[1].opclo_price {
|
|
// // let result = rsi3_1m_vec.binary_search_by_key(&opclo_1m_vec[1].close_time, |&RsiData{rsi_value, close_time}|close_time);
|
|
// // match result {
|
|
// // Ok(T) => {
|
|
// // if rsi3_1m_vec[T].rsi_value < 30.0 {
|
|
// // if current_price < opclo_1m_vec[1].opclo_price {
|
|
// // filtered_2nd_symbols.push((symbol, opclo_1m_vec.last().unwrap().close_time));
|
|
// // }
|
|
// // }
|
|
// // },
|
|
// // Err(E) => {}
|
|
// // }
|
|
// // }
|
|
// // },
|
|
// // Err(E) => {}
|
|
// // }
|
|
// // }
|
|
|
|
// // }
|
|
|
|
// // }
|
|
// // }
|
|
// // }
|
|
// // } else if market_cap_index.first().unwrap().liquidation_signal == 1 && market_cap_index.first().unwrap().market_cap_index < - 10.0 {
|
|
// // let mut rsi3_1m_vec: Vec<RsiData> = Vec::new();
|
|
// // let mut rsi10_1m_vec: Vec<RsiData> = Vec::new();
|
|
// // let mut rsi30_1m_vec: Vec<RsiData> = Vec::new();
|
|
// // let mut op_low_1m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// // let mut ema3_1m_vec: Vec<EmaData> = Vec::new();
|
|
// // let mut bb30_1m_vec: Vec<BollingerBandData> = Vec::new();
|
|
// // let mut cnt = 0;
|
|
// // for symbol in filtered_symbols {
|
|
// // let rsi3_1m_option = alldata.rsi3_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// // let rsi10_1m_option = alldata.rsi10_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// // let rsi30_1m_option = alldata.rsi30_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// // let op_low_1m_option = alldata.rt_price_1m_vec.iter().position(|x| *x.0 == *symbol);
|
|
// // let ema3_1m_option = alldata.ema3_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// // let bb30_1m_option = alldata.bb30_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
|
|
// // if rsi3_1m_option.is_some() && rsi10_1m_option.is_some() && rsi30_1m_option.is_some() && op_low_1m_option.is_some() && ema3_1m_option.is_some() && bb30_1m_option.is_some() {
|
|
// // rsi3_1m_vec = alldata.rsi3_1m_data[rsi3_1m_option.unwrap()].1.clone();
|
|
// // rsi10_1m_vec = alldata.rsi10_1m_data[rsi10_1m_option.unwrap()].1.clone();
|
|
// // rsi30_1m_vec = alldata.rsi30_1m_data[rsi30_1m_option.unwrap()].1.clone();
|
|
// // op_low_1m_vec = alldata.rt_price_1m_vec[op_low_1m_option.unwrap()].1.clone();
|
|
// // ema3_1m_vec = alldata.ema3_1m_data[ema3_1m_option.unwrap()].1.clone();
|
|
// // bb30_1m_vec = alldata.bb30_1m_data[bb30_1m_option.unwrap()].1.clone();
|
|
|
|
// // if rsi3_1m_vec.len() >= 3 && rsi10_1m_vec.len() >= 3 && rsi30_1m_vec.len() >= 3 && op_low_1m_vec.len() >= 3 && ema3_1m_vec.len() >= 3 && bb30_1m_vec.len() >= 3 {
|
|
// // op_low_1m_vec.reverse();
|
|
// // op_low_1m_vec.truncate(5);
|
|
// // op_low_1m_vec.reverse();
|
|
|
|
// // if op_low_1m_vec.last().unwrap().candle_type == "DOWN" {
|
|
// // cnt = 0;
|
|
// // for element in &op_low_1m_vec {
|
|
// // if element.candle_type == "DOWN" {
|
|
// // cnt += 1;
|
|
// // }
|
|
// // }
|
|
|
|
// // if cnt >= 4 {
|
|
// // let result = ema3_1m_vec.binary_search_by_key(&op_low_1m_vec.last().unwrap().close_time, |&EmaData{ema_value, close_time}|close_time);
|
|
// // match result {
|
|
// // Ok(T) => {
|
|
// // if ema3_1m_vec[T].ema_value > (op_low_1m_vec.last().unwrap().open_price + op_low_1m_vec.last().unwrap().low_price) / 2.0 {
|
|
// // let result = rsi3_1m_vec.binary_search_by_key(&op_low_1m_vec.last().unwrap().close_time, |&RsiData{rsi_value, close_time}|close_time);
|
|
// // match result {
|
|
// // Ok(T) => {
|
|
// // if rsi3_1m_vec[T].rsi_value < 10.0 {
|
|
// // let result = rsi10_1m_vec.binary_search_by_key(&op_low_1m_vec.last().unwrap().close_time, |&RsiData{rsi_value, close_time}|close_time);
|
|
// // match result {
|
|
// // Ok(T) => {
|
|
// // if rsi10_1m_vec[T].rsi_value < 15.0 {
|
|
// // let result = rsi30_1m_vec.binary_search_by_key(&op_low_1m_vec.last().unwrap().close_time, |&RsiData{rsi_value, close_time}|close_time);
|
|
// // match result {
|
|
// // Ok(T) => {
|
|
// // if rsi30_1m_vec[T].rsi_value < 35.0 {
|
|
// // let result = bb30_1m_vec.binary_search_by_key(&op_low_1m_vec.first().unwrap().close_time, |&BollingerBandData{sma, upperband, lowerband, close_time}|close_time);
|
|
// // match result {
|
|
// // Ok(T) => {
|
|
// // if bb30_1m_vec[T].lowerband > (op_low_1m_vec.last().unwrap().open_price + op_low_1m_vec.last().unwrap().low_price) / 2.0 {
|
|
// // filtered_2nd_symbols.push((symbol, op_low_1m_vec.last().unwrap().close_time));
|
|
// // }
|
|
// // },
|
|
// // Err(E) => {},
|
|
// // }
|
|
// // }
|
|
// // },
|
|
// // Err(E) => {}
|
|
// // }
|
|
// // }
|
|
// // },
|
|
// // Err(E) => {}
|
|
// // }
|
|
// // }
|
|
// // },
|
|
// // Err(E) => {}
|
|
// // }
|
|
// // }
|
|
// // },
|
|
// // Err(E) => {}
|
|
// // }
|
|
// // }
|
|
|
|
// // }
|
|
|
|
// // }
|
|
// // }
|
|
// // }
|
|
// // }
|
|
|
|
// insert_pre_suggested_coins(1, &filtered_2nd_symbols, alldata).await;
|
|
|
|
// Ok(())
|
|
// }
|
|
|
|
// Supertrend UP area에서 이득보기
|
|
// pub async fn execute_strategist_for_test2(
|
|
// alldata: &AllData,
|
|
// ) -> Result<(), 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 market_cap_index = select_marketcap().await;
|
|
|
|
// let mut filtered_symbols: Vec<String> = Vec::new();
|
|
|
|
// filtered_symbols.push(String::from("BTCUSDT"));
|
|
|
|
// let current_price = get_current_price(&filtered_symbols.first().unwrap(), &alldata.price_vec)
|
|
// .await
|
|
// .unwrap();
|
|
|
|
// let mut filtered_2nd_symbols: Vec<(String, i64)> = Vec::new(); // (symbol, closetime)
|
|
// let mut ema3_1m_vec: &Vec<EmaData> = &Vec::new();
|
|
// let mut ema3_30m_vec: &Vec<EmaData> = &Vec::new();
|
|
// let mut ema10_1m_vec: &Vec<EmaData> = &Vec::new();
|
|
// let mut ema30_1m_vec: &Vec<EmaData> = &Vec::new();
|
|
// let mut sma3_1m_vec: &Vec<SmaData> = &Vec::new();
|
|
// let mut sma10_1m_vec: &Vec<SmaData> = &Vec::new();
|
|
// let mut sma3_30m_vec: &Vec<SmaData> = &Vec::new();
|
|
// let mut sma30_1m_vec: &Vec<SmaData> = &Vec::new();
|
|
// let mut rsi3_1m_vec: &Vec<RsiData> = &Vec::new();
|
|
// let mut rsi30_1m_vec: &Vec<RsiData> = &Vec::new();
|
|
// let mut stoch_rsi3_1m_k_vec: &Vec<StochRsiKData> = &Vec::new();
|
|
// let mut stoch_rsi3_1m_d_vec: &Vec<StochRsiDData> = &Vec::new();
|
|
// let mut stoch_rsi30_1m_k_vec: &Vec<StochRsiKData> = &Vec::new();
|
|
// let mut stoch_rsi30_1m_d_vec: &Vec<StochRsiDData> = &Vec::new();
|
|
// let mut rt_price_1m_vec: &Vec<RealtimePriceData> = &Vec::new();
|
|
// let mut is_filtering_passed: bool = false;
|
|
|
|
// let mut cnt = 0;
|
|
// let exists_condition = Some(String::from("used_usdt >= 10.0 AND registerer = 2"));
|
|
// let inspect_result_1 = exists_record(&inspect_table_name_1, &exists_condition).await;
|
|
// let inspect_result_2 = exists_record(&inspect_table_name_2, &exists_condition).await;
|
|
// let inspect_result_4 = exists_record(&inspect_table_name_4, &None).await;
|
|
// let mut is_buy_period_30m = false;
|
|
|
|
// if inspect_result_1 == false && inspect_result_2 == false && inspect_result_4 == false {
|
|
// for symbol in filtered_symbols {
|
|
// is_filtering_passed = false;
|
|
// let ema3_1m_option = alldata.ema3_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let ema3_30m_option = alldata.ema3_30m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let ema10_1m_option = alldata.ema10_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let ema30_1m_option = alldata.ema30_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let sma3_1m_option = alldata.sma3_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let sma10_1m_option = alldata.sma10_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let sma3_30m_option = alldata.sma3_30m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let sma30_1m_option = alldata.sma30_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let rsi3_1m_option = alldata.rsi3_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let rsi30_1m_option = alldata.rsi30_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let stoch_rsi3_1m_k_option = alldata
|
|
// .stoch_rsi3_1m_3_k_data
|
|
// .iter()
|
|
// .position(|x| *x.0 == *symbol);
|
|
// let stoch_rsi3_1m_d_option = alldata
|
|
// .stoch_rsi3_1m_3_d_data
|
|
// .iter()
|
|
// .position(|x| *x.0 == *symbol);
|
|
// let stoch_rsi30_1m_k_option = alldata
|
|
// .stoch_rsi30_1m_30_k_data
|
|
// .iter()
|
|
// .position(|x| *x.0 == *symbol);
|
|
// let stoch_rsi30_1m_d_option = alldata
|
|
// .stoch_rsi30_1m_30_d_data
|
|
// .iter()
|
|
// .position(|x| *x.0 == *symbol);
|
|
// let rt_price_1m_option = alldata.rt_price_1m_vec.iter().position(|x| *x.0 == *symbol);
|
|
|
|
// if ema3_1m_option.is_some()
|
|
// && ema3_30m_option.is_some()
|
|
// && ema10_1m_option.is_some()
|
|
// && ema30_1m_option.is_some()
|
|
// && sma3_1m_option.is_some()
|
|
// && sma10_1m_option.is_some()
|
|
// && sma3_30m_option.is_some()
|
|
// && sma30_1m_option.is_some()
|
|
// && rsi3_1m_option.is_some()
|
|
// && rsi30_1m_option.is_some()
|
|
// && stoch_rsi3_1m_k_option.is_some()
|
|
// && stoch_rsi3_1m_d_option.is_some()
|
|
// && stoch_rsi30_1m_k_option.is_some()
|
|
// && stoch_rsi30_1m_d_option.is_some()
|
|
// && rt_price_1m_option.is_some()
|
|
// {
|
|
// ema3_1m_vec = &alldata.ema3_1m_data[ema3_1m_option.unwrap()].1;
|
|
// ema3_30m_vec = &alldata.ema3_30m_data[ema3_30m_option.unwrap()].1;
|
|
// ema10_1m_vec = &alldata.ema10_1m_data[ema10_1m_option.unwrap()].1;
|
|
// ema30_1m_vec = &alldata.ema30_1m_data[ema30_1m_option.unwrap()].1;
|
|
// sma3_1m_vec = &alldata.sma3_1m_data[sma3_1m_option.unwrap()].1;
|
|
// sma10_1m_vec = &alldata.sma10_1m_data[sma10_1m_option.unwrap()].1;
|
|
// sma3_30m_vec = &alldata.sma3_30m_data[sma3_30m_option.unwrap()].1;
|
|
// sma30_1m_vec = &alldata.sma30_1m_data[sma30_1m_option.unwrap()].1;
|
|
// rsi3_1m_vec = &alldata.rsi3_1m_data[rsi3_1m_option.unwrap()].1;
|
|
// rsi30_1m_vec = &alldata.rsi30_1m_data[rsi30_1m_option.unwrap()].1;
|
|
// stoch_rsi3_1m_k_vec =
|
|
// &alldata.stoch_rsi3_1m_3_k_data[stoch_rsi3_1m_k_option.unwrap()].1;
|
|
// stoch_rsi3_1m_d_vec =
|
|
// &alldata.stoch_rsi3_1m_3_d_data[stoch_rsi3_1m_d_option.unwrap()].1;
|
|
// stoch_rsi30_1m_k_vec =
|
|
// &alldata.stoch_rsi30_1m_30_k_data[stoch_rsi30_1m_k_option.unwrap()].1;
|
|
// stoch_rsi30_1m_d_vec =
|
|
// &alldata.stoch_rsi30_1m_30_d_data[stoch_rsi30_1m_d_option.unwrap()].1;
|
|
// rt_price_1m_vec = &alldata.rt_price_1m_vec[rt_price_1m_option.unwrap()].1;
|
|
|
|
// // filtering condition: data are ready
|
|
// if ema3_1m_vec.len() >= 3
|
|
// && ema3_30m_vec.len() >= 3
|
|
// && ema10_1m_vec.len() >= 3
|
|
// && ema30_1m_vec.len() >= 3
|
|
// && sma3_1m_vec.len() >= 3
|
|
// && sma10_1m_vec.len() >= 3
|
|
// && sma3_30m_vec.len() >= 3
|
|
// && sma30_1m_vec.len() >= 3
|
|
// && rsi3_1m_vec.len() >= 3
|
|
// && rsi30_1m_vec.len() >= 3
|
|
// && stoch_rsi3_1m_k_vec.len() >= 5
|
|
// && stoch_rsi3_1m_d_vec.len() >= 5
|
|
// && stoch_rsi30_1m_k_vec.len() >= 5
|
|
// && stoch_rsi30_1m_d_vec.len() >= 5
|
|
// && rt_price_1m_vec.len() >= 50
|
|
// {
|
|
// is_filtering_passed = true;
|
|
// }
|
|
|
|
// // // filtering condition: SuperTrend & EMA & SMA
|
|
// // if is_filtering_passed == true {
|
|
// // let supertrend_option = supertrend(&symbol, &alldata.rt_price_1m_vec, 10, 1.0, false).await;
|
|
// // if supertrend_option.is_some() {
|
|
// // let supertrend_vec = supertrend_option.unwrap();
|
|
// // let supertrend_result = supertrend_vec.binary_search_by_key(&rt_price_1m_vec.last().unwrap().close_time, |SupertrendData{band_value, signal, area, close_time}| *close_time);
|
|
// // let ema3_result = ema3_1m_vec.binary_search_by_key(&rt_price_1m_vec.last().unwrap().close_time, |&EmaData{ema_value, close_time}|close_time);
|
|
// // let sma10_result = sma10_1m_vec.binary_search_by_key(&rt_price_1m_vec.last().unwrap().close_time, |&SmaData{sma_value, close_time}|close_time);
|
|
|
|
// // if supertrend_vec.last().unwrap().signal.is_some() && ema3_result.is_ok() && sma10_result.is_ok() {
|
|
// // if (((supertrend_vec.last().unwrap().signal.as_ref().unwrap().contains("BUY") && ema3_1m_vec[ema3_result.unwrap()].ema_value > sma10_1m_vec[sma10_result.unwrap()].sma_value) && rt_price_1m_vec.last().unwrap().close_price <= supertrend_vec[supertrend_vec.len()-2].band_value * 1.0005)
|
|
// // || (supertrend_vec.last().unwrap().area.contains("UP") && ema3_1m_vec[ema3_result.unwrap()-1].ema_value < sma10_1m_vec[sma10_result.unwrap()-1].sma_value && ema3_1m_vec[ema3_result.unwrap()].ema_value > sma10_1m_vec[sma10_result.unwrap()].sma_value))
|
|
// // && sma10_1m_vec[sma10_result.unwrap()-2].sma_value < sma10_1m_vec[sma10_result.unwrap()].sma_value {
|
|
// // is_filtering_passed = true;
|
|
// // } else { is_filtering_passed = false; }
|
|
// // } else { is_filtering_passed = false; }
|
|
// // } else { is_filtering_passed = false; }
|
|
// // }
|
|
|
|
// // filtering condition: SuperTrend
|
|
// if is_filtering_passed == true {
|
|
// let supertrend_option =
|
|
// supertrend(&symbol, &alldata.rt_price_1m_vec, 3, 1.0, false).await;
|
|
// if supertrend_option.is_some() {
|
|
// let supertrend_vec = supertrend_option.unwrap();
|
|
// let supertrend_result = supertrend_vec.binary_search_by_key(
|
|
// &rt_price_1m_vec.last().unwrap().close_time,
|
|
// |SupertrendData {
|
|
// band_value,
|
|
// signal,
|
|
// area,
|
|
// close_time,
|
|
// }| *close_time,
|
|
// );
|
|
|
|
// if supertrend_result.is_ok() {
|
|
// if supertrend_vec[supertrend_result.unwrap()]
|
|
// .signal
|
|
// .as_ref()
|
|
// .is_some()
|
|
// {
|
|
// if supertrend_vec[supertrend_result.unwrap()]
|
|
// .signal
|
|
// .as_ref()
|
|
// .unwrap()
|
|
// .contains("BUY")
|
|
// {
|
|
// is_filtering_passed = true;
|
|
// } else {
|
|
// is_filtering_passed = false;
|
|
// }
|
|
// } else {
|
|
// is_filtering_passed = false;
|
|
// }
|
|
// } else {
|
|
// is_filtering_passed = false;
|
|
// }
|
|
// } else {
|
|
// is_filtering_passed = false;
|
|
// }
|
|
// }
|
|
|
|
// // filtering condition: SMA & EMA
|
|
// if is_filtering_passed == true {
|
|
// let sma3_1m_result = sma3_1m_vec.binary_search_by_key(
|
|
// &rt_price_1m_vec.last().unwrap().close_time,
|
|
// |&SmaData {
|
|
// sma_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// let sma10_1m_result = sma10_1m_vec.binary_search_by_key(
|
|
// &rt_price_1m_vec.last().unwrap().close_time,
|
|
// |&SmaData {
|
|
// sma_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// let sma30_1m_result = sma30_1m_vec.binary_search_by_key(
|
|
// &rt_price_1m_vec.last().unwrap().close_time,
|
|
// |&SmaData {
|
|
// sma_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// let ema3_1m_result = ema3_1m_vec.binary_search_by_key(
|
|
// &rt_price_1m_vec.last().unwrap().close_time,
|
|
// |&EmaData {
|
|
// ema_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// let ema3_30m_result = ema3_30m_vec.binary_search_by_key(
|
|
// &sma3_30m_vec.last().unwrap().close_time,
|
|
// |&EmaData {
|
|
// ema_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// let ema10_1m_result = ema10_1m_vec.binary_search_by_key(
|
|
// &rt_price_1m_vec.last().unwrap().close_time,
|
|
// |&EmaData {
|
|
// ema_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// let ema30_1m_result = ema30_1m_vec.binary_search_by_key(
|
|
// &rt_price_1m_vec.last().unwrap().close_time,
|
|
// |&EmaData {
|
|
// ema_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// if sma10_1m_result.is_ok()
|
|
// && sma30_1m_result.is_ok()
|
|
// && ema3_1m_result.is_ok()
|
|
// && ema10_1m_result.is_ok()
|
|
// && ema30_1m_result.is_ok()
|
|
// && ema3_30m_result.is_ok()
|
|
// {
|
|
// if sma3_1m_vec[sma3_1m_result.unwrap()].sma_value
|
|
// > sma3_1m_vec[sma3_1m_result.unwrap() - 1].sma_value
|
|
// && sma3_1m_vec[sma3_1m_result.unwrap()].sma_value
|
|
// > sma3_1m_vec[sma3_1m_result.unwrap() - 2].sma_value
|
|
// && sma3_1m_vec[sma3_1m_result.unwrap() - 1].sma_value
|
|
// > sma3_1m_vec[sma3_1m_result.unwrap() - 2].sma_value
|
|
// && sma30_1m_vec[sma30_1m_result.unwrap()].sma_value
|
|
// > rt_price_1m_vec.last().unwrap().close_price
|
|
// && sma30_1m_vec[sma30_1m_result.unwrap() - 1].sma_value
|
|
// > rt_price_1m_vec[rt_price_1m_vec.len() - 2].close_price
|
|
// && sma30_1m_vec[sma30_1m_result.unwrap() - 2].sma_value
|
|
// > rt_price_1m_vec[rt_price_1m_vec.len() - 3].close_price
|
|
// && sma30_1m_vec[sma30_1m_result.unwrap() - 3].sma_value
|
|
// > rt_price_1m_vec[rt_price_1m_vec.len() - 4].close_price
|
|
// && sma30_1m_vec[sma30_1m_result.unwrap() - 4].sma_value
|
|
// > rt_price_1m_vec[rt_price_1m_vec.len() - 5].close_price
|
|
// && sma30_1m_vec[sma30_1m_result.unwrap() - 5].sma_value
|
|
// > rt_price_1m_vec[rt_price_1m_vec.len() - 6].close_price
|
|
// && sma30_1m_vec[sma30_1m_result.unwrap() - 6].sma_value
|
|
// > rt_price_1m_vec[rt_price_1m_vec.len() - 7].close_price
|
|
// && sma30_1m_vec[sma30_1m_result.unwrap() - 7].sma_value
|
|
// > rt_price_1m_vec[rt_price_1m_vec.len() - 8].close_price
|
|
// && sma30_1m_vec[sma30_1m_result.unwrap() - 8].sma_value
|
|
// > rt_price_1m_vec[rt_price_1m_vec.len() - 9].close_price
|
|
// && sma30_1m_vec[sma30_1m_result.unwrap() - 9].sma_value
|
|
// > rt_price_1m_vec[rt_price_1m_vec.len() - 10].close_price
|
|
// // ema10_1m_vec[ema10_1m_result.unwrap()].ema_value > sma10_1m_vec[sma10_1m_result.unwrap()].sma_value
|
|
// // ema10_1m_vec[ema10_1m_result.unwrap()-1].ema_value <= sma10_1m_vec[sma10_1m_result.unwrap()-1].sma_value
|
|
// // (sma10_1m_vec[sma10_1m_result.unwrap()].sma_value - ema10_1m_vec[ema10_1m_result.unwrap()].ema_value).abs() >= (sma10_1m_vec[sma10_1m_result.unwrap()-1].sma_value - ema10_1m_vec[ema10_1m_result.unwrap()-1].ema_value).abs()
|
|
|
|
// // && ema10_1m_vec[ema10_1m_result.unwrap()-1].ema_value < ema10_1m_vec[ema10_1m_result.unwrap()].ema_value
|
|
// // && ema10_1m_vec[ema10_1m_result.unwrap()-2].ema_value < ema10_1m_vec[ema10_1m_result.unwrap()-1].ema_value
|
|
|
|
// // && sma10_1m_vec[sma10_1m_result.unwrap()].sma_value > ema30_1m_vec[ema30_1m_result.unwrap()].ema_value
|
|
// // && ema30_1m_vec[ema30_1m_result.unwrap()-1].ema_value < ema30_1m_vec[ema30_1m_result.unwrap()].ema_value
|
|
// // && ema30_1m_vec[ema30_1m_result.unwrap()-2].ema_value < ema30_1m_vec[ema30_1m_result.unwrap()].ema_value
|
|
// // && ema30_1m_vec[ema30_1m_result.unwrap()-3].ema_value < ema30_1m_vec[ema30_1m_result.unwrap()].ema_value
|
|
// // && ema30_1m_vec[ema30_1m_result.unwrap()-4].ema_value < ema30_1m_vec[ema30_1m_result.unwrap()].ema_value
|
|
// // && ema30_1m_vec[ema30_1m_result.unwrap()-5].ema_value < ema30_1m_vec[ema30_1m_result.unwrap()].ema_value
|
|
// // && ema30_1m_vec[ema30_1m_result.unwrap()-2].ema_value < ema30_1m_vec[ema30_1m_result.unwrap()-1].ema_value
|
|
// // && ema30_1m_vec[ema30_1m_result.unwrap()-3].ema_value < ema30_1m_vec[ema30_1m_result.unwrap()-2].ema_value
|
|
// // && ema30_1m_vec[ema30_1m_result.unwrap()-4].ema_value < ema30_1m_vec[ema30_1m_result.unwrap()-3].ema_value
|
|
// // && ema30_1m_vec[ema30_1m_result.unwrap()-5].ema_value < ema30_1m_vec[ema30_1m_result.unwrap()-4].ema_value
|
|
// // && ema30_1m_vec[ema30_1m_result.unwrap()-5].ema_value < ema30_1m_vec[ema30_1m_result.unwrap()].ema_value
|
|
// // && rt_price_1m_vec.last().unwrap().close_price > ema30_1m_vec[ema30_1m_result.unwrap()].ema_value
|
|
// {
|
|
// is_filtering_passed = true;
|
|
// } else {
|
|
// is_filtering_passed = false;
|
|
// }
|
|
// } else {
|
|
// is_filtering_passed = false;
|
|
// }
|
|
// }
|
|
|
|
// // filtering condition: current price limitation
|
|
// // if is_filtering_passed == true {
|
|
// // if rt_price_1m_vec[rt_price_1m_vec.len()-2].close_price + ((rt_price_1m_vec[rt_price_1m_vec.len()-2].high_price - rt_price_1m_vec[rt_price_1m_vec.len()-2].low_price) * 0.5) > rt_price_1m_vec.last().unwrap().close_price {
|
|
// // is_filtering_passed = true;
|
|
// // } else { is_filtering_passed = false; }
|
|
// // }
|
|
|
|
// // filtering condition: Heatmap Volume
|
|
// if is_filtering_passed == true {
|
|
// let heatmap_volume_option = heatmap_volume(
|
|
// &symbol,
|
|
// &alldata.rt_price_1m_vec,
|
|
// 30,
|
|
// 30,
|
|
// 4.0,
|
|
// 2.5,
|
|
// 1.0,
|
|
// -0.5,
|
|
// )
|
|
// .await;
|
|
// if heatmap_volume_option.is_some() {
|
|
// let heatmap_volume_vec = heatmap_volume_option.unwrap();
|
|
// let heatmap_search_result = heatmap_volume_vec.binary_search_by_key(
|
|
// &rt_price_1m_vec.last().unwrap().close_time,
|
|
// |HeatmapVolumeData {
|
|
// heatmap_value,
|
|
// heatmap_level,
|
|
// close_time,
|
|
// }| *close_time,
|
|
// );
|
|
// if heatmap_search_result.is_ok() {
|
|
// let heatmap_volume_trunc_vec_option = heatmap_volume_vec.get(
|
|
// heatmap_search_result.unwrap() - 11
|
|
// ..heatmap_search_result.unwrap() - 1,
|
|
// );
|
|
// if heatmap_volume_trunc_vec_option.is_some() {
|
|
// let heatmap_volume_trunc_vec =
|
|
// heatmap_volume_trunc_vec_option.unwrap();
|
|
// let mut heat_value_summation = 0.0;
|
|
// for element in heatmap_volume_trunc_vec {
|
|
// if element.heatmap_level == HeatMapLevel::ExtraHigh {
|
|
// heat_value_summation += 2.0;
|
|
// } else if element.heatmap_level == HeatMapLevel::High {
|
|
// heat_value_summation += 1.5;
|
|
// } else if element.heatmap_level == HeatMapLevel::Medium {
|
|
// heat_value_summation += 1.0;
|
|
// } else if element.heatmap_level == HeatMapLevel::Normal {
|
|
// heat_value_summation += 0.5;
|
|
// } else {
|
|
// heat_value_summation += 0.0;
|
|
// }
|
|
// }
|
|
// if heat_value_summation >= 1.5 {
|
|
// is_filtering_passed = true;
|
|
// } else {
|
|
// is_filtering_passed = false;
|
|
// }
|
|
// }
|
|
// }
|
|
// } else {
|
|
// is_filtering_passed = false;
|
|
// }
|
|
// }
|
|
|
|
// // filtering condition: Stoch RSI
|
|
// // if is_filtering_passed == true {
|
|
// // // let sample_length: usize = 5;
|
|
// // // stoch_rsi10_1m_k_vec.reverse();
|
|
// // // stoch_rsi10_1m_k_vec.truncate(5);
|
|
// // // stoch_rsi10_1m_k_vec.reverse();
|
|
// // // stoch_rsi10_1m_d_vec.reverse();
|
|
// // // stoch_rsi10_1m_d_vec.truncate(5);
|
|
// // // stoch_rsi10_1m_d_vec.reverse();
|
|
// // let rsi3_k_result = stoch_rsi3_1m_k_vec.binary_search_by_key(&rt_price_1m_vec.last().unwrap().close_time, |&StochRsiKData{stoch_rsi_k_value, close_time}|close_time);
|
|
// // let rsi3_d_result = stoch_rsi3_1m_d_vec.binary_search_by_key(&rt_price_1m_vec.last().unwrap().close_time, |&StochRsiDData{stoch_rsi_d_value, close_time}|close_time);
|
|
// // let rsi30_k_result = stoch_rsi30_1m_k_vec.binary_search_by_key(&rt_price_1m_vec.last().unwrap().close_time, |&StochRsiKData{stoch_rsi_k_value, close_time}|close_time);
|
|
// // let rsi30_d_result = stoch_rsi30_1m_d_vec.binary_search_by_key(&rt_price_1m_vec.last().unwrap().close_time, |&StochRsiDData{stoch_rsi_d_value, close_time}|close_time);
|
|
// // if rsi30_k_result.is_ok() && rsi30_d_result.is_ok() && rsi3_k_result.is_ok() && rsi3_d_result.is_ok() {
|
|
// // if
|
|
// // // stoch_rsi3_1m_k_vec[rsi3_k_result.unwrap()].stoch_rsi_k_value <= 80.0 || stoch_rsi30_1m_k_vec[rsi30_k_result.unwrap()].stoch_rsi_k_value <= 80.0
|
|
// // // (stoch_rsi3_1m_k_vec[rsi3_k_result.unwrap()].stoch_rsi_k_value >= stoch_rsi3_1m_k_vec[rsi3_k_result.unwrap()-1].stoch_rsi_k_value && stoch_rsi3_1m_k_vec[rsi3_k_result.unwrap()].stoch_rsi_k_value >= stoch_rsi3_1m_d_vec[rsi3_d_result.unwrap()].stoch_rsi_d_value)
|
|
// // (stoch_rsi30_1m_k_vec[rsi30_k_result.unwrap()].stoch_rsi_k_value >= stoch_rsi30_1m_k_vec[rsi30_k_result.unwrap()-1].stoch_rsi_k_value
|
|
// // && stoch_rsi30_1m_k_vec[rsi30_k_result.unwrap()].stoch_rsi_k_value >= stoch_rsi30_1m_d_vec[rsi30_d_result.unwrap()].stoch_rsi_d_value
|
|
// // && stoch_rsi30_1m_k_vec[rsi30_k_result.unwrap()].stoch_rsi_k_value < 80.0)
|
|
|
|
// // // (stoch_rsi30_1m_k_vec[rsi30_k_result.unwrap()].stoch_rsi_k_value >= stoch_rsi30_1m_d_vec[rsi30_d_result.unwrap()].stoch_rsi_d_value
|
|
// // // && stoch_rsi30_1m_d_vec[rsi30_d_result.unwrap()].stoch_rsi_d_value > stoch_rsi30_1m_d_vec[rsi30_d_result.unwrap()-1].stoch_rsi_d_value
|
|
// // // && stoch_rsi30_1m_k_vec[rsi30_k_result.unwrap()].stoch_rsi_k_value < 80.0)
|
|
// // // ||
|
|
// // || (stoch_rsi3_1m_k_vec[rsi3_k_result.unwrap()-1].stoch_rsi_k_value <= 60.0
|
|
// // && stoch_rsi3_1m_k_vec[rsi3_k_result.unwrap()-2].stoch_rsi_k_value >= stoch_rsi3_1m_k_vec[rsi3_k_result.unwrap()-1].stoch_rsi_k_value
|
|
// // && stoch_rsi3_1m_k_vec[rsi3_k_result.unwrap()-1].stoch_rsi_k_value <= stoch_rsi3_1m_d_vec[rsi3_d_result.unwrap()-1].stoch_rsi_d_value
|
|
// // && stoch_rsi30_1m_k_vec[rsi30_k_result.unwrap()-1].stoch_rsi_k_value <= stoch_rsi30_1m_d_vec[rsi30_d_result.unwrap()-1].stoch_rsi_d_value)
|
|
// // // // && stoch_rsi30_1m_k_vec[rsi30_k_result.unwrap()].stoch_rsi_k_value < 80.0)
|
|
// // // || (stoch_rsi3_1m_k_vec[rsi3_k_result.unwrap()].stoch_rsi_k_value == 100.0
|
|
// // // && stoch_rsi3_1m_k_vec[rsi3_k_result.unwrap()].stoch_rsi_k_value == 100.0
|
|
// // // && stoch_rsi30_1m_k_vec[rsi30_k_result.unwrap()].stoch_rsi_k_value >= stoch_rsi30_1m_d_vec[rsi30_d_result.unwrap()].stoch_rsi_d_value
|
|
// // // && stoch_rsi30_1m_k_vec[rsi30_k_result.unwrap()].stoch_rsi_k_value < 80.0)
|
|
// // {
|
|
// // is_filtering_passed = true;
|
|
// // } else { is_filtering_passed = false; }
|
|
// // } else { is_filtering_passed = false; }
|
|
// // }
|
|
|
|
// // // filtering condition: MACD
|
|
// // if is_filtering_passed == true {
|
|
// // let macd_vec = ema_macd(&ema3_1m_vec, &ema10_1m_vec, 10).await?;
|
|
// // let macd_search_result = macd_vec.binary_search_by_key(&rt_price_1m_vec.last().unwrap().close_time, |&EmaMacd{macd_value, close_time}|close_time);
|
|
|
|
// // if macd_search_result.is_ok() {
|
|
// // if macd_vec[macd_search_result.unwrap()].macd_value > macd_vec[macd_search_result.unwrap()-1].macd_value {
|
|
// // is_filtering_passed = true;
|
|
// // } else { is_filtering_passed = false; }
|
|
// // } else { is_filtering_passed = false; }
|
|
// // }
|
|
|
|
// // filtering condition: Ratio between amplitude and body of candles
|
|
// if is_filtering_passed == true {
|
|
// let sample_length: usize = 5; // 5 candle samsples
|
|
// let rt_price_1m_partial_vec_option = rt_price_1m_vec
|
|
// .get(rt_price_1m_vec.len() - sample_length - 1..rt_price_1m_vec.len() - 1);
|
|
// if rt_price_1m_partial_vec_option.is_some() {
|
|
// let rt_price_1m_partial_vec = rt_price_1m_partial_vec_option.unwrap();
|
|
|
|
// let mut sum_ratio_amp_body = 0.0;
|
|
// for element in rt_price_1m_partial_vec {
|
|
// sum_ratio_amp_body += (element.close_price - element.open_price).abs()
|
|
// / (element.high_price - element.low_price);
|
|
// }
|
|
// let average_ratio_amp_body = sum_ratio_amp_body / sample_length as f64;
|
|
// if average_ratio_amp_body > 0.3 {
|
|
// is_filtering_passed = true;
|
|
// } else {
|
|
// is_filtering_passed = false;
|
|
// }
|
|
// } else {
|
|
// is_filtering_passed = false;
|
|
// }
|
|
// }
|
|
|
|
// // check all filterings are passed
|
|
// if is_filtering_passed == true {
|
|
// filtered_2nd_symbols.push((symbol, rt_price_1m_vec.last().unwrap().close_time));
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// insert_pre_suggested_coins(2, &filtered_2nd_symbols, alldata).await;
|
|
// Ok(())
|
|
// }
|
|
|
|
// pub async fn strategist_001 (alldata: &AllData) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|
// // [strategist_001 procedure]
|
|
// // 1. retrieve all usdttrade symbols
|
|
// // 2. 1st filtering symbols (opclo_1m price avg < opclo_30m price avg)
|
|
// // 3. 2nd filtering symbols (opclo_30m price at the previous candle < bb_sma30_30m lowerband)
|
|
// // 4. insert or update record into [strategist_001_table]
|
|
// // 5. if symbol's 30m price is over bb_sma30_30m lowerband, move the record from [strategist_001_table] to [suggested_coin_list]
|
|
|
|
// // 1. retrieve all usdttrade symbols
|
|
// let signal_decision = select_signal_decision().await;
|
|
|
|
// // 3. 1st filtering symbols: 5 samples of candle 30m has 4 DOWN candles at least && the latest candle 30m < SMA3
|
|
// let mut opclo_30m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut sma3_30m_vec: Vec<SmaData> = Vec::new();
|
|
// let mut filtered_1st_symbols: Vec<String> = Vec::new();
|
|
// let mut cnt = 0;
|
|
// for symbol in &alldata.valid_symbol_vec {
|
|
|
|
// let opclo_30m_option = alldata.rt_price_30m_vec.iter().position(|x| *x.0 == *symbol);
|
|
// let sma3_30m_option = alldata.sma3_30m_data.iter().position(|x| *x.0 == *symbol);
|
|
|
|
// // read 1d csv file & bollingerband sma30 csv file
|
|
// if opclo_30m_option.is_some() & sma3_30m_option.is_some() {
|
|
// opclo_30m_vec = alldata.rt_price_30m_vec[opclo_30m_option.unwrap()].1.clone();
|
|
// sma3_30m_vec = alldata.sma3_30m_data[sma3_30m_option.unwrap()].1.clone();
|
|
|
|
// if opclo_30m_vec.len() >= 5 && sma3_30m_vec.len() >= 1 {
|
|
// opclo_30m_vec.reverse();
|
|
// opclo_30m_vec.truncate(5);
|
|
// opclo_30m_vec.reverse();
|
|
|
|
// cnt = 0;
|
|
// for element in &opclo_30m_vec {
|
|
// if element.candle_type == "DOWN" {
|
|
// cnt += 1;
|
|
// }
|
|
// }
|
|
|
|
// if cnt >= 4 {
|
|
// let result = sma3_30m_vec.binary_search_by_key(&opclo_30m_vec.last().unwrap().close_time, |&SmaData{sma_value, close_time}|close_time);
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if sma3_30m_vec[T].sma_value > opclo_30m_vec.last().unwrap().opclo_price {
|
|
// filtered_1st_symbols.push(symbol.clone());
|
|
// }
|
|
// },
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 4. 2nd filtering symbols: 30m RSI 3 < 15, 30m RSI 10 < 25
|
|
// let mut rsi3_vec: Vec<RsiData> = Vec::new();
|
|
// let mut rsi10_vec: Vec<RsiData> = Vec::new();
|
|
// let mut opclo_30m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut filtered_2nd_symbols: Vec<String> = Vec::new();
|
|
// for symbol in filtered_1st_symbols {
|
|
|
|
// let rsi3_option = alldata.rsi3_30m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let rsi10_option = alldata.rsi10_30m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let opclo_30m_option = alldata.rt_price_30m_vec.iter().position(|x| *x.0 == *symbol);
|
|
|
|
// if rsi3_option.is_some() && rsi10_option.is_some() && opclo_30m_option.is_some() {
|
|
// rsi3_vec = alldata.rsi3_30m_data[rsi3_option.unwrap()].1.clone();
|
|
// rsi10_vec = alldata.rsi10_30m_data[rsi10_option.unwrap()].1.clone();
|
|
// opclo_30m_vec = alldata.rt_price_30m_vec[opclo_30m_option.unwrap()].1.clone();
|
|
|
|
// if rsi3_vec.len() >= 1 && rsi10_vec.len() >= 1 && opclo_30m_vec.len() >= 1 {
|
|
// let result = rsi3_vec.binary_search_by_key(&opclo_30m_vec.last().unwrap().close_time, |&RsiData{rsi_value, close_time}|close_time);
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if rsi3_vec[T].rsi_value < 15.0 {
|
|
// let result = rsi10_vec.binary_search_by_key(&opclo_30m_vec.last().unwrap().close_time, |&RsiData{rsi_value, close_time}|close_time);
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if rsi10_vec[T].rsi_value < 25.0 {
|
|
// filtered_2nd_symbols.push(symbol);
|
|
// }
|
|
// },
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// },
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 3. 3rd filtering symbols: 5 samples of candle 1m has 4 DOWN candles at least && the latest candle 1m < EMA3
|
|
// let mut opclo_1m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut ema3_1m_vec: Vec<EmaData> = Vec::new();
|
|
// let mut filtered_3rd_symbols: Vec<(String, i64)> = Vec::new(); // (symbol, closetime)
|
|
// let mut cnt = 0;
|
|
// for symbol in filtered_2nd_symbols {
|
|
|
|
// let opclo_1m_option = alldata.rt_price_1m_vec.iter().position(|x| *x.0 == *symbol);
|
|
// let ema3_1m_option = alldata.ema3_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
|
|
// // read 1d csv file & bollingerband sma30 csv file
|
|
// if opclo_1m_option.is_some() & ema3_1m_option.is_some() {
|
|
// opclo_1m_vec = alldata.rt_price_1m_vec[opclo_1m_option.unwrap()].1.clone();
|
|
// ema3_1m_vec = alldata.ema3_1m_data[ema3_1m_option.unwrap()].1.clone();
|
|
|
|
// if opclo_1m_vec.len() >= 5 && ema3_1m_vec.len() >= 1 {
|
|
// opclo_1m_vec.reverse();
|
|
// opclo_1m_vec.truncate(5);
|
|
// opclo_1m_vec.reverse();
|
|
|
|
// cnt = 0;
|
|
// for element in &opclo_1m_vec {
|
|
// if element.candle_type == "DOWN" {
|
|
// cnt += 1;
|
|
// }
|
|
// }
|
|
|
|
// if cnt >= 4 {
|
|
// let result = ema3_1m_vec.binary_search_by_key(&opclo_1m_vec.last().unwrap().close_time, |&EmaData{ema_value, close_time}|close_time);
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if ema3_1m_vec[T].ema_value > opclo_1m_vec.last().unwrap().opclo_price {
|
|
// filtered_3rd_symbols.push((symbol, opclo_1m_vec.last().unwrap().close_time));
|
|
// }
|
|
// },
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // // 2. 2nd filtering symbols: candle 1m price avg < candle 30m price avg
|
|
// // let mut opclo_1m_vec: Vec<PriceData> = Vec::new();
|
|
// // let mut opclo_1m_price_avg = 0.0;
|
|
// // let mut opclo_30m_vec: Vec<PriceData> = Vec::new();
|
|
// // let mut opclo_30m_price_avg = 0.0;
|
|
// // let mut filtered_2nd_symbols: Vec<String> = Vec::new();
|
|
// // for element in filtered_1st_symbols {
|
|
// // // initialize avgs
|
|
// // opclo_1m_price_avg = 0.0;
|
|
// // opclo_30m_price_avg = 0.0;
|
|
|
|
// // let opclo_1m_result = read_price_into_vector("1m", &element).await;
|
|
// // let opclo_30m_result = read_price_into_vector("30m", &element).await;
|
|
|
|
// // // read 1d csv file
|
|
// // if opclo_1m_result.is_ok() && opclo_30m_result.is_ok() {
|
|
// // let opclo_1m_option = opclo_1m_result?;
|
|
// // let opclo_30m_option = opclo_30m_result?;
|
|
|
|
// // if opclo_1m_option.is_some() && opclo_30m_option.is_some() {
|
|
// // opclo_1m_vec = opclo_1m_option.unwrap();
|
|
// // opclo_30m_vec = opclo_30m_option.unwrap();
|
|
|
|
// // if opclo_1m_vec.len() >= 10 && opclo_30m_vec.len() >= 4 {
|
|
// // opclo_1m_vec.reverse();
|
|
// // opclo_1m_vec.split_off(10);
|
|
// // opclo_30m_vec.reverse();
|
|
// // opclo_30m_vec.split_off(4);
|
|
|
|
// // // calculate opclo 1m price average
|
|
// // for element in &opclo_1m_vec {
|
|
// // opclo_1m_price_avg += element.opclo_price;
|
|
// // }
|
|
// // opclo_1m_price_avg /= opclo_1m_vec.len() as f64;
|
|
|
|
// // // calculate opclo 30m price average
|
|
// // for element in &opclo_30m_vec {
|
|
// // opclo_30m_price_avg += element.opclo_price;
|
|
// // }
|
|
// // opclo_30m_price_avg /= opclo_30m_vec.len() as f64;
|
|
|
|
// // // campare both prices
|
|
// // if opclo_1m_price_avg < opclo_30m_price_avg * 0.98 {
|
|
// // filtered_2nd_symbols.push(element);
|
|
// // }
|
|
// // }
|
|
// // }
|
|
// // }
|
|
// // }
|
|
|
|
// // // 3. 2nd filtering symbols: 85% of BB SMA10 MA price > candle 1d price yesterday avg
|
|
// // let mut opclo_1d_vec: Vec<PriceData> = Vec::new();
|
|
// // let mut read_bb_vec: Vec<BBData> = Vec::new();
|
|
// // let mut filtered_2nd_symbols: Vec<String> = Vec::new();
|
|
// // for element in filtered_1st_symbols {
|
|
|
|
// // let opclo_1d_result = read_price_into_vector("1d", &element).await;
|
|
// // let read_bb_result = read_bb_into_vector("sma10", "1d", &element).await;
|
|
|
|
// // // read 1d csv file & bollingerband sma30 csv file
|
|
// // if opclo_1d_result.is_ok() & read_bb_result.is_ok() {
|
|
// // let opclo_1d_option = opclo_1d_result?;
|
|
// // let read_bb_option = read_bb_result?;
|
|
// // if opclo_1d_option.is_some() && read_bb_option.is_some() {
|
|
// // opclo_1d_vec = opclo_1d_option.unwrap();
|
|
// // read_bb_vec = read_bb_option.unwrap();
|
|
|
|
// // if opclo_1d_vec.len() > 1 && read_bb_vec.len() > 1 {
|
|
// // opclo_1d_vec.pop();
|
|
// // read_bb_vec.pop();
|
|
// // let result = read_bb_vec.binary_search_by_key(&opclo_1d_vec.last().unwrap().close_time, |&BBData{ma_price, upperband, lowerband, close_time}|close_time);
|
|
// // match result {
|
|
// // Ok(T) => {
|
|
// // if read_bb_vec[T].ma_price > opclo_1d_vec.last().unwrap().opclo_price {
|
|
// // filtered_2nd_symbols.push(element);
|
|
// // }
|
|
// // },
|
|
// // Err(E) => {}
|
|
// // }
|
|
// // }
|
|
// // }
|
|
// // }
|
|
// // }
|
|
|
|
// // // 3. 2nd filtering symbols: lower band in bollingerband of sma30 > candle 30m price
|
|
// // let mut read_bb_vec: Vec<BBData> = Vec::new();
|
|
// // let mut opclo_30m_vec: Vec<PriceData> = Vec::new();
|
|
// // let mut filtered_3rd_symbols: Vec<(String, u64)> = Vec::new(); // (symbol, closetime)
|
|
// // for element in filtered_2nd_symbols {
|
|
|
|
// // // read 30m csv file & bollingerband sma30 csv file
|
|
// // let opclo_30m_result = read_price_into_vector("30m", &element).await;
|
|
// // let bb_result = read_bb_into_vector("sma30", "30m", &element).await;
|
|
|
|
// // if opclo_30m_result.is_ok() && bb_result.is_ok() {
|
|
// // let opclo_30m_option = opclo_30m_result?;
|
|
// // let read_bb_option = bb_result?;
|
|
// // if opclo_30m_option.is_some() && read_bb_option.is_some() {
|
|
// // opclo_30m_vec = opclo_30m_option.unwrap();
|
|
// // read_bb_vec = read_bb_option.unwrap();
|
|
|
|
// // // 2nd filtering symbols
|
|
// // let result = read_bb_vec.binary_search_by_key(&opclo_30m_vec.last().unwrap().close_time, |&BBData{ma_price, upperband, lowerband, close_time}|close_time);
|
|
// // match result {
|
|
// // Ok(T) => {
|
|
// // if read_bb_vec[T].lowerband > opclo_30m_vec.last().unwrap().opclo_price {
|
|
// // filtered_3rd_symbols.push((element, read_bb_vec[T].close_time));
|
|
// // }
|
|
// // },
|
|
// // Err(E) => {}
|
|
// // }
|
|
// // }
|
|
|
|
// // }
|
|
// // }
|
|
|
|
// // 4. insert record into [pre_suggested_coin_list]
|
|
// insert_pre_suggested_coins(1, &filtered_3rd_symbols, alldata).await;
|
|
// // println!("strategist_001 완료");
|
|
// Ok(())
|
|
// }
|
|
|
|
// pub async fn strategist_002(
|
|
// alldata: &AllData,
|
|
// ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|
// // [strategist_002 procedure]
|
|
// // 1. retrieve all usdttrade symbols
|
|
// // 2. 1st filtering symbols (opclo_1m price avg < opclo_30m price avg)
|
|
// // 3. 2nd filtering symbols (sma30 price > opclo_30m price, check if the middle sample among 5 sample from the latest price is the lowest price and then check if RSI30 is lower than 0.3 of the middle sample)
|
|
// // 4. if the two conditions are right, upload the filtered symbols into [strategist_002_table]
|
|
// // 5. monitor price of symbols in [strategist_002_table], and upload them into [suggested_coin_list] when price seems to become high
|
|
// let signal_decision = select_signal_decision().await;
|
|
|
|
// if signal_decision[0].decision.contains("UP") {
|
|
// // 2. 1st filtering symbols: candle 1m price avg < candle 30m price avg
|
|
// let mut opclo_1m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut opclo_1m_price_avg = 0.0;
|
|
// let mut opclo_30m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut opclo_30m_price_avg = 0.0;
|
|
// let mut filtered_1st_symbols: Vec<String> = Vec::new();
|
|
// for symbol in &alldata.valid_symbol_vec {
|
|
// // initialize avgs
|
|
// opclo_1m_price_avg = 0.0;
|
|
// opclo_30m_price_avg = 0.0;
|
|
|
|
// let opclo_1m_option = alldata.rt_price_1m_vec.iter().position(|x| *x.0 == *symbol);
|
|
// let opclo_30m_option = alldata
|
|
// .rt_price_30m_vec
|
|
// .iter()
|
|
// .position(|x| *x.0 == *symbol);
|
|
|
|
// // read 1d csv file
|
|
// if opclo_1m_option.is_some() && opclo_30m_option.is_some() {
|
|
// opclo_1m_vec = alldata.rt_price_1m_vec[opclo_1m_option.unwrap()].1.clone();
|
|
// opclo_30m_vec = alldata.rt_price_30m_vec[opclo_30m_option.unwrap()]
|
|
// .1
|
|
// .clone();
|
|
|
|
// if opclo_1m_vec.len() >= 10 && opclo_30m_vec.len() >= 4 {
|
|
// opclo_1m_vec.reverse();
|
|
// opclo_1m_vec.split_off(10);
|
|
// opclo_30m_vec.reverse();
|
|
// opclo_30m_vec.split_off(4);
|
|
|
|
// // calculate opclo 1m price average
|
|
// for element in &opclo_1m_vec {
|
|
// opclo_1m_price_avg += element.opclo_price;
|
|
// }
|
|
// opclo_1m_price_avg /= opclo_1m_vec.len() as f64;
|
|
|
|
// // calculate opclo 30m price average
|
|
// for element in &opclo_30m_vec {
|
|
// opclo_30m_price_avg += element.opclo_price;
|
|
// }
|
|
// opclo_30m_price_avg /= opclo_30m_vec.len() as f64;
|
|
|
|
// // campare both prices
|
|
// if opclo_1m_price_avg < opclo_30m_price_avg * 0.97 {
|
|
// filtered_1st_symbols.push(symbol.clone());
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 3. 2nd filtering symbols: check if the middle sample among 5 sample from the latest price of SMA30 is the lowest price and then check if RSI30 is lower than 0.2 of the middle sample
|
|
// let mut sma10_30m_vec: Vec<SmaData> = Vec::new();
|
|
// let mut rsi30_30m_vec: Vec<RsiData> = Vec::new();
|
|
// let mut opclo_30m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut filtered_2nd_symbols: Vec<(String, i64)> = Vec::new(); // (symbol, closetime)
|
|
// for symbol in filtered_1st_symbols {
|
|
// // read 30m opclo, SMA30, rsi30 csv file
|
|
// let opclo_30m_option = alldata
|
|
// .rt_price_30m_vec
|
|
// .iter()
|
|
// .position(|x| *x.0 == *symbol);
|
|
// let sma10_30m_option = alldata.sma10_30m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let rsi30_30m_option = alldata.rsi30_30m_data.iter().position(|x| *x.0 == *symbol);
|
|
|
|
// if opclo_30m_option.is_some()
|
|
// && sma10_30m_option.is_some()
|
|
// && rsi30_30m_option.is_some()
|
|
// {
|
|
// opclo_30m_vec = alldata.rt_price_30m_vec[opclo_30m_option.unwrap()]
|
|
// .1
|
|
// .clone();
|
|
// sma10_30m_vec = alldata.sma10_30m_data[sma10_30m_option.unwrap()].1.clone();
|
|
// rsi30_30m_vec = alldata.rsi30_30m_data[rsi30_30m_option.unwrap()].1.clone();
|
|
|
|
// if opclo_30m_vec.len() >= 5 && sma10_30m_vec.len() >= 5 && rsi30_30m_vec.len() >= 5
|
|
// {
|
|
// opclo_30m_vec.pop();
|
|
// opclo_30m_vec.reverse();
|
|
// opclo_30m_vec.truncate(5);
|
|
|
|
// // 2nd filtering symbols
|
|
// let result = sma10_30m_vec.binary_search_by_key(
|
|
// &opclo_30m_vec.first().unwrap().close_time,
|
|
// |SmaData {
|
|
// sma_value,
|
|
// close_time,
|
|
// }| *close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if sma10_30m_vec[T].sma_value > opclo_30m_vec[0].opclo_price {
|
|
// let index_of_min: Option<usize> = opclo_30m_vec
|
|
// .iter()
|
|
// .enumerate()
|
|
// .min_by(|(_, a), (_, b)| {
|
|
// a.opclo_price
|
|
// .partial_cmp(&b.opclo_price)
|
|
// .expect("Nan was forbidden.")
|
|
// })
|
|
// .map(|(index, _)| index);
|
|
|
|
// // index 1 means the middle index of 5 element in a vec, assuming the latest price is included but removed in the vec.
|
|
// if index_of_min == Some(0) {
|
|
// let result = rsi30_30m_vec.binary_search_by_key(
|
|
// &opclo_30m_vec[0].close_time,
|
|
// |&RsiData {
|
|
// rsi_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if rsi30_30m_vec[T].rsi_value < 20.0 {
|
|
// filtered_2nd_symbols.push((
|
|
// symbol,
|
|
// opclo_30m_vec.last().unwrap().close_time,
|
|
// ));
|
|
// }
|
|
// }
|
|
// Err(e) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// // 4. insert record into [pre_suggested_coin_list]
|
|
// insert_pre_suggested_coins(2, &filtered_2nd_symbols, alldata).await;
|
|
// }
|
|
// // println!("strategist_002 완료");
|
|
// Ok(())
|
|
// }
|
|
|
|
// pub async fn strategist_003(
|
|
// alldata: &AllData,
|
|
// ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|
// // [strategist_003 procedure]
|
|
// // 1. retrieve all usdttrade symbols
|
|
// // 2. 1st filtering symbols (opclo_1m price avg < opclo_30m price avg)
|
|
// // 3. 2nd filtering symbols (opclo_30m price at the previous candle < bb_sma30_30m lowerband)
|
|
// // 4. 3rd filtering symbols (check if the middle sample among 5 sample from the latest price is the lowest price and then check if RSI30 is lower than 0.25 of the middle sample)
|
|
// // 5. if the two conditions are right, upload the filtered symbols into [suggested_coin_list]
|
|
// let signal_decision = select_signal_decision().await;
|
|
|
|
// if signal_decision[0].decision.contains("UP") {
|
|
// // 1. retrieve all usdttrade symbols
|
|
|
|
// // 2. 1st filtering symbols: yesterday and today's candle 1d opclo price < EMA10
|
|
// let mut opclo_1d_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut ema10_1d_vec: Vec<EmaData> = Vec::new();
|
|
// let mut rsi10_vec: Vec<RsiData> = Vec::new();
|
|
// let mut filtered_1st_symbols: Vec<String> = Vec::new();
|
|
// for symbol in &alldata.valid_symbol_vec {
|
|
// // read 1d csv file
|
|
// let opclo_1d_option = alldata.rt_price_1d_vec.iter().position(|x| *x.0 == *symbol);
|
|
// let ema10_1d_option = alldata.ema10_1d_data.iter().position(|x| *x.0 == *symbol);
|
|
// let rsi10_1d_option = alldata.rsi10_1d_data.iter().position(|x| *x.0 == *symbol);
|
|
|
|
// if opclo_1d_option.is_some() && ema10_1d_option.is_some() && rsi10_1d_option.is_some() {
|
|
// opclo_1d_vec = alldata.rt_price_1d_vec[opclo_1d_option.unwrap()].1.clone();
|
|
// ema10_1d_vec = alldata.ema10_1d_data[ema10_1d_option.unwrap()].1.clone();
|
|
// rsi10_vec = alldata.rsi10_1d_data[rsi10_1d_option.unwrap()].1.clone();
|
|
|
|
// if opclo_1d_vec.len() >= 2 && ema10_1d_vec.len() >= 2 && rsi10_vec.len() >= 2 {
|
|
// opclo_1d_vec.reverse();
|
|
// opclo_1d_vec.split_off(2);
|
|
// ema10_1d_vec.reverse();
|
|
// ema10_1d_vec.split_off(2);
|
|
// rsi10_vec.reverse();
|
|
// rsi10_vec.split_off(2);
|
|
|
|
// let result = ema10_1d_vec.binary_search_by_key(
|
|
// &opclo_1d_vec.last().unwrap().close_time,
|
|
// |EmaData {
|
|
// ema_value,
|
|
// close_time,
|
|
// }| *close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if ema10_1d_vec[T].ema_value > opclo_1d_vec[1].opclo_price {
|
|
// let result = rsi10_vec.binary_search_by_key(
|
|
// &opclo_1d_vec[1].close_time,
|
|
// |&RsiData {
|
|
// rsi_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if rsi10_vec[T].rsi_value < 20.0 {
|
|
// let result = ema10_1d_vec.binary_search_by_key(&opclo_1d_vec.first().unwrap().close_time, |EmaData{ema_value, close_time}| *close_time);
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if ema10_1d_vec[T].ema_value
|
|
// > opclo_1d_vec[0].opclo_price
|
|
// {
|
|
// filtered_1st_symbols.push(symbol.clone());
|
|
// }
|
|
// }
|
|
// Err(e) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// Err(e) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 3. 2nd filtering symbols: lower band in bollingerband of sma30 > candle 30m price
|
|
// let mut opclo_30m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut read_bb_vec: Vec<BollingerBandData> = Vec::new();
|
|
// let mut filtered_2nd_symbols: Vec<String> = Vec::new(); // (symbol, closetime)
|
|
// for symbol in filtered_1st_symbols {
|
|
// // read 30m csv file
|
|
// let opclo_30m_option = alldata
|
|
// .rt_price_30m_vec
|
|
// .iter()
|
|
// .position(|x| *x.0 == *symbol);
|
|
// let bb30_30m_option = alldata.bb30_30m_data.iter().position(|x| *x.0 == *symbol);
|
|
|
|
// if opclo_30m_option.is_some() && bb30_30m_option.is_some() {
|
|
// opclo_30m_vec = alldata.rt_price_30m_vec[opclo_30m_option.unwrap()]
|
|
// .1
|
|
// .clone();
|
|
// read_bb_vec = alldata.bb30_30m_data[bb30_30m_option.unwrap()].1.clone();
|
|
|
|
// if opclo_30m_vec.len() >= 1 && read_bb_vec.len() >= 1 {
|
|
// let result = read_bb_vec.binary_search_by_key(
|
|
// &opclo_30m_vec.last().unwrap().close_time,
|
|
// |&BollingerBandData {
|
|
// sma,
|
|
// upperband,
|
|
// lowerband,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if read_bb_vec[T].lowerband > opclo_30m_vec.last().unwrap().opclo_price
|
|
// {
|
|
// filtered_2nd_symbols.push(symbol);
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 4. 3rd filtering symbols: check if the middle sample among 5 sample from the latest price of SMA30 is the lowest price and then check if RSI30 is lower than 0.3 of the middle sample
|
|
// let mut low_1m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut bb30_1m_vec: Vec<BollingerBandData> = Vec::new();
|
|
// let mut rsi3_vec: Vec<RsiData> = Vec::new();
|
|
// let mut rsi10_vec: Vec<RsiData> = Vec::new();
|
|
// let mut filtered_3rd_symbols: Vec<(String, i64)> = Vec::new(); // (symbol, closetime)
|
|
// for symbol in filtered_2nd_symbols {
|
|
// let low_1m_option = alldata.rt_price_1m_vec.iter().position(|x| *x.0 == *symbol);
|
|
// let bb30_1m_option = alldata.bb30_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let rsi3_1m_option = alldata.rsi3_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let rsi10_1m_option = alldata.rsi10_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
|
|
// if low_1m_option.is_some()
|
|
// && bb30_1m_option.is_some()
|
|
// && rsi3_1m_option.is_some()
|
|
// && rsi10_1m_option.is_some()
|
|
// {
|
|
// low_1m_vec = alldata.rt_price_1m_vec[low_1m_option.unwrap()].1.clone();
|
|
// bb30_1m_vec = alldata.bb30_1m_data[bb30_1m_option.unwrap()].1.clone();
|
|
// rsi3_vec = alldata.rsi3_1m_data[rsi3_1m_option.unwrap()].1.clone();
|
|
// rsi10_vec = alldata.rsi10_1m_data[rsi10_1m_option.unwrap()].1.clone();
|
|
|
|
// if low_1m_vec.len() >= 1
|
|
// && bb30_1m_vec.len() >= 1
|
|
// && rsi3_vec.len() >= 1
|
|
// && rsi10_vec.len() >= 1
|
|
// {
|
|
// let result = bb30_1m_vec.binary_search_by_key(
|
|
// &low_1m_vec.last().unwrap().close_time,
|
|
// |&BollingerBandData {
|
|
// sma,
|
|
// upperband,
|
|
// lowerband,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if bb30_1m_vec[T].lowerband > low_1m_vec.last().unwrap().low_price {
|
|
// let result = rsi3_vec.binary_search_by_key(
|
|
// &low_1m_vec.last().unwrap().close_time,
|
|
// |&RsiData {
|
|
// rsi_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if rsi3_vec[T].rsi_value < 15.0 {
|
|
// let result = rsi10_vec.binary_search_by_key(&low_1m_vec.last().unwrap().close_time, |&RsiData{rsi_value, close_time}|close_time);
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if rsi10_vec[T].rsi_value < 20.0 {
|
|
// filtered_3rd_symbols.push((
|
|
// symbol,
|
|
// low_1m_vec.last().unwrap().close_time,
|
|
// ));
|
|
// }
|
|
// }
|
|
// Err(e) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// Err(e) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// // 4. insert record into [pre_suggested_coin_list]
|
|
// insert_pre_suggested_coins(3, &filtered_3rd_symbols, alldata).await;
|
|
// }
|
|
|
|
// // println!("strategist_003 완료");
|
|
// Ok(())
|
|
// }
|
|
|
|
// pub async fn strategist_004(
|
|
// alldata: &AllData,
|
|
// ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|
// // [strategist_004 procedure]
|
|
// // 1st filtering: opclo_30m price < bb30_30m lowerband
|
|
// // 2nd filtering: opclo_1m price < bb30_1m lowerband
|
|
// // 3rd filtering: RSI3_1m < 10, RSI10_1m < 25
|
|
|
|
// let signal_decision = select_signal_decision().await;
|
|
// if signal_decision[0].decision.contains("UP") {
|
|
// // 1st filtering: (opclo_30m price < bb30 lowerband)
|
|
// let mut opclo_30m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut bb30_30m_vec: Vec<BollingerBandData> = Vec::new();
|
|
// let mut filtered_1st_symbols: Vec<String> = Vec::new();
|
|
// for symbol in &alldata.valid_symbol_vec {
|
|
// let opclo_30m_option = alldata
|
|
// .rt_price_30m_vec
|
|
// .iter()
|
|
// .position(|x| *x.0 == *symbol);
|
|
// let bb30_30m_option = alldata.bb30_30m_data.iter().position(|x| *x.0 == *symbol);
|
|
|
|
// if opclo_30m_option.is_some() && bb30_30m_option.is_some() {
|
|
// opclo_30m_vec = alldata.rt_price_30m_vec[opclo_30m_option.unwrap()]
|
|
// .1
|
|
// .clone();
|
|
// bb30_30m_vec = alldata.bb30_30m_data[bb30_30m_option.unwrap()].1.clone();
|
|
|
|
// if opclo_30m_vec.len() >= 1 && bb30_30m_vec.len() >= 1 {
|
|
// let result = bb30_30m_vec.binary_search_by_key(
|
|
// &opclo_30m_vec.last().unwrap().close_time,
|
|
// |&BollingerBandData {
|
|
// sma,
|
|
// upperband,
|
|
// lowerband,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if bb30_30m_vec[T].lowerband > opclo_30m_vec.last().unwrap().opclo_price
|
|
// {
|
|
// filtered_1st_symbols.push(symbol.clone());
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 2nd filtering: (opclo_1m price < bb30_1m lowerband)
|
|
// let mut opclo_1m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut bb30_1m_vec: Vec<BollingerBandData> = Vec::new();
|
|
// let mut filtered_2nd_symbols: Vec<String> = Vec::new();
|
|
// for symbol in filtered_1st_symbols {
|
|
// let opclo_1m_option = alldata.rt_price_1m_vec.iter().position(|x| *x.0 == *symbol);
|
|
// let bb30_1m_option = alldata.bb30_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
|
|
// if opclo_1m_option.is_some() && bb30_1m_option.is_some() {
|
|
// opclo_1m_vec = alldata.rt_price_1m_vec[opclo_1m_option.unwrap()].1.clone();
|
|
// bb30_1m_vec = alldata.bb30_1m_data[bb30_1m_option.unwrap()].1.clone();
|
|
|
|
// if opclo_1m_vec.len() >= 1 && bb30_1m_vec.len() >= 1 {
|
|
// let result = bb30_1m_vec.binary_search_by_key(
|
|
// &opclo_1m_vec.last().unwrap().close_time,
|
|
// |&BollingerBandData {
|
|
// sma,
|
|
// upperband,
|
|
// lowerband,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if bb30_1m_vec[T].lowerband > opclo_1m_vec.last().unwrap().opclo_price {
|
|
// filtered_2nd_symbols.push(symbol);
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 3rd filtering: RSI3_1m < 10, RSI10_1m < 25
|
|
// let mut opclo_1m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut rsi3_1m_vec: Vec<RsiData> = Vec::new();
|
|
// let mut rsi10_1m_vec: Vec<RsiData> = Vec::new();
|
|
// let mut filtered_3rd_symbols: Vec<(String, i64)> = Vec::new(); // (symbol, closetime)
|
|
// for symbol in filtered_2nd_symbols {
|
|
// let opclo_1m_option = alldata.rt_price_1m_vec.iter().position(|x| *x.0 == *symbol);
|
|
// let rsi3_1m_option = alldata.rsi3_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let rsi10_1m_option = alldata.rsi10_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
|
|
// if opclo_1m_option.is_some() && rsi3_1m_option.is_some() && rsi10_1m_option.is_some() {
|
|
// opclo_1m_vec = alldata.rt_price_1m_vec[opclo_1m_option.unwrap()].1.clone();
|
|
// rsi3_1m_vec = alldata.rsi3_1m_data[rsi3_1m_option.unwrap()].1.clone();
|
|
// rsi10_1m_vec = alldata.rsi10_1m_data[rsi10_1m_option.unwrap()].1.clone();
|
|
// }
|
|
|
|
// if opclo_1m_vec.len() >= 1 && rsi3_1m_vec.len() >= 1 && rsi10_1m_vec.len() >= 1 {
|
|
// let result = rsi3_1m_vec.binary_search_by_key(
|
|
// &opclo_1m_vec.last().unwrap().close_time,
|
|
// |&RsiData {
|
|
// rsi_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if rsi3_1m_vec[T].rsi_value < 10.0 {
|
|
// let result = rsi10_1m_vec.binary_search_by_key(
|
|
// &opclo_1m_vec.last().unwrap().close_time,
|
|
// |&RsiData {
|
|
// rsi_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if rsi10_1m_vec[T].rsi_value < 25.0 {
|
|
// filtered_3rd_symbols.push((
|
|
// symbol,
|
|
// opclo_1m_vec.last().unwrap().close_time,
|
|
// ));
|
|
// }
|
|
// }
|
|
// Err(e) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// Err(e) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// // 4. insert record into [pre_suggested_coin_list]
|
|
// insert_pre_suggested_coins(4, &filtered_3rd_symbols, alldata).await;
|
|
// }
|
|
// // println!("strategist_004 완료");
|
|
// Ok(())
|
|
// }
|
|
|
|
// // for ultra-short
|
|
// pub async fn strategist_005(
|
|
// alldata: &AllData,
|
|
// ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|
// // [strategist_005 procedure]
|
|
// // 1st filtering: sampling the least 1m 5 tickers, check DOWN ticker at least 2, check the quote vol of the last ticker > 2X the counterpart of the previous 2 tickers.
|
|
// // 2nd filtering: opclo_1m price < sma3_1m
|
|
// // 3rd filtering: RSI3_1m < 10, RSI10_1m < 25
|
|
// // 4th filtering: check the latest and previous 30m candles are UPs
|
|
|
|
// let signal_decision = select_signal_decision().await;
|
|
// if signal_decision[0].decision.contains("UP") {
|
|
// // 1st filtering: sampling the least 1m 5 tickers, check DOWN ticker at least 2, check the quote vol of the last ticker > 2X the counterpart of the previous 2 tickers.
|
|
// let mut opclo_1m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut filtered_1st_symbols: Vec<String> = Vec::new();
|
|
// for symbol in &alldata.valid_symbol_vec {
|
|
// let opclo_1m_option = alldata.rt_price_1m_vec.iter().position(|x| *x.0 == *symbol);
|
|
|
|
// if opclo_1m_option.is_some() {
|
|
// opclo_1m_vec = alldata.rt_price_1m_vec[opclo_1m_option.unwrap()].1.clone();
|
|
// if opclo_1m_vec.len() >= 5 {
|
|
// opclo_1m_vec.reverse();
|
|
// opclo_1m_vec.truncate(5);
|
|
// opclo_1m_vec.reverse();
|
|
|
|
// let mut cnt = 0;
|
|
// for element in &opclo_1m_vec {
|
|
// if element.candle_type == "DOWN"
|
|
// && element.opclo_price > opclo_1m_vec.last().unwrap().opclo_price
|
|
// {
|
|
// cnt += 1;
|
|
// }
|
|
// }
|
|
|
|
// if cnt >= 2 && opclo_1m_vec.last().unwrap().candle_type == "DOWN" {
|
|
// let mut vec_cmp = opclo_1m_vec.to_vec();
|
|
// vec_cmp.pop();
|
|
// vec_cmp.reverse();
|
|
// let mut vec_iter = vec_cmp.iter();
|
|
|
|
// for _ in 0..2 {
|
|
// let temp = vec_iter.next();
|
|
// if temp.is_some() {
|
|
// if (temp.unwrap().quote_asset_volume != 0.0)
|
|
// && (temp.unwrap().quote_asset_volume * 2.0
|
|
// < opclo_1m_vec.last().unwrap().quote_asset_volume)
|
|
// {
|
|
// filtered_1st_symbols.push(symbol.clone());
|
|
// break;
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 2nd filtering: opclo_1m price < sma3_1m
|
|
// let mut sma3_1m_vec: Vec<SmaData> = Vec::new();
|
|
// let mut opclo_1m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut filtered_2nd_symbols: Vec<String> = Vec::new();
|
|
// for symbol in filtered_1st_symbols {
|
|
// let sma3_1m_option = alldata.sma3_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let opclo_1m_option = alldata.rt_price_1m_vec.iter().position(|x| *x.0 == *symbol);
|
|
|
|
// if sma3_1m_option.is_some() && opclo_1m_option.is_some() {
|
|
// sma3_1m_vec = alldata.sma3_1m_data[sma3_1m_option.unwrap()].1.clone();
|
|
// opclo_1m_vec = alldata.rt_price_1m_vec[opclo_1m_option.unwrap()].1.clone();
|
|
|
|
// if sma3_1m_vec.len() >= 1 && opclo_1m_vec.len() >= 1 {
|
|
// let result = sma3_1m_vec.binary_search_by_key(
|
|
// &opclo_1m_vec.last().unwrap().close_time,
|
|
// |&SmaData {
|
|
// sma_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if sma3_1m_vec[T].sma_value > opclo_1m_vec.last().unwrap().opclo_price {
|
|
// filtered_2nd_symbols.push(symbol);
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 3rd filtering: RSI3_1m < 10, RSI10_1m < 25
|
|
// let mut opclo_1m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut rsi3_1m_vec: Vec<RsiData> = Vec::new();
|
|
// let mut rsi10_1m_vec: Vec<RsiData> = Vec::new();
|
|
// let mut filtered_3rd_symbols: Vec<String> = Vec::new();
|
|
// for symbol in filtered_2nd_symbols {
|
|
// let opclo_1m_option = alldata.rt_price_1m_vec.iter().position(|x| *x.0 == *symbol);
|
|
// let rsi3_1m_option = alldata.rsi3_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let rsi10_1m_option = alldata.rsi10_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
|
|
// if opclo_1m_option.is_some() && rsi3_1m_option.is_some() && rsi10_1m_option.is_some() {
|
|
// opclo_1m_vec = alldata.rt_price_1m_vec[opclo_1m_option.unwrap()].1.clone();
|
|
// rsi3_1m_vec = alldata.rsi3_1m_data[rsi3_1m_option.unwrap()].1.clone();
|
|
// rsi10_1m_vec = alldata.rsi10_1m_data[rsi10_1m_option.unwrap()].1.clone();
|
|
|
|
// if opclo_1m_vec.len() >= 1 && rsi3_1m_vec.len() >= 1 && rsi10_1m_vec.len() >= 1 {
|
|
// let result = rsi3_1m_vec.binary_search_by_key(
|
|
// &opclo_1m_vec.last().unwrap().close_time,
|
|
// |&RsiData {
|
|
// rsi_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if rsi3_1m_vec[T].rsi_value < 10.0 {
|
|
// let result = rsi10_1m_vec.binary_search_by_key(
|
|
// &opclo_1m_vec.last().unwrap().close_time,
|
|
// |&RsiData {
|
|
// rsi_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if rsi10_1m_vec[T].rsi_value < 25.0 {
|
|
// filtered_3rd_symbols.push(symbol);
|
|
// }
|
|
// }
|
|
// Err(e) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// Err(e) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 4th filtering: check the latest and previous 30m candles are UPs
|
|
// let mut opclo_30m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut opclo_1m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut filtered_4th_symbols: Vec<(String, i64)> = Vec::new(); // (symbol, closetime)
|
|
// for symbol in filtered_3rd_symbols {
|
|
// let opclo_30m_option = alldata
|
|
// .rt_price_30m_vec
|
|
// .iter()
|
|
// .position(|x| *x.0 == *symbol);
|
|
// let opclo_1m_option = alldata.rt_price_1m_vec.iter().position(|x| *x.0 == *symbol);
|
|
|
|
// if opclo_30m_option.is_some() && opclo_1m_option.is_some() {
|
|
// opclo_30m_vec = alldata.rt_price_30m_vec[opclo_30m_option.unwrap()]
|
|
// .1
|
|
// .clone();
|
|
// opclo_1m_vec = alldata.rt_price_1m_vec[opclo_1m_option.unwrap()].1.clone();
|
|
|
|
// if opclo_30m_vec.len() >= 2 && opclo_1m_vec.len() >= 1 {
|
|
// opclo_30m_vec.reverse();
|
|
// opclo_30m_vec.truncate(2);
|
|
// opclo_30m_vec.reverse();
|
|
|
|
// if opclo_30m_vec.first().unwrap().candle_type == "UP"
|
|
// && opclo_30m_vec.last().unwrap().candle_type == "UP"
|
|
// {
|
|
// filtered_4th_symbols
|
|
// .push((symbol, opclo_1m_vec.last().unwrap().close_time));
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 4. insert record into [pre_suggested_coin_list]
|
|
// insert_pre_suggested_coins(5, &filtered_4th_symbols, alldata).await;
|
|
// }
|
|
// // println!("strategist_005 완료");
|
|
// Ok(())
|
|
// }
|
|
|
|
// pub async fn strategist_006(
|
|
// alldata: &AllData,
|
|
// ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|
// // [strategist_006 procedure]
|
|
// // 1st filtering: the latest 2 opclo_1d < BB30_1d upper band, current price < previous opclo_1d
|
|
// // 2nd filtering: check 5 samples of candle 30m has DOWN candles at least 3, the latest opclo_30m < SMA3_30m
|
|
// // 3rd filtering: RSI3_30m < 15, RSI10_30m < 35
|
|
// // 4th filtering: the latest 30m quote vol > 2X the previous quote vol
|
|
|
|
// // 1st filtering symbols: the latest 2 opclo_1d < BB30_1d upper band, current price < previous opclo_1d
|
|
// let mut opclo_1d_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut bb30_1d_vec: Vec<BollingerBandData> = Vec::new();
|
|
// let mut filtered_1st_symbols: Vec<String> = Vec::new();
|
|
// let mut current_price: Option<f64>;
|
|
// for symbol in &alldata.valid_symbol_vec {
|
|
// let opclo_1d_option = alldata.rt_price_1d_vec.iter().position(|x| *x.0 == *symbol);
|
|
// let bb30_1d_option = alldata.bb30_1d_data.iter().position(|x| *x.0 == *symbol);
|
|
|
|
// if opclo_1d_option.is_some() && bb30_1d_option.is_some() {
|
|
// opclo_1d_vec = alldata.rt_price_1d_vec[opclo_1d_option.unwrap()].1.clone();
|
|
// bb30_1d_vec = alldata.bb30_1d_data[bb30_1d_option.unwrap()].1.clone();
|
|
|
|
// if opclo_1d_vec.len() >= 2 && bb30_1d_vec.len() >= 2 {
|
|
// opclo_1d_vec.reverse();
|
|
// opclo_1d_vec.truncate(2);
|
|
// opclo_1d_vec.reverse();
|
|
// bb30_1d_vec.reverse();
|
|
// bb30_1d_vec.truncate(2);
|
|
// bb30_1d_vec.reverse();
|
|
|
|
// let result = bb30_1d_vec.binary_search_by_key(
|
|
// &opclo_1d_vec.first().unwrap().close_time,
|
|
// |&BollingerBandData {
|
|
// sma,
|
|
// upperband,
|
|
// lowerband,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// current_price = get_current_price(&symbol, &alldata.price_vec).await;
|
|
|
|
// if current_price.is_some() {
|
|
// if current_price.unwrap().is_normal() {
|
|
// if (bb30_1d_vec[T].upperband
|
|
// > opclo_1d_vec.first().unwrap().opclo_price)
|
|
// && (opclo_1d_vec.first().unwrap().opclo_price
|
|
// > current_price.unwrap())
|
|
// {
|
|
// let result = bb30_1d_vec.binary_search_by_key(
|
|
// &opclo_1d_vec.last().unwrap().close_time,
|
|
// |&BollingerBandData {
|
|
// sma,
|
|
// upperband,
|
|
// lowerband,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if bb30_1d_vec[T].upperband
|
|
// > opclo_1d_vec.last().unwrap().opclo_price
|
|
// {
|
|
// filtered_1st_symbols.push(symbol.clone());
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 2nd filtering: check 5 samples of candle 30m has DOWN candles at least 3, the latest opclo_30m < SMA3_30m
|
|
// let mut opclo_30m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut sma3_30m_vec: Vec<SmaData> = Vec::new();
|
|
// let mut filtered_2nd_symbols: Vec<String> = Vec::new();
|
|
// let mut cnt = 0;
|
|
// for symbol in filtered_1st_symbols {
|
|
// let opclo_30m_option = alldata
|
|
// .rt_price_30m_vec
|
|
// .iter()
|
|
// .position(|x| *x.0 == *symbol);
|
|
// let sma3_30m_option = alldata.sma3_30m_data.iter().position(|x| *x.0 == *symbol);
|
|
|
|
// if opclo_30m_option.is_some() && sma3_30m_option.is_some() {
|
|
// opclo_30m_vec = alldata.rt_price_30m_vec[opclo_30m_option.unwrap()]
|
|
// .1
|
|
// .clone();
|
|
// sma3_30m_vec = alldata.sma3_30m_data[sma3_30m_option.unwrap()].1.clone();
|
|
|
|
// if opclo_30m_vec.len() >= 5 && sma3_30m_vec.len() >= 1 {
|
|
// opclo_30m_vec.reverse();
|
|
// opclo_30m_vec.truncate(5);
|
|
// opclo_30m_vec.reverse();
|
|
|
|
// cnt = 0;
|
|
// for element in &opclo_30m_vec {
|
|
// if element.candle_type == "DOWN" {
|
|
// cnt += 1;
|
|
// }
|
|
// }
|
|
|
|
// if cnt >= 3 {
|
|
// let result = sma3_30m_vec.binary_search_by_key(
|
|
// &opclo_30m_vec.last().unwrap().close_time,
|
|
// |&SmaData {
|
|
// sma_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if sma3_30m_vec[T].sma_value > opclo_30m_vec.last().unwrap().opclo_price
|
|
// {
|
|
// filtered_2nd_symbols.push(symbol);
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 3rd filtering: RSI3_30m < 15, RSI10_30m < 35
|
|
// let mut rsi3_30m_vec: Vec<RsiData> = Vec::new();
|
|
// let mut rsi10_30m_vec: Vec<RsiData> = Vec::new();
|
|
// let mut opclo_30m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut filtered_3rd_symbols: Vec<String> = Vec::new();
|
|
// for symbol in filtered_2nd_symbols {
|
|
// let rsi3_30m_option = alldata.rsi3_30m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let rsi10_30m_option = alldata.rsi10_30m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let opclo_30m_option = alldata
|
|
// .rt_price_30m_vec
|
|
// .iter()
|
|
// .position(|x| *x.0 == *symbol);
|
|
|
|
// if rsi3_30m_option.is_some() && rsi10_30m_option.is_some() && opclo_30m_option.is_some() {
|
|
// rsi3_30m_vec = alldata.rsi3_30m_data[rsi3_30m_option.unwrap()].1.clone();
|
|
// rsi10_30m_vec = alldata.rsi10_30m_data[rsi10_30m_option.unwrap()].1.clone();
|
|
// opclo_30m_vec = alldata.rt_price_30m_vec[opclo_30m_option.unwrap()]
|
|
// .1
|
|
// .clone();
|
|
|
|
// if rsi3_30m_vec.len() >= 1 && rsi10_30m_vec.len() >= 1 && opclo_30m_vec.len() >= 1 {
|
|
// let result = rsi3_30m_vec.binary_search_by_key(
|
|
// &opclo_30m_vec.last().unwrap().close_time,
|
|
// |&RsiData {
|
|
// rsi_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if rsi3_30m_vec[T].rsi_value < 15.0 {
|
|
// let result = rsi10_30m_vec.binary_search_by_key(
|
|
// &opclo_30m_vec.last().unwrap().close_time,
|
|
// |&RsiData {
|
|
// rsi_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if rsi10_30m_vec[T].rsi_value < 35.0 {
|
|
// filtered_3rd_symbols.push(symbol);
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 4th filtering: the latest 30m quote vol > 2X the previous quote vol
|
|
// let mut opclo_30m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut filtered_4th_symbols: Vec<(String, i64)> = Vec::new(); // (symbol, closetime)
|
|
// for symbol in filtered_3rd_symbols {
|
|
// let opclo_30m_option = alldata
|
|
// .rt_price_30m_vec
|
|
// .iter()
|
|
// .position(|x| *x.0 == *symbol);
|
|
|
|
// if opclo_30m_option.is_some() {
|
|
// opclo_30m_vec = alldata.rt_price_30m_vec[opclo_30m_option.unwrap()]
|
|
// .1
|
|
// .clone();
|
|
|
|
// if opclo_30m_vec.len() >= 2 {
|
|
// opclo_30m_vec.reverse();
|
|
// opclo_30m_vec.truncate(2);
|
|
// opclo_30m_vec.reverse();
|
|
|
|
// if 2.0 * opclo_30m_vec.first().unwrap().quote_asset_volume
|
|
// < opclo_30m_vec.last().unwrap().quote_asset_volume
|
|
// && opclo_30m_vec.last().unwrap().candle_type == "DOWN"
|
|
// {
|
|
// filtered_4th_symbols.push((symbol, opclo_30m_vec.last().unwrap().close_time));
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 7. insert record into [pre_suggested_coin_list]
|
|
// insert_pre_suggested_coins(6, &filtered_4th_symbols, alldata).await;
|
|
// Ok(())
|
|
// }
|
|
|
|
// pub async fn strategist_006 () -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|
// // [strategist_006 procedure]
|
|
// // 1. retrieve all usdttrade symbols
|
|
// // 2. 1st filtering symbols (low_price_1m price avg < low_price_30m price avg)
|
|
// // 3. 2nd filtering symbols (low_price_30m price at the previous candle < bb_sma30_30m lowerband)
|
|
// // 4. insert [pre_suggested_coin_list]
|
|
|
|
// // 1. retrieve all usdttrade symbols
|
|
// #[derive(Debug, FromRow)]
|
|
// struct UsdtTrades {
|
|
// symbol: String,
|
|
// }
|
|
// let mut usdt_trades = UsdtTrades { symbol: String::new() };
|
|
|
|
// let table_name = String::from("valid_usdt_trades");
|
|
// let column_name = String::from("symbol");
|
|
// let table_condition = None;
|
|
// let mut usdt_trade_symbols = select_record(&table_name, &column_name, &table_condition, &usdt_trades).await.unwrap();
|
|
|
|
// let mut low_price_1m_vec: Vec<OpcloData> = Vec::new();
|
|
// let mut low_price_1m_avg = 0.0;
|
|
// let mut low_price_30m_vec: Vec<OpcloData> = Vec::new();
|
|
// let mut low_price_30m_avg = 0.0;
|
|
|
|
// // 2. 1st filtering symbols: candle 1m price avg < candle 30m price avg
|
|
// let mut filtered_1st_symbols: Vec<String> = Vec::new();
|
|
// for element in usdt_trade_symbols {
|
|
// // initialize avgs
|
|
// low_price_1m_avg = 0.0;
|
|
// low_price_30m_avg = 0.0;
|
|
|
|
// // read 1m csv file
|
|
// low_price_1m_vec = read_low_price_into_vector("1m", &element.symbol).await?;
|
|
|
|
// // calculate opclo 1m price average
|
|
// for element in &low_price_1m_vec {
|
|
// low_price_1m_avg += element.price;
|
|
// }
|
|
// low_price_1m_avg /= low_price_1m_vec.len() as f64;
|
|
|
|
// // read 30m csv file
|
|
// low_price_30m_vec = read_low_price_into_vector("30m", &element.symbol).await?;
|
|
|
|
// // calculate opclo 30m price average
|
|
// for element in &low_price_30m_vec {
|
|
// low_price_30m_avg += element.price;
|
|
// }
|
|
// low_price_30m_avg /= low_price_30m_vec.len() as f64;
|
|
|
|
// // campare both prices
|
|
// if low_price_1m_avg < low_price_30m_avg {
|
|
// filtered_1st_symbols.push(element.symbol);
|
|
// }
|
|
// }
|
|
|
|
// let mut read_bb_vec: Vec<BBData> = Vec::new();
|
|
// let mut filtered_2nd_symbols: Vec<(String, u64)> = Vec::new(); // (symbol, closetime)
|
|
|
|
// // 3. 2nd filtering symbols: lower band in bollingerband of sma30 > candle 30m price
|
|
// for element in filtered_1st_symbols {
|
|
|
|
// // read 30m csv file
|
|
// low_price_30m_vec = read_low_price_into_vector("30m", &element).await?;
|
|
|
|
// // read bollingerband sma30 csv file
|
|
// read_bb_vec = read_bb_into_vector("sma30", "30m", &element).await?;
|
|
|
|
// // 2nd filtering symbols
|
|
// low_price_30m_vec.pop();
|
|
// let result = read_bb_vec.binary_search_by_key(&low_price_30m_vec.last().unwrap().server_epoch, |&BBData{ma_price, upperband, lowerband, server_epoch}|server_epoch);
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if read_bb_vec[T].lowerband > low_price_30m_vec.last().unwrap().price {
|
|
// filtered_2nd_symbols.push((element, read_bb_vec[T].server_epoch));
|
|
// }
|
|
// },
|
|
// Err(E) => {}
|
|
// }
|
|
|
|
// }
|
|
|
|
// // 4. insert record into [pre_suggested_coin_list]
|
|
// insert_pre_suggested_coins(6, &filtered_2nd_symbols).await;
|
|
|
|
// println!("strategist_006 완료");
|
|
// Ok(())
|
|
// }
|
|
|
|
// pub async fn strategist_007 () -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|
// // [strategist_007 procedure]
|
|
// // 1. retrieve all usdttrade symbols
|
|
// // 2. 1st filtering symbols (low_price_1m avg < low_price_30m price avg)
|
|
// // 3. 2nd filtering symbols (sma30 price > low_price_30m, check if the middle sample among 5 sample from the latest price is the lowest price and then check if RSI30 is lower than 0.3 of the middle sample)
|
|
// // 4. insert [pre_suggested_coin_list]
|
|
|
|
// // 1. retrieve all usdttrade symbols
|
|
// #[derive(Debug, FromRow)]
|
|
// struct UsdtTrades {
|
|
// symbol: String,
|
|
// }
|
|
// let mut usdt_trades = UsdtTrades { symbol: String::new() };
|
|
|
|
// let table_name = String::from("valid_usdt_trades");
|
|
// let column_name = String::from("symbol");
|
|
// let table_condition = None;
|
|
// let mut usdt_trade_symbols = select_record(&table_name, &column_name, &table_condition, &usdt_trades).await.unwrap();
|
|
|
|
// let mut low_price_1m_vec: Vec<OpcloData> = Vec::new();
|
|
// let mut low_price_1m_avg = 0.0;
|
|
// let mut low_price_30m_vec: Vec<OpcloData> = Vec::new();
|
|
// let mut low_price_30m_avg = 0.0;
|
|
|
|
// // 2. 1st filtering symbols: candle 1m price avg < candle 30m price avg
|
|
// let mut filtered_1st_symbols: Vec<String> = Vec::new();
|
|
// for element in usdt_trade_symbols {
|
|
// // initialize avgs
|
|
// low_price_1m_avg = 0.0;
|
|
// low_price_30m_avg = 0.0;
|
|
|
|
// // read 1m csv file
|
|
// low_price_1m_vec = read_low_price_into_vector("1m", &element.symbol).await?;
|
|
|
|
// // calculate opclo 1m price average
|
|
// for element in &low_price_1m_vec {
|
|
// low_price_1m_avg += element.price;
|
|
// }
|
|
// low_price_1m_avg /= low_price_1m_vec.len() as f64;
|
|
|
|
// // read 30m csv file
|
|
// low_price_30m_vec = read_low_price_into_vector("30m", &element.symbol).await?;
|
|
|
|
// // calculate opclo 30m price average
|
|
// for element in &low_price_30m_vec {
|
|
// low_price_30m_avg += element.price;
|
|
// }
|
|
// low_price_30m_avg /= low_price_30m_vec.len() as f64;
|
|
|
|
// // campare both prices
|
|
// if low_price_1m_avg < low_price_30m_avg {
|
|
// filtered_1st_symbols.push(element.symbol);
|
|
// }
|
|
// }
|
|
|
|
// let mut sma30_30m_vec: Vec<MaData> = Vec::new();
|
|
// let mut rsi30_vec: Vec<RsiData> = Vec::new();
|
|
// let mut filtered_2nd_symbols: Vec<(String, u64)> = Vec::new(); // (symbol, closetime)
|
|
|
|
// // 3. 2nd filtering symbols: check if the middle sample among 5 sample from the latest price of SMA30 is the lowest price and then check if RSI30 is lower than 0.3 of the middle sample
|
|
// for element in filtered_1st_symbols {
|
|
|
|
// // read 30m csv file
|
|
// low_price_30m_vec = read_low_price_into_vector("30m", &element).await?;
|
|
// low_price_30m_vec.pop();
|
|
// low_price_30m_vec.reverse();
|
|
// low_price_30m_vec.truncate(5);
|
|
|
|
// // read SMA30 csv file
|
|
// sma30_30m_vec = read_ma_into_vector(&MA::Sma, 30, "30m", &element).await?;
|
|
|
|
// // read rsi30 csv file
|
|
// rsi30_vec = read_rsi_into_vector(30, "30m", &element).await?;
|
|
|
|
// if low_price_30m_vec.len() == 5 {
|
|
|
|
// // 2nd filtering symbols
|
|
// let result = sma30_30m_vec.binary_search_by_key(&low_price_30m_vec.first().unwrap().server_epoch, |MaData{price, server_epoch}| *server_epoch);
|
|
// match result {
|
|
// Ok(T) => {
|
|
|
|
// if sma30_30m_vec[T].price > low_price_30m_vec[0].price {
|
|
|
|
// let index_of_min: Option<usize> = low_price_30m_vec
|
|
// .iter()
|
|
// .enumerate()
|
|
// .min_by(|(_, a), (_, b)| a.price.partial_cmp(&b.price).expect("Nan was forbidden."))
|
|
// .map(|(index, _)| index);
|
|
|
|
// // index 1 means the middle index of 5 element in a vec, assuming the latest price is included but removed in the vec.
|
|
// if index_of_min == Some(1) {
|
|
// let result = rsi30_vec.binary_search_by_key(&low_price_30m_vec[1].server_epoch, |&RsiData{rsi_value, server_epoch}|server_epoch);
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if rsi30_vec[T].rsi_value < 0.3 {
|
|
// filtered_2nd_symbols.push((element, low_price_30m_vec.first().unwrap().server_epoch));
|
|
// }
|
|
// },
|
|
// Err(e) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// },
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 4. insert record into [pre_suggested_coin_list]
|
|
// insert_pre_suggested_coins(7, &filtered_2nd_symbols).await;
|
|
|
|
// println!("strategist_007 완료");
|
|
// Ok(())
|
|
// }
|
|
|
|
// pub async fn strategist_008 () -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|
// // [strategist_008 procedure]
|
|
// // 1. retrieve all usdttrade symbols
|
|
// // 2. 1st filtering symbols (low_price_1m avg < low_price_30m avg)
|
|
// // 3. 2nd filtering symbols (low_price_30m at the previous candle < bb_sma30_30m lowerband)
|
|
// // 4. insert [pre_suggested_coin_list]
|
|
|
|
// // 1. retrieve all usdttrade symbols
|
|
// #[derive(Debug, FromRow)]
|
|
// struct UsdtTrades {
|
|
// symbol: String,
|
|
// }
|
|
// let mut usdt_trades = UsdtTrades { symbol: String::new() };
|
|
|
|
// let table_name = String::from("valid_usdt_trades");
|
|
// let column_name = String::from("symbol");
|
|
// let table_condition = None;
|
|
// let mut usdt_trade_symbols = select_record(&table_name, &column_name, &table_condition, &usdt_trades).await.unwrap();
|
|
|
|
// let mut low_price_1m_vec: Vec<OpcloData> = Vec::new();
|
|
// let mut low_price_1m_avg = 0.0;
|
|
// let mut low_price_30m_vec: Vec<OpcloData> = Vec::new();
|
|
// let mut low_price_30m_avg = 0.0;
|
|
|
|
// // 2. 1st filtering symbols: candle 1m price avg < candle 30m price avg
|
|
// let mut filtered_1st_symbols: Vec<String> = Vec::new();
|
|
// for element in usdt_trade_symbols {
|
|
// // initialize avgs
|
|
// low_price_1m_avg = 0.0;
|
|
// low_price_30m_avg = 0.0;
|
|
|
|
// // read 1m csv file
|
|
// low_price_1m_vec = read_low_price_into_vector("1m", &element.symbol).await?;
|
|
|
|
// // calculate opclo 1m price average
|
|
// for element in &low_price_1m_vec {
|
|
// low_price_1m_avg += element.price;
|
|
// }
|
|
// low_price_1m_avg /= low_price_1m_vec.len() as f64;
|
|
|
|
// // read 30m csv file
|
|
// low_price_30m_vec = read_low_price_into_vector("30m", &element.symbol).await?;
|
|
|
|
// // calculate opclo 30m price average
|
|
// for element in &low_price_30m_vec {
|
|
// low_price_30m_avg += element.price;
|
|
// }
|
|
// low_price_30m_avg /= low_price_30m_vec.len() as f64;
|
|
|
|
// // campare both prices
|
|
// if low_price_1m_avg < low_price_30m_avg {
|
|
// filtered_1st_symbols.push(element.symbol);
|
|
// }
|
|
// }
|
|
|
|
// let mut read_bb_vec: Vec<BBData> = Vec::new();
|
|
// let mut filtered_2nd_symbols: Vec<(String, u64)> = Vec::new(); // (symbol, closetime)
|
|
|
|
// // 3. 2nd filtering symbols: lower band in bollingerband of sma30 > candle 30m price
|
|
// for element in filtered_1st_symbols {
|
|
|
|
// // read 30m csv file
|
|
// low_price_30m_vec = read_low_price_into_vector("30m", &element).await?;
|
|
|
|
// // read bollingerband sma30 csv file
|
|
// read_bb_vec = read_bb_into_vector("sma30", "30m", &element).await?;
|
|
|
|
// // 2nd filtering symbols
|
|
// low_price_30m_vec.pop();
|
|
// let result = read_bb_vec.binary_search_by_key(&low_price_30m_vec.last().unwrap().server_epoch, |&BBData{ma_price, upperband, lowerband, server_epoch}|server_epoch);
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if read_bb_vec[T].lowerband > low_price_30m_vec.last().unwrap().price {
|
|
// filtered_2nd_symbols.push((element, read_bb_vec[T].server_epoch));
|
|
// }
|
|
// },
|
|
// Err(E) => {}
|
|
// }
|
|
|
|
// }
|
|
|
|
// let mut sma30_30m_vec: Vec<MaData> = Vec::new();
|
|
// let mut rsi30_vec: Vec<RsiData> = Vec::new();
|
|
// let mut filtered_3rd_symbols: Vec<(String, u64)> = Vec::new(); // (symbol, closetime)
|
|
|
|
// // 4. 3rd filtering symbols: check if the middle sample among 5 sample from the latest price of SMA30 is the lowest price and then check if RSI30 is lower than 0.3 of the middle sample
|
|
// for element in filtered_2nd_symbols {
|
|
|
|
// // read 30m csv file
|
|
// low_price_30m_vec = read_low_price_into_vector("30m", &element.0).await?;
|
|
// low_price_30m_vec.pop();
|
|
// low_price_30m_vec.reverse();
|
|
// low_price_30m_vec.truncate(5);
|
|
|
|
// // read SMA30 csv file
|
|
// sma30_30m_vec = read_ma_into_vector(&MA::Sma, 30, "30m", &element.0).await?;
|
|
|
|
// // read rsi30 csv file
|
|
// rsi30_vec = read_rsi_into_vector(30, "30m", &element.0).await?;
|
|
|
|
// if low_price_30m_vec.len() == 5 {
|
|
|
|
// // 2nd filtering symbols
|
|
// let result = sma30_30m_vec.binary_search_by_key(&low_price_30m_vec.first().unwrap().server_epoch, |MaData{price, server_epoch}| *server_epoch);
|
|
// match result {
|
|
// Ok(T) => {
|
|
|
|
// if sma30_30m_vec[T].price > low_price_30m_vec[0].price {
|
|
|
|
// let index_of_min: Option<usize> = low_price_30m_vec
|
|
// .iter()
|
|
// .enumerate()
|
|
// .min_by(|(_, a), (_, b)| a.price.partial_cmp(&b.price).expect("Nan was forbidden."))
|
|
// .map(|(index, _)| index);
|
|
|
|
// // index 1 means the middle index of 5 element in a vec, assuming the latest price is included but removed in the vec.
|
|
// if index_of_min == Some(1) {
|
|
// let result = rsi30_vec.binary_search_by_key(&low_price_30m_vec[1].server_epoch, |&RsiData{rsi_value, server_epoch}|server_epoch);
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if rsi30_vec[T].rsi_value < 0.25 {
|
|
// filtered_3rd_symbols.push((element.0, low_price_30m_vec.first().unwrap().server_epoch));
|
|
// }
|
|
// },
|
|
// Err(e) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// },
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 4. insert record into [pre_suggested_coin_list]
|
|
// insert_pre_suggested_coins(8, &filtered_3rd_symbols).await;
|
|
|
|
// println!("strategist_008 완료");
|
|
// Ok(())
|
|
// }
|
|
|
|
// pub async fn strategist_009 () -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|
// // [strategist_009 procedure]
|
|
// // 1. retrieve all usdttrade symbols
|
|
// // 2. 1st filtering symbols (opclo_30m price avg < opclo_1d price avg)
|
|
// // 3. 2nd filtering symbols (check if the middle sample among 5 sample from the latest price is the lowest price and then check if RSI3 and RSI10 are lower than 0.15 and 0.3 respectively of the middle sample)
|
|
// // 4. insert or update record into [strategist_001_table]
|
|
// // 5. if symbol's 30m price is over bb_sma30_30m lowerband, move the record from [strategist_001_table] to [suggested_coin_list]
|
|
|
|
// // 1. retrieve all usdttrade symbols
|
|
// #[derive(Debug, FromRow)]
|
|
// struct UsdtTrades {
|
|
// symbol: String,
|
|
// }
|
|
// let mut usdt_trades = UsdtTrades { symbol: String::new() };
|
|
|
|
// let table_name = String::from("valid_usdt_trades");
|
|
// let column_name = String::from("symbol");
|
|
// let table_condition = None;
|
|
// let mut usdt_trade_symbols = select_record(&table_name, &column_name, &table_condition, &usdt_trades).await.unwrap();
|
|
|
|
// let mut opclo_30m_vec: Vec<OpcloData> = Vec::new();
|
|
// let mut opclo_30m_price_avg = 0.0;
|
|
// let mut opclo_1d_vec: Vec<OpcloData> = Vec::new();
|
|
// let mut opclo_1d_price_avg = 0.0;
|
|
|
|
// // 2. 1st filtering symbols: candle 30m price avg < candle 1d price avg
|
|
// let mut filtered_1st_symbols: Vec<String> = Vec::new();
|
|
// for element in usdt_trade_symbols {
|
|
// // initialize avgs
|
|
// opclo_30m_price_avg = 0.0;
|
|
// opclo_1d_price_avg = 0.0;
|
|
|
|
// // read 1m csv file
|
|
// opclo_30m_vec = read_opclo_into_vector("30m", &element.symbol).await?;
|
|
|
|
// // calculate opclo 1m price average
|
|
// for element in &opclo_30m_vec {
|
|
// opclo_30m_price_avg += element.price;
|
|
// }
|
|
// opclo_30m_price_avg /= opclo_30m_vec.len() as f64;
|
|
|
|
// // read 30m csv file
|
|
// opclo_1d_vec = read_opclo_into_vector("1d", &element.symbol).await?;
|
|
|
|
// // calculate opclo 30m price average
|
|
// for element in &opclo_1d_vec {
|
|
// opclo_1d_price_avg += element.price;
|
|
// }
|
|
// opclo_1d_price_avg /= opclo_1d_vec.len() as f64;
|
|
|
|
// // campare both prices
|
|
// if opclo_30m_price_avg < opclo_1d_price_avg {
|
|
// filtered_1st_symbols.push(element.symbol);
|
|
// }
|
|
// }
|
|
|
|
// let mut rsi3_vec: Vec<RsiData> = Vec::new();
|
|
// let mut rsi10_vec: Vec<RsiData> = Vec::new();
|
|
// let mut filtered_2nd_symbols: Vec<(String, u64)> = Vec::new(); // (symbol, closetime)
|
|
|
|
// // 3. 2nd filtering symbols: check if the middle sample among 5 sample from the latest price is the lowest price and then check if RSI3 and RSI10 are lower than 0.15 and 0.3 respectively of the middle sample
|
|
// for element in filtered_1st_symbols {
|
|
|
|
// rsi3_vec.clear();
|
|
// rsi10_vec.clear();
|
|
// // read rsi3 csv file
|
|
// rsi3_vec = read_rsi_into_vector(3, "30m", &element).await?;
|
|
// // read rsi10 csv file
|
|
// rsi10_vec = read_rsi_into_vector(10, "30m", &element).await?;
|
|
|
|
// if rsi3_vec.len() >= 2 && rsi10_vec.len() >= 2 {
|
|
// if rsi3_vec.last().unwrap().rsi_value < 0.15 && rsi10_vec.last().unwrap().rsi_value < 0.30 {
|
|
// filtered_2nd_symbols.push((element, opclo_30m_vec.first().unwrap().server_epoch));
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 4. insert record into [pre_suggested_coin_list]
|
|
// insert_pre_suggested_coins(9, &filtered_2nd_symbols).await;
|
|
|
|
// println!("strategist_009 완료");
|
|
// Ok(())
|
|
// }
|
|
|
|
// pub async fn strategist_010 () -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|
// // [strategist_010 procedure]
|
|
// // 1. retrieve all usdttrade symbols
|
|
// // 2. 1st filtering symbols (opclo_30m price avg < opclo_1d price avg)
|
|
// // 3. 2nd filtering symbols (candle 30m low price at the previous candle < bb_sma30_30m lowerband)
|
|
// // 4. 3rd filtering symbols (check if the middle sample among 5 sample from the latest price is the lowest price and then check if RSI3 and RSI10 are lower than 0.15 and 0.3 respectively of the middle sample)
|
|
// // 5. insert or update record into [strategist_001_table]
|
|
// // 6. if symbol's 30m price is over bb_sma30_30m lowerband, move the record from [strategist_001_table] to [suggested_coin_list]
|
|
|
|
// let instant = Instant::now();
|
|
|
|
// // 1. retrieve all usdttrade symbols
|
|
// #[derive(Debug, FromRow)]
|
|
// struct UsdtTrades {
|
|
// symbol: String,
|
|
// }
|
|
// let mut usdt_trades = UsdtTrades { symbol: String::new() };
|
|
|
|
// let table_name = String::from("valid_usdt_trades");
|
|
// let column_name = String::from("symbol");
|
|
// let table_condition = None;
|
|
// let mut usdt_trade_symbols = select_record(&table_name, &column_name, &table_condition, &usdt_trades).await.unwrap();
|
|
|
|
// let mut opclo_30m_vec: Vec<OpcloData> = Vec::new();
|
|
// let mut opclo_30m_price_avg = 0.0;
|
|
// let mut opclo_1d_vec: Vec<OpcloData> = Vec::new();
|
|
// let mut opclo_1d_price_avg = 0.0;
|
|
|
|
// // 2. 1st filtering symbols: candle 30m price avg < candle 1d price avg
|
|
// let mut filtered_1st_symbols: Vec<String> = Vec::new();
|
|
// for element in usdt_trade_symbols {
|
|
// // initialize avgs
|
|
// opclo_30m_price_avg = 0.0;
|
|
// opclo_1d_price_avg = 0.0;
|
|
|
|
// //
|
|
// let opclo_30m_result = read_opclo_into_vector("30m", &element.symbol).await;
|
|
// let opclo_1d_result = read_opclo_into_vector("1d", &element.symbol).await;
|
|
|
|
// // read opclo_30m and 1d csv file
|
|
// if opclo_30m_result.is_ok() && opclo_1d_result.is_ok() {
|
|
// opclo_30m_vec = opclo_30m_result.unwrap();
|
|
// opclo_1d_vec = opclo_1d_result.unwrap();
|
|
|
|
// if opclo_30m_vec.len() > 4 && opclo_1d_vec.len() > 7 {
|
|
// opclo_1d_vec.reverse();
|
|
// opclo_1d_vec.split_off(7);
|
|
// opclo_30m_vec.reverse();
|
|
// opclo_1d_vec.split_off(4);
|
|
|
|
// // calculate opclo 1m price average
|
|
// for element in &opclo_30m_vec {
|
|
// opclo_30m_price_avg += element.price;
|
|
// }
|
|
// opclo_30m_price_avg /= opclo_30m_vec.len() as f64;
|
|
|
|
// // calculate opclo 30m price average
|
|
// for element in &opclo_1d_vec {
|
|
// opclo_1d_price_avg += element.price;
|
|
// }
|
|
// opclo_1d_price_avg /= opclo_1d_vec.len() as f64;
|
|
|
|
// // campare both prices
|
|
// if opclo_30m_price_avg < opclo_1d_price_avg {
|
|
// filtered_1st_symbols.push(element.symbol);
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 4. 3rd filtering symbols: yesterday 1d RSI 3 < 10, 1d RSI 10 < 15
|
|
// let mut rsi3_vec: Vec<RsiData> = Vec::new();
|
|
// let mut rsi10_vec: Vec<RsiData> = Vec::new();
|
|
// let mut filtered_2nd_symbols: Vec<String> = Vec::new();
|
|
// for element in filtered_1st_symbols {
|
|
|
|
// rsi3_vec.clear();
|
|
// rsi10_vec.clear();
|
|
|
|
// let rsi3_result = read_rsi_into_vector(3, "1d", &element).await;
|
|
// let rsi10_result = read_rsi_into_vector(10, "1d", &element).await;
|
|
|
|
// // read rsi3 csv file & rsi10 csv file
|
|
// if rsi3_result.is_ok() & rsi10_result.is_ok() {
|
|
// rsi3_vec = rsi3_result.unwrap();
|
|
// rsi10_vec = rsi10_result.unwrap();
|
|
|
|
// if rsi3_vec.len() > 1 && rsi10_vec.len() > 1 {
|
|
// rsi3_vec.pop();
|
|
// rsi10_vec.pop();
|
|
// if rsi3_vec.last().unwrap().rsi_value < 0.10 && rsi10_vec.last().unwrap().rsi_value < 0.15 {
|
|
// filtered_2nd_symbols.push(element);
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 3. 2nd filtering symbols: lower band in bollingerband of sma30 > candle 30m low price
|
|
// let mut read_bb_vec: Vec<BBData> = Vec::new();
|
|
// let mut filtered_3rd_symbols: Vec<String> = Vec::new();
|
|
// for element in filtered_2nd_symbols {
|
|
|
|
// let opclo_30m_result = read_low_price_into_vector("30m", &element).await;
|
|
// let read_bb_result = read_bb_into_vector("sma30", "30m", &element).await;
|
|
|
|
// // read 30m csv file && bollingerband sma30 csv file
|
|
// if opclo_30m_result.is_ok() && read_bb_result.is_ok() {
|
|
// opclo_30m_vec = opclo_30m_result.unwrap();
|
|
// read_bb_vec = read_bb_result.unwrap();
|
|
|
|
// if opclo_30m_vec.len() > 1 && read_bb_vec.len() > 1 {
|
|
// // 2nd filtering symbols
|
|
// opclo_30m_vec.pop();
|
|
// let result = read_bb_vec.binary_search_by_key(&opclo_30m_vec.last().unwrap().server_epoch, |&BBData{ma_price, upperband, lowerband, server_epoch}|server_epoch);
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if read_bb_vec[T].lowerband > opclo_30m_vec.last().unwrap().price {
|
|
// filtered_3rd_symbols.push(element);
|
|
// }
|
|
// },
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// let mut rsi3_vec: Vec<RsiData> = Vec::new();
|
|
// let mut rsi10_vec: Vec<RsiData> = Vec::new();
|
|
// let mut filtered_4th_symbols: Vec<(String, u64)> = Vec::new(); // (symbol, closetime)
|
|
|
|
// // 3. 3rd filtering symbols: check if the middle sample among 5 sample from the latest price is the lowest price and then check if RSI3 and RSI10 are lower than 0.15 and 0.3 respectively of the middle sample
|
|
// for element in filtered_3rd_symbols {
|
|
|
|
// rsi3_vec.clear();
|
|
// rsi10_vec.clear();
|
|
|
|
// let opclo_30m_result = read_low_price_into_vector("30m", &element).await;
|
|
// let rsi3_result = read_rsi_into_vector(3, "30m", &element).await;
|
|
// let rsi10_result = read_rsi_into_vector(10, "30m", &element).await;
|
|
|
|
// // read rsi3 csv file & rsi10 csv file
|
|
// if rsi3_result.is_ok() && rsi10_result.is_ok() && opclo_30m_result.is_ok() {
|
|
// rsi3_vec = rsi3_result.unwrap();
|
|
// rsi10_vec = rsi10_result.unwrap();
|
|
// opclo_30m_vec = opclo_30m_result.unwrap();
|
|
|
|
// if rsi3_vec.len() > 1 && rsi10_vec.len() > 1 {
|
|
// if rsi3_vec.last().unwrap().rsi_value < 0.15 && rsi10_vec.last().unwrap().rsi_value < 0.20 {
|
|
// filtered_4th_symbols.push((element, opclo_30m_vec.last().unwrap().server_epoch));
|
|
// }
|
|
// }
|
|
|
|
// }
|
|
// }
|
|
|
|
// // 4. insert record into [pre_suggested_coin_list]
|
|
// insert_pre_suggested_coins(10, &filtered_4th_symbols).await;
|
|
|
|
// if instant.elapsed().as_millis() < 50 {
|
|
// sleep(Duration::from_millis(50)).await;
|
|
// }
|
|
// // println!("strategist_010 완료");
|
|
// Ok(())
|
|
// }
|
|
|
|
// pub async fn strategist_011 () -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|
// // [strategist_011 procedure]
|
|
// // 1. retrieve all usdttrade symbols
|
|
// // 2. 1st filtering symbols (opclo_1m price avg < opclo_30m price avg)
|
|
// // 3. 2nd filtering symbols (candle 30m low price at the previous candle < bb_sma30_30m lowerband)
|
|
// // 4. 3rd filtering symbols (check if the middle sample among 5 sample from the latest price is the lowest price and then check if RSI3 and RSI10 are lower than 0.15 and 0.3 respectively of the middle sample)
|
|
// // 5. insert or update record into [strategist_001_table]
|
|
// // 6. if symbol's 30m price is over bb_sma30_30m lowerband, move the record from [strategist_001_table] to [suggested_coin_list]
|
|
|
|
// let instant = Instant::now();
|
|
|
|
// // 1. retrieve all usdttrade symbols
|
|
// #[derive(Debug, FromRow)]
|
|
// struct UsdtTrades {
|
|
// symbol: String,
|
|
// }
|
|
// let mut usdt_trades = UsdtTrades { symbol: String::new() };
|
|
|
|
// let table_name = String::from("valid_usdt_trades");
|
|
// let column_name = String::from("symbol");
|
|
// let table_condition = None;
|
|
// let mut usdt_trade_symbols = select_record(&table_name, &column_name, &table_condition, &usdt_trades).await.unwrap();
|
|
|
|
// let mut opclo_1m_vec: Vec<OpcloData> = Vec::new();
|
|
// let mut opclo_1m_price_avg = 0.0;
|
|
// let mut opclo_30m_vec: Vec<OpcloData> = Vec::new();
|
|
// let mut opclo_30m_price_avg = 0.0;
|
|
|
|
// // 2. 1st filtering symbols: candle 1m price avg < candle 30m price avg
|
|
// let mut filtered_1st_symbols: Vec<String> = Vec::new();
|
|
// for element in usdt_trade_symbols {
|
|
// // initialize avgs
|
|
// opclo_1m_price_avg = 0.0;
|
|
// opclo_30m_price_avg = 0.0;
|
|
|
|
// let opclo_1m_result = read_opclo_into_vector("1m", &element.symbol).await;
|
|
// let opclo_30m_result = read_opclo_into_vector("30m", &element.symbol).await;
|
|
|
|
// if opclo_1m_result.is_ok() && opclo_30m_result.is_ok() {
|
|
// opclo_1m_vec = opclo_1m_result.unwrap();
|
|
// opclo_30m_vec = opclo_30m_result.unwrap();
|
|
|
|
// if opclo_1m_vec.len() > 1 && opclo_30m_vec.len() > 1 {
|
|
// // calculate opclo 1m price average
|
|
// for element in &opclo_1m_vec {
|
|
// opclo_1m_price_avg += element.price;
|
|
// }
|
|
// opclo_1m_price_avg /= opclo_1m_vec.len() as f64;
|
|
|
|
// // calculate opclo 30m price average
|
|
// for element in &opclo_30m_vec {
|
|
// opclo_30m_price_avg += element.price;
|
|
// }
|
|
// opclo_30m_price_avg /= opclo_30m_vec.len() as f64;
|
|
|
|
// // campare both prices
|
|
// if opclo_1m_price_avg < opclo_30m_price_avg {
|
|
// filtered_1st_symbols.push(element.symbol);
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 3. 2nd filtering symbols: lower band in bollingerband of sma30 > candle 30m low price
|
|
// let mut read_bb_vec: Vec<BBData> = Vec::new();
|
|
// let mut filtered_2nd_symbols: Vec<String> = Vec::new();
|
|
// for element in filtered_1st_symbols {
|
|
|
|
// let opclo_30m_result = read_low_price_into_vector("30m", &element).await;
|
|
// let read_bb_result = read_bb_into_vector("sma30", "30m", &element).await;
|
|
|
|
// // read 30m csv file & bollingerband sma30 csv file
|
|
// if opclo_30m_result.is_ok() && read_bb_result.is_ok() {
|
|
// opclo_30m_vec = opclo_30m_result.unwrap();
|
|
// read_bb_vec = read_bb_result.unwrap();
|
|
|
|
// if opclo_30m_vec.len() > 1 && read_bb_vec.len() > 1
|
|
// {
|
|
// // 2nd filtering symbols
|
|
// opclo_30m_vec.pop();
|
|
// let result = read_bb_vec.binary_search_by_key(&opclo_30m_vec.last().unwrap().server_epoch, |&BBData{ma_price, upperband, lowerband, server_epoch}|server_epoch);
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if read_bb_vec[T].lowerband > opclo_30m_vec.last().unwrap().price {
|
|
// filtered_2nd_symbols.push(element);
|
|
// }
|
|
// },
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// let mut rsi3_vec: Vec<RsiData> = Vec::new();
|
|
// let mut rsi10_vec: Vec<RsiData> = Vec::new();
|
|
// let mut filtered_3rd_symbols: Vec<(String, u64)> = Vec::new(); // (symbol, closetime)
|
|
|
|
// // 3. 3rd filtering symbols: check if the middle sample among 5 sample from the latest price is the lowest price and then check if RSI3 and RSI10 are lower than 0.15 and 0.3 respectively of the middle sample
|
|
// for element in filtered_2nd_symbols {
|
|
|
|
// rsi3_vec.clear();
|
|
// rsi10_vec.clear();
|
|
|
|
// let rsi3_result = read_rsi_into_vector(3, "30m", &element).await;
|
|
// let rsi10_result = read_rsi_into_vector(10, "30m", &element).await;
|
|
|
|
// if rsi3_result.is_ok() && rsi10_result.is_ok() {
|
|
// rsi3_vec = rsi3_result.unwrap();
|
|
// rsi10_vec = rsi10_result.unwrap();
|
|
|
|
// if rsi3_vec.len() > 1 && rsi10_vec.len() > 1 {
|
|
// if rsi3_vec.last().unwrap().rsi_value < 0.15 && rsi10_vec.last().unwrap().rsi_value < 0.20 {
|
|
// filtered_3rd_symbols.push((element, opclo_30m_vec.first().unwrap().server_epoch));
|
|
// }
|
|
// }
|
|
|
|
// }
|
|
// }
|
|
|
|
// // 4. insert record into [pre_suggested_coin_list]
|
|
// insert_pre_suggested_coins(11, &filtered_3rd_symbols).await;
|
|
|
|
// if instant.elapsed().as_millis() < 50 {
|
|
// sleep(Duration::from_millis(50)).await;
|
|
// }
|
|
|
|
// // println!("strategist_011 완료");
|
|
// Ok(())
|
|
// }
|
|
|
|
// pub async fn strategist_012 () -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|
// // [strategist_010 procedure]
|
|
// // 1. retrieve all usdttrade symbols
|
|
// // 2. 1st filtering symbols (opclo_30m price avg < opclo_1d price avg)
|
|
// // 3. 2nd filtering symbols (candle 30m low price at the previous candle < bb_sma30_30m lowerband)
|
|
// // 4. 3rd filtering symbols (check if the middle sample among 5 sample from the latest price is the lowest price and then check if RSI3 and RSI10 are lower than 0.15 and 0.3 respectively of the middle sample)
|
|
// // 5. insert or update record into [strategist_001_table]
|
|
// // 6. if symbol's 30m price is over bb_sma30_30m lowerband, move the record from [strategist_001_table] to [suggested_coin_list]
|
|
|
|
// let instant = Instant::now();
|
|
|
|
// // 1. retrieve all usdttrade symbols
|
|
// #[derive(Debug, FromRow)]
|
|
// struct UsdtTrades {
|
|
// symbol: String,
|
|
// }
|
|
// let mut usdt_trades = UsdtTrades { symbol: String::new() };
|
|
|
|
// let table_name = String::from("valid_usdt_trades");
|
|
// let column_name = String::from("symbol");
|
|
// let table_condition = None;
|
|
// let mut usdt_trade_symbols = select_record(&table_name, &column_name, &table_condition, &usdt_trades).await.unwrap();
|
|
|
|
// let mut opclo_30m_vec: Vec<OpcloData> = Vec::new();
|
|
// let mut opclo_30m_price_avg = 0.0;
|
|
// let mut opclo_1d_vec: Vec<OpcloData> = Vec::new();
|
|
// let mut opclo_1d_price_avg = 0.0;
|
|
|
|
// // 2. 1st filtering symbols: candle 30m price avg < candle 1d price avg
|
|
// let mut filtered_1st_symbols: Vec<String> = Vec::new();
|
|
// for element in usdt_trade_symbols {
|
|
// // initialize avgs
|
|
// opclo_30m_price_avg = 0.0;
|
|
// opclo_1d_price_avg = 0.0;
|
|
|
|
// let opclo_30m_result = read_opclo_into_vector("30m", &element.symbol).await;
|
|
// let opclo_1d_result = read_opclo_into_vector("1d", &element.symbol).await;
|
|
|
|
// // read 30m csv file & read 1d csv file
|
|
// if opclo_30m_result.is_ok() && opclo_1d_result.is_ok() {
|
|
// opclo_30m_vec = opclo_30m_result.unwrap();
|
|
// opclo_1d_vec = opclo_1d_result.unwrap();
|
|
|
|
// if opclo_30m_vec.len() > 1 && opclo_1d_vec.len() > 1 {
|
|
// // calculate opclo 1m price average
|
|
// for element in &opclo_30m_vec {
|
|
// opclo_30m_price_avg += element.price;
|
|
// }
|
|
// opclo_30m_price_avg /= opclo_30m_vec.len() as f64;
|
|
|
|
// // calculate opclo 30m price average
|
|
// for element in &opclo_1d_vec {
|
|
// opclo_1d_price_avg += element.price;
|
|
// }
|
|
// opclo_1d_price_avg /= opclo_1d_vec.len() as f64;
|
|
|
|
// // campare both prices
|
|
// if opclo_30m_price_avg < (opclo_1d_price_avg/4.0) {
|
|
// filtered_1st_symbols.push(element.symbol);
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// let mut opclo_30m_vec: Vec<OpcloData> = Vec::new();
|
|
// // 3. 2nd filtering symbols: lower band in bollingerband of sma30 > candle 30m low price
|
|
// let mut read_bb_vec: Vec<BBData> = Vec::new();
|
|
// let mut filtered_2nd_symbols: Vec<String> = Vec::new();
|
|
// for element in filtered_1st_symbols {
|
|
|
|
// let opclo_30m_result = read_low_price_into_vector("30m", &element).await;
|
|
// let read_bb_result = read_bb_into_vector("sma30", "30m", &element).await;
|
|
|
|
// // read 1m csv file & bollingerband sma30 csv file
|
|
// if opclo_30m_result.is_ok() & read_bb_result.is_ok() {
|
|
// opclo_30m_vec = opclo_30m_result.unwrap();
|
|
// read_bb_vec = read_bb_result.unwrap();
|
|
|
|
// if opclo_30m_vec.len() > 1 && read_bb_vec.len() > 1 {
|
|
// // 2nd filtering symbols
|
|
// let result = read_bb_vec.binary_search_by_key(&opclo_30m_vec.last().unwrap().server_epoch, |&BBData{ma_price, upperband, lowerband, server_epoch}|server_epoch);
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if read_bb_vec[T].lowerband > opclo_30m_vec.last().unwrap().price {
|
|
// filtered_2nd_symbols.push(element);
|
|
// }
|
|
// },
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// let mut opclo_1m_vec: Vec<OpcloData> = Vec::new();
|
|
// let mut opclo_1m_price_avg = 0.0;
|
|
// let mut opclo_30m_vec: Vec<OpcloData> = Vec::new();
|
|
// let mut opclo_30m_price_avg = 0.0;
|
|
// let mut filtered_3rd_symbols: Vec<String> = Vec::new();
|
|
// for element in filtered_2nd_symbols {
|
|
// // initialize avgs
|
|
// opclo_1m_price_avg = 0.0;
|
|
// opclo_30m_price_avg = 0.0;
|
|
|
|
// let opclo_1m_result = read_opclo_into_vector("1m", &element).await;
|
|
// let opclo_30m_result = read_opclo_into_vector("30m", &element).await;
|
|
|
|
// if opclo_1m_result.is_ok() && opclo_30m_result.is_ok() {
|
|
// opclo_1m_vec = opclo_1m_result.unwrap();
|
|
// opclo_30m_vec = opclo_30m_result.unwrap();
|
|
|
|
// if opclo_1m_vec.len() > 10 && opclo_30m_vec.len() > 4 {
|
|
// opclo_1m_vec.reverse();
|
|
// opclo_1m_vec.split_off(10);
|
|
// opclo_30m_vec.reverse();
|
|
// opclo_30m_vec.split_off(4);
|
|
|
|
// // calculate opclo 1m price average
|
|
// for element in &opclo_1m_vec {
|
|
// opclo_1m_price_avg += element.price;
|
|
// }
|
|
// opclo_1m_price_avg /= opclo_1m_vec.len() as f64;
|
|
|
|
// // calculate opclo 30m price average
|
|
// for element in &opclo_30m_vec {
|
|
// opclo_30m_price_avg += element.price;
|
|
// }
|
|
// opclo_30m_price_avg /= opclo_30m_vec.len() as f64;
|
|
|
|
// // campare both prices
|
|
// if opclo_1m_price_avg < (opclo_30m_price_avg*0.99) {
|
|
// filtered_3rd_symbols.push(element);
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// let mut rsi3_vec: Vec<RsiData> = Vec::new();
|
|
// let mut rsi10_vec: Vec<RsiData> = Vec::new();
|
|
// let mut filtered_4th_symbols: Vec<(String, u64)> = Vec::new(); // (symbol, closetime)
|
|
|
|
// // 3. 3rd filtering symbols: check if the middle sample among 5 sample from the latest price is the lowest price and then check if RSI3 and RSI10 are lower than 0.15 and 0.3 respectively of the middle sample
|
|
// for element in filtered_3rd_symbols {
|
|
|
|
// rsi3_vec.clear();
|
|
// rsi10_vec.clear();
|
|
|
|
// let rsi3_result = read_rsi_into_vector(3, "30m", &element).await;
|
|
// let rsi10_result = read_rsi_into_vector(10, "30m", &element).await;
|
|
|
|
// // read rsi3 csv file & rsi10 csv file
|
|
// if rsi3_result.is_ok() & rsi10_result.is_ok() {
|
|
// rsi3_vec = rsi3_result.unwrap();
|
|
// rsi10_vec = rsi10_result.unwrap();
|
|
|
|
// if rsi3_vec.len() > 1 && rsi10_vec.len() > 1 {
|
|
// if rsi3_vec.last().unwrap().rsi_value < 0.10 && rsi10_vec.last().unwrap().rsi_value < 0.10 {
|
|
// filtered_4th_symbols.push((element, opclo_30m_vec.first().unwrap().server_epoch));
|
|
// }
|
|
// }
|
|
|
|
// }
|
|
// }
|
|
|
|
// // 4. insert record into [pre_suggested_coin_list]
|
|
// insert_pre_suggested_coins(12, &filtered_4th_symbols).await;
|
|
|
|
// if instant.elapsed().as_millis() < 50 {
|
|
// sleep(Duration::from_millis(50)).await;
|
|
// }
|
|
|
|
// // println!("strategist_012 완료");
|
|
// Ok(())
|
|
// }
|
|
|
|
// // original strategist 012
|
|
// // pub async fn strategist_012 () -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|
// // // [strategist_010 procedure]
|
|
// // // 1. retrieve all usdttrade symbols
|
|
// // // 2. 1st filtering symbols (opclo_30m price avg < opclo_1d price avg)
|
|
// // // 3. 2nd filtering symbols (candle 30m low price at the previous candle < bb_sma30_30m lowerband)
|
|
// // // 4. 3rd filtering symbols (check if the middle sample among 5 sample from the latest price is the lowest price and then check if RSI3 and RSI10 are lower than 0.15 and 0.3 respectively of the middle sample)
|
|
// // // 5. insert or update record into [strategist_001_table]
|
|
// // // 6. if symbol's 30m price is over bb_sma30_30m lowerband, move the record from [strategist_001_table] to [suggested_coin_list]
|
|
|
|
// // let instant = Instant::now();
|
|
|
|
// // // 1. retrieve all usdttrade symbols
|
|
// // #[derive(Debug, FromRow)]
|
|
// // struct UsdtTrades {
|
|
// // symbol: String,
|
|
// // }
|
|
// // let mut usdt_trades = UsdtTrades { symbol: String::new() };
|
|
|
|
// // let table_name = String::from("valid_usdt_trades");
|
|
// // let column_name = String::from("symbol");
|
|
// // let table_condition = None;
|
|
// // let mut usdt_trade_symbols = select_record(&table_name, &column_name, &table_condition, &usdt_trades).await.unwrap();
|
|
|
|
// // let mut opclo_30m_vec: Vec<OpcloData> = Vec::new();
|
|
// // let mut opclo_30m_price_avg = 0.0;
|
|
// // let mut opclo_1d_vec: Vec<OpcloData> = Vec::new();
|
|
// // let mut opclo_1d_price_avg = 0.0;
|
|
|
|
// // // 2. 1st filtering symbols: candle 30m price avg < candle 1d price avg
|
|
// // let mut filtered_1st_symbols: Vec<String> = Vec::new();
|
|
// // for element in usdt_trade_symbols {
|
|
// // // initialize avgs
|
|
// // opclo_30m_price_avg = 0.0;
|
|
// // opclo_1d_price_avg = 0.0;
|
|
|
|
// // let opclo_30m_result = read_opclo_into_vector("30m", &element.symbol).await;
|
|
// // let opclo_1d_result = read_opclo_into_vector("1d", &element.symbol).await;
|
|
|
|
// // // read 30m csv file & read 1d csv file
|
|
// // if opclo_30m_result.is_ok() && opclo_1d_result.is_ok() {
|
|
// // opclo_30m_vec = opclo_30m_result.unwrap();
|
|
// // opclo_1d_vec = opclo_1d_result.unwrap();
|
|
|
|
// // if opclo_30m_vec.len() > 1 && opclo_1d_vec.len() > 1 {
|
|
// // // calculate opclo 1m price average
|
|
// // for element in &opclo_30m_vec {
|
|
// // opclo_30m_price_avg += element.price;
|
|
// // }
|
|
// // opclo_30m_price_avg /= opclo_30m_vec.len() as f64;
|
|
|
|
// // // calculate opclo 30m price average
|
|
// // for element in &opclo_1d_vec {
|
|
// // opclo_1d_price_avg += element.price;
|
|
// // }
|
|
// // opclo_1d_price_avg /= opclo_1d_vec.len() as f64;
|
|
|
|
// // // campare both prices
|
|
// // if opclo_30m_price_avg < (opclo_1d_price_avg/3.0) {
|
|
// // filtered_1st_symbols.push(element.symbol);
|
|
// // }
|
|
// // }
|
|
// // }
|
|
// // }
|
|
|
|
// // let mut opclo_1m_vec: Vec<OpcloData> = Vec::new();
|
|
// // // 3. 2nd filtering symbols: lower band in bollingerband of sma30 > candle 30m low price
|
|
// // let mut read_bb_vec: Vec<BBData> = Vec::new();
|
|
// // let mut filtered_2nd_symbols: Vec<String> = Vec::new();
|
|
// // for element in filtered_1st_symbols {
|
|
|
|
// // let opclo_1m_result = read_low_price_into_vector("1m", &element).await;
|
|
// // let read_bb_result = read_bb_into_vector("sma30", "1m", &element).await;
|
|
|
|
// // // read 1m csv file & bollingerband sma30 csv file
|
|
// // if opclo_1m_result.is_ok() & read_bb_result.is_ok() {
|
|
// // opclo_1m_vec = opclo_1m_result.unwrap();
|
|
// // read_bb_vec = read_bb_result.unwrap();
|
|
|
|
// // if opclo_1m_vec.len() > 1 && read_bb_vec.len() > 1 {
|
|
// // // 2nd filtering symbols
|
|
// // let result = read_bb_vec.binary_search_by_key(&opclo_30m_vec.last().unwrap().server_epoch, |&BBData{ma_price, upperband, lowerband, server_epoch}|server_epoch);
|
|
// // match result {
|
|
// // Ok(T) => {
|
|
// // if read_bb_vec[T].lowerband > opclo_1m_vec.last().unwrap().price {
|
|
// // filtered_2nd_symbols.push(element);
|
|
// // }
|
|
// // },
|
|
// // Err(E) => {}
|
|
// // }
|
|
// // }
|
|
// // }
|
|
// // }
|
|
|
|
// // let mut rsi3_vec: Vec<RsiData> = Vec::new();
|
|
// // let mut rsi10_vec: Vec<RsiData> = Vec::new();
|
|
// // let mut filtered_3rd_symbols: Vec<(String, u64)> = Vec::new(); // (symbol, closetime)
|
|
|
|
// // // 3. 3rd filtering symbols: check if the middle sample among 5 sample from the latest price is the lowest price and then check if RSI3 and RSI10 are lower than 0.15 and 0.3 respectively of the middle sample
|
|
// // for element in filtered_2nd_symbols {
|
|
|
|
// // rsi3_vec.clear();
|
|
// // rsi10_vec.clear();
|
|
|
|
// // let rsi3_result = read_rsi_into_vector(3, "30m", &element).await;
|
|
// // let rsi10_result = read_rsi_into_vector(10, "30m", &element).await;
|
|
|
|
// // // read rsi3 csv file & rsi10 csv file
|
|
// // if rsi3_result.is_ok() & rsi10_result.is_ok() {
|
|
// // rsi3_vec = rsi3_result.unwrap();
|
|
// // rsi10_vec = rsi10_result.unwrap();
|
|
|
|
// // if rsi3_vec.len() > 1 && rsi10_vec.len() > 1 {
|
|
// // if rsi3_vec.last().unwrap().rsi_value < 0.15 && rsi10_vec.last().unwrap().rsi_value < 0.20 {
|
|
// // filtered_3rd_symbols.push((element, opclo_30m_vec.first().unwrap().server_epoch));
|
|
// // }
|
|
// // }
|
|
|
|
// // }
|
|
// // }
|
|
|
|
// // // 4. insert record into [pre_suggested_coin_list]
|
|
// // insert_pre_suggested_coins(12, &filtered_3rd_symbols).await;
|
|
|
|
// // if instant.elapsed().as_millis() < 50 {
|
|
// // sleep(Duration::from_millis(50)).await;
|
|
// // }
|
|
|
|
// // // println!("strategist_012 완료");
|
|
// // Ok(())
|
|
// // }
|
|
|
|
// pub async fn strategist_013 () -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|
// // [strategist_013 procedure]
|
|
// // 1. retrieve all usdttrade symbols
|
|
// // 2. 1st filtering symbols (the latest opclo_1d price avg < 20% of opclo_1d price avg two days before, the latest opclo_1d price avg < opclo_1d price avg a day before)
|
|
// // 3. 2nd filtering symbols (1d RSI3 and RSI10 are lower than 0.10)
|
|
// // 4. 3rd filtering symbols (candle 1d low price < 90% of bb_sma30_1d lowerband)
|
|
// // 5. 4th filtering symbols (30m RSI3 and RSI10 are lower than 0.10 abd 0.10 respectively)
|
|
// // 6. 5th filtering symbols (candle 30m low price < 99.5% of bb_sma30_30m lowerband)
|
|
|
|
// let instant = Instant::now();
|
|
|
|
// // 1. retrieve all usdttrade symbols
|
|
// #[derive(Debug, FromRow)]
|
|
// struct UsdtTrades {
|
|
// symbol: String,
|
|
// }
|
|
// let mut usdt_trades = UsdtTrades { symbol: String::new() };
|
|
|
|
// let table_name = String::from("valid_usdt_trades");
|
|
// let column_name = String::from("symbol");
|
|
// let table_condition = None;
|
|
// let mut usdt_trade_symbols = select_record(&table_name, &column_name, &table_condition, &usdt_trades).await.unwrap();
|
|
|
|
// // 2. 1st filtering symbols (the latest opclo_1d price avg < 90% of opclo_1d price avg two days before)
|
|
// let mut opclo_1d_vec: Vec<OpcloData> = Vec::new();
|
|
// let mut opclo_1d_latest_price = 0.0;
|
|
// let mut opclo_1d_1before_price = 0.0;
|
|
// let mut opclo_1d_2before_price = 0.0;
|
|
// let mut filtered_1st_symbols: Vec<String> = Vec::new();
|
|
// for element in usdt_trade_symbols {
|
|
// // initialize avgs
|
|
// opclo_1d_latest_price = 0.0;
|
|
// opclo_1d_1before_price = 0.0;
|
|
// opclo_1d_2before_price = 0.0;
|
|
|
|
// let opclo_1d_result = read_opclo_into_vector("1d", &element.symbol).await;
|
|
|
|
// // read 30m csv file & read 1d csv file
|
|
// if opclo_1d_result.is_ok() {
|
|
// opclo_1d_vec = opclo_1d_result.unwrap();
|
|
|
|
// if opclo_1d_vec.len() > 3 {
|
|
// // compare the lastest price and 20% of 2 days before price
|
|
// opclo_1d_vec.reverse();
|
|
// let mut iter = opclo_1d_vec.iter();
|
|
// opclo_1d_latest_price = iter.next().unwrap().price;
|
|
// opclo_1d_1before_price = iter.next().unwrap().price;
|
|
// opclo_1d_2before_price = iter.next().unwrap().price;
|
|
|
|
// // campare both prices
|
|
// if (opclo_1d_latest_price < opclo_1d_2before_price * 0.9) && (opclo_1d_latest_price < opclo_1d_1before_price * 0.95) {
|
|
// filtered_1st_symbols.push(element.symbol);
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 3. 2nd filtering symbols (1d RSI3 and RSI10 are lower than 0.10)
|
|
// let mut rsi3_vec: Vec<RsiData> = Vec::new();
|
|
// let mut rsi10_vec: Vec<RsiData> = Vec::new();
|
|
// let mut filtered_2nd_symbols: Vec<String> = Vec::new();
|
|
// for element in filtered_1st_symbols {
|
|
|
|
// rsi3_vec.clear();
|
|
// rsi10_vec.clear();
|
|
|
|
// let rsi3_result = read_rsi_into_vector(3, "1d", &element).await;
|
|
// let rsi10_result = read_rsi_into_vector(10, "1d", &element).await;
|
|
|
|
// // read rsi3 csv file & rsi10 csv file
|
|
// if rsi3_result.is_ok() & rsi10_result.is_ok() {
|
|
// rsi3_vec = rsi3_result.unwrap();
|
|
// rsi10_vec = rsi10_result.unwrap();
|
|
|
|
// if rsi3_vec.len() > 1 && rsi10_vec.len() > 1 {
|
|
// if rsi3_vec.last().unwrap().rsi_value < 0.10 && rsi10_vec.last().unwrap().rsi_value < 0.10 {
|
|
// filtered_2nd_symbols.push(element);
|
|
// }
|
|
// }
|
|
|
|
// }
|
|
// }
|
|
|
|
// // 4. 3rd filtering symbols (candle 1d low price < 90% of bb_sma30_1d lowerband)
|
|
// let mut opclo_30m_vec: Vec<OpcloData> = Vec::new();
|
|
// let mut read_bb_vec: Vec<BBData> = Vec::new();
|
|
// let mut filtered_3rd_symbols: Vec<String> = Vec::new();
|
|
// for element in filtered_2nd_symbols {
|
|
|
|
// let opclo_1d_result = read_low_price_into_vector("1d", &element).await;
|
|
// let read_bb_result = read_bb_into_vector("sma30", "1d", &element).await;
|
|
|
|
// // read 1d csv file & bollingerband sma30 csv file
|
|
// if opclo_1d_result.is_ok() & read_bb_result.is_ok() {
|
|
// opclo_30m_vec = opclo_1d_result.unwrap();
|
|
// read_bb_vec = read_bb_result.unwrap();
|
|
|
|
// if opclo_30m_vec.len() > 1 && read_bb_vec.len() > 1 {
|
|
// // 3rd filtering symbols
|
|
// let result = read_bb_vec.binary_search_by_key(&opclo_30m_vec.last().unwrap().server_epoch, |&BBData{ma_price, upperband, lowerband, server_epoch}|server_epoch);
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if read_bb_vec[T].lowerband * 0.9 > opclo_30m_vec.last().unwrap().price {
|
|
// filtered_3rd_symbols.push(element);
|
|
// }
|
|
// },
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 5. 4th filtering symbols (30m RSI3 and RSI10 are lower than 0.10 abd 0.10 respectively)
|
|
// let mut rsi3_vec: Vec<RsiData> = Vec::new();
|
|
// let mut rsi10_vec: Vec<RsiData> = Vec::new();
|
|
// let mut filtered_4th_symbols: Vec<String> = Vec::new();
|
|
// for element in filtered_3rd_symbols {
|
|
|
|
// rsi3_vec.clear();
|
|
// rsi10_vec.clear();
|
|
|
|
// let rsi3_result = read_rsi_into_vector(3, "30m", &element).await;
|
|
// let rsi10_result = read_rsi_into_vector(10, "30m", &element).await;
|
|
|
|
// // read rsi3 csv file & rsi10 csv file
|
|
// if rsi3_result.is_ok() & rsi10_result.is_ok() {
|
|
// rsi3_vec = rsi3_result.unwrap();
|
|
// rsi10_vec = rsi10_result.unwrap();
|
|
|
|
// if rsi3_vec.len() > 1 && rsi10_vec.len() > 1 {
|
|
// if rsi3_vec.last().unwrap().rsi_value < 0.10 && rsi10_vec.last().unwrap().rsi_value < 0.10 {
|
|
// filtered_4th_symbols.push(element);
|
|
// }
|
|
// }
|
|
|
|
// }
|
|
// }
|
|
|
|
// // 6. 5th filtering symbols (candle 30m low price < 99.5% of bb_sma30_30m lowerband)
|
|
// let mut opclo_30m_vec: Vec<OpcloData> = Vec::new();
|
|
// let mut read_bb_vec: Vec<BBData> = Vec::new();
|
|
// let mut filtered_5th_symbols: Vec<(String, u64)> = Vec::new(); // (symbol, closetime)
|
|
// for element in filtered_4th_symbols {
|
|
|
|
// let opclo_30m_result = read_low_price_into_vector("30m", &element).await;
|
|
// let read_bb_result = read_bb_into_vector("sma30", "30m", &element).await;
|
|
|
|
// // read 1d csv file & bollingerband sma30 csv file
|
|
// if opclo_30m_result.is_ok() & read_bb_result.is_ok() {
|
|
// opclo_30m_vec = opclo_30m_result.unwrap();
|
|
// read_bb_vec = read_bb_result.unwrap();
|
|
|
|
// if opclo_30m_vec.len() > 1 && read_bb_vec.len() > 1 {
|
|
// // 3rd filtering symbols
|
|
// let result = read_bb_vec.binary_search_by_key(&opclo_30m_vec.last().unwrap().server_epoch, |&BBData{ma_price, upperband, lowerband, server_epoch}|server_epoch);
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if read_bb_vec[T].lowerband * 0.995 > opclo_30m_vec.last().unwrap().price {
|
|
// filtered_5th_symbols.push((element, opclo_30m_vec.last().unwrap().server_epoch));
|
|
// }
|
|
// },
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 4. insert record into [pre_suggested_coin_list]
|
|
// insert_pre_suggested_coins(13, &filtered_5th_symbols).await;
|
|
|
|
// if instant.elapsed().as_millis() < 50 {
|
|
// sleep(Duration::from_millis(50)).await;
|
|
// }
|
|
|
|
// // println!("strategist_013 완료");
|
|
// Ok(())
|
|
// }
|
|
|
|
// pub async fn strategist_014 () -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|
// // [strategist_014 procedure]
|
|
// // 1. retrieve all usdttrade symbols
|
|
// // 2. 1st filtering symbols: candle 1d price yesterday avg < 80% of candle 1d opclo price latest 7 days avg
|
|
// // 3. 2nd filtering symbols: 85% of BB SMA10 MA price > candle 1d price yesterday avg
|
|
// // 4. 3rd filtering symbols: yesterday 1d RSI 3 < 10, 1d RSI 10 < 15
|
|
// // 5. 4th filtering symbols: avg between yesterday 1d opclo price and yesterday low price> latest 30m opclo price
|
|
// // 6. 5th filtering symbols: 30m RSI 3 < 10, 30m RSI 10 < 15
|
|
// // 7. insert record into [pre_suggested_coin_list]
|
|
|
|
// let instant = Instant::now();
|
|
|
|
// // 1. retrieve all usdttrade symbols
|
|
// #[derive(Debug, FromRow)]
|
|
// struct UsdtTrades {
|
|
// symbol: String,
|
|
// }
|
|
// let mut usdt_trades = UsdtTrades { symbol: String::new() };
|
|
|
|
// let table_name = String::from("valid_usdt_trades");
|
|
// let column_name = String::from("symbol");
|
|
// let table_condition = None;
|
|
// let mut usdt_trade_symbols = select_record(&table_name, &column_name, &table_condition, &usdt_trades).await.unwrap();
|
|
|
|
// // 2. 1st filtering symbols: candle 1d price yesterday avg < 80% of candle 1d opclo price latest 7 days avg
|
|
// let mut opclo_1d_vec: Vec<OpcloData> = Vec::new();
|
|
// let mut opclo_1d_price_7days_avg = 0.0;
|
|
// let mut filtered_1st_symbols: Vec<String> = Vec::new();
|
|
// for element in usdt_trade_symbols {
|
|
// // initialize avgs
|
|
// opclo_1d_price_7days_avg = 0.0;
|
|
|
|
// let opclo_1d_result = read_opclo_into_vector("1d", &element.symbol).await;
|
|
|
|
// // read 1d csv file
|
|
// if opclo_1d_result.is_ok() {
|
|
|
|
// opclo_1d_vec = opclo_1d_result.unwrap();
|
|
|
|
// if opclo_1d_vec.len() >= 8 {
|
|
// opclo_1d_vec.pop();
|
|
// opclo_1d_vec.reverse();
|
|
|
|
// opclo_1d_vec.split_off(7);
|
|
|
|
// // calculate opclo 1d price average
|
|
// for element in &opclo_1d_vec {
|
|
// opclo_1d_price_7days_avg += element.price;
|
|
// }
|
|
// opclo_1d_price_7days_avg /= opclo_1d_vec.len() as f64;
|
|
|
|
// // campare the yesterday opclo price with 30days avg
|
|
// if opclo_1d_vec[0].price < (opclo_1d_price_7days_avg * 0.8) {
|
|
// filtered_1st_symbols.push(element.symbol);
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 3. 2nd filtering symbols: 85% of BB SMA10 MA price > candle 1d price yesterday avg
|
|
// let mut read_bb_vec: Vec<BBData> = Vec::new();
|
|
// let mut filtered_2nd_symbols: Vec<String> = Vec::new();
|
|
// for element in filtered_1st_symbols {
|
|
|
|
// let opclo_1d_result = read_opclo_into_vector("1d", &element).await;
|
|
// let read_bb_result = read_bb_into_vector("sma10", "1d", &element).await;
|
|
|
|
// // read 1d csv file & bollingerband sma30 csv file
|
|
// if opclo_1d_result.is_ok() & read_bb_result.is_ok() {
|
|
// opclo_1d_vec = opclo_1d_result.unwrap();
|
|
// read_bb_vec = read_bb_result.unwrap();
|
|
|
|
// if opclo_1d_vec.len() > 1 && read_bb_vec.len() > 1 {
|
|
// opclo_1d_vec.pop();
|
|
// read_bb_vec.pop();
|
|
// let result = read_bb_vec.binary_search_by_key(&opclo_1d_vec.last().unwrap().server_epoch, |&BBData{ma_price, upperband, lowerband, server_epoch}|server_epoch);
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if read_bb_vec[T].ma_price * 0.85 > opclo_1d_vec.last().unwrap().price {
|
|
// filtered_2nd_symbols.push(element);
|
|
// }
|
|
// },
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 4. 3rd filtering symbols: yesterday 1d RSI 3 < 10, 1d RSI 10 < 15
|
|
// let mut rsi3_vec: Vec<RsiData> = Vec::new();
|
|
// let mut rsi10_vec: Vec<RsiData> = Vec::new();
|
|
// let mut filtered_3rd_symbols: Vec<String> = Vec::new();
|
|
// for element in filtered_2nd_symbols {
|
|
|
|
// rsi3_vec.clear();
|
|
// rsi10_vec.clear();
|
|
|
|
// let rsi3_result = read_rsi_into_vector(3, "1d", &element).await;
|
|
// let rsi10_result = read_rsi_into_vector(10, "1d", &element).await;
|
|
|
|
// // read rsi3 csv file & rsi10 csv file
|
|
// if rsi3_result.is_ok() & rsi10_result.is_ok() {
|
|
// rsi3_vec = rsi3_result.unwrap();
|
|
// rsi10_vec = rsi10_result.unwrap();
|
|
|
|
// if rsi3_vec.len() > 1 && rsi10_vec.len() > 1 {
|
|
// rsi3_vec.pop();
|
|
// rsi10_vec.pop();
|
|
// if rsi3_vec.last().unwrap().rsi_value < 0.10 && rsi10_vec.last().unwrap().rsi_value < 0.15 {
|
|
// filtered_3rd_symbols.push(element);
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 5. 4th filtering symbols: avg between yesterday 1d opclo price and yesterday low price> latest 30m opclo price
|
|
// let mut opclo_1d_vec: Vec<OpcloData> = Vec::new();
|
|
// let mut opclo_30m_vec: Vec<OpcloData> = Vec::new();
|
|
// let mut low_1d_vec: Vec<OpcloData> = Vec::new();
|
|
// let mut avg = 0.0;
|
|
// let mut price_same_closetime = 0.0;
|
|
// let mut filtered_4th_symbols: Vec<String> = Vec::new();
|
|
// for element in filtered_3rd_symbols {
|
|
// // initialize avgs
|
|
// avg = 0.0;
|
|
// price_same_closetime = 0.0;
|
|
|
|
// let opclo_1d_result = read_opclo_into_vector("1d", &element).await;
|
|
// let opclo_30m_result = read_opclo_into_vector("30m", &element).await;
|
|
// let low_1d_result = read_low_price_into_vector("1d", &element).await;
|
|
|
|
// // read 1d csv file
|
|
// if opclo_1d_result.is_ok() && low_1d_result.is_ok() && opclo_30m_result.is_ok() {
|
|
|
|
// opclo_1d_vec = opclo_1d_result.unwrap();
|
|
// opclo_30m_vec = opclo_30m_result.unwrap();
|
|
// low_1d_vec = low_1d_result.unwrap();
|
|
|
|
// if opclo_1d_vec.len() > 1 && low_1d_vec.len() > 1 && opclo_30m_vec.len() > 1 {
|
|
// opclo_1d_vec.pop();
|
|
|
|
// let result = low_1d_vec.binary_search_by_key(&opclo_1d_vec.last().unwrap().server_epoch, |OpcloData{price, server_epoch, usdt_volume, up_down}| *server_epoch);
|
|
|
|
// match result {
|
|
// Ok(T) => {
|
|
// avg = (opclo_1d_vec.last().unwrap().price + low_1d_vec[T].price) / 2.0;
|
|
|
|
// if opclo_30m_vec.last().unwrap().price < avg {
|
|
// filtered_4th_symbols.push(element);
|
|
// }
|
|
// },
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 6. 5th filtering symbols: 30m RSI 3 < 10, 30m RSI 10 < 15
|
|
// let mut rsi3_vec: Vec<RsiData> = Vec::new();
|
|
// let mut rsi10_vec: Vec<RsiData> = Vec::new();
|
|
// let mut opclo_30m_vec: Vec<OpcloData> = Vec::new();
|
|
// let mut filtered_5th_symbols: Vec<(String, u64)> = Vec::new(); // (symbol, closetime)
|
|
// for element in filtered_4th_symbols {
|
|
|
|
// rsi3_vec.clear();
|
|
// rsi10_vec.clear();
|
|
|
|
// let rsi3_result = read_rsi_into_vector(3, "30m", &element).await;
|
|
// let rsi10_result = read_rsi_into_vector(10, "30m", &element).await;
|
|
// let opclo_30m_result = read_opclo_into_vector("30m", &element).await;
|
|
|
|
// // read rsi3 csv file & rsi10 csv file
|
|
// if rsi3_result.is_ok() & rsi10_result.is_ok() && opclo_30m_result.is_ok() {
|
|
// rsi3_vec = rsi3_result.unwrap();
|
|
// rsi10_vec = rsi10_result.unwrap();
|
|
// opclo_30m_vec = opclo_30m_result.unwrap();
|
|
|
|
// if rsi3_vec.len() > 1 && rsi10_vec.len() > 1 && opclo_30m_vec.len() > 1 {
|
|
// if rsi3_vec.last().unwrap().rsi_value < 0.10 && rsi10_vec.last().unwrap().rsi_value < 0.10 {
|
|
// filtered_5th_symbols.push((element, opclo_30m_vec.last().unwrap().server_epoch));
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 7. insert record into [pre_suggested_coin_list]
|
|
// insert_pre_suggested_coins(14, &filtered_5th_symbols).await;
|
|
|
|
// if instant.elapsed().as_millis() < 50 {
|
|
// sleep(Duration::from_millis(50)).await;
|
|
// }
|
|
// Ok(())
|
|
// }
|
|
|
|
// pub async fn strategist_013(
|
|
// alldata: &AllData,
|
|
// ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|
// // [strategist_013 procedure]
|
|
// // 1st filtering: the latest 2 opclo_1d < BB30_1d upper band, current price < previous opclo_1d
|
|
// // 2nd filtering: check 5 samples of candle 30m has DOWN candles at least 4, the latest opclo_30m < EMA3_30m, the latest opclo_30m < SMA30_30m
|
|
// // 3rd filtering: low price 30m < BB30_30m lowerband
|
|
// // 4th filtering: RSI3_30m < 15, RSI10_30m < 35
|
|
// // 5th filtering: RSI3_1m < 10, RSI10_1m < 25
|
|
// // 6th filtering: opclo_1m < EMA3_1m, opclo_1m < EMA10_1m
|
|
|
|
// // 1st filtering: the latest 2 opclo_1d < BB30_1d upper band, current price < previous opclo_1d
|
|
// let mut opclo_1d_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut bb30_1d_vec: Vec<BollingerBandData> = Vec::new();
|
|
// let mut filtered_1st_symbols: Vec<String> = Vec::new();
|
|
// let mut current_price: Option<f64>;
|
|
// for symbol in &alldata.valid_symbol_vec {
|
|
// let opclo_1d_option = alldata.rt_price_1d_vec.iter().position(|x| *x.0 == *symbol);
|
|
// let bb30_1d_option = alldata.bb30_1d_data.iter().position(|x| *x.0 == *symbol);
|
|
|
|
// if opclo_1d_option.is_some() && bb30_1d_option.is_some() {
|
|
// opclo_1d_vec = alldata.rt_price_1d_vec[opclo_1d_option.unwrap()].1.clone();
|
|
// bb30_1d_vec = alldata.bb30_1d_data[bb30_1d_option.unwrap()].1.clone();
|
|
|
|
// if opclo_1d_vec.len() >= 2 && bb30_1d_vec.len() >= 2 {
|
|
// opclo_1d_vec.reverse();
|
|
// opclo_1d_vec.truncate(2);
|
|
// opclo_1d_vec.reverse();
|
|
// bb30_1d_vec.reverse();
|
|
// bb30_1d_vec.truncate(2);
|
|
// bb30_1d_vec.reverse();
|
|
|
|
// let result = bb30_1d_vec.binary_search_by_key(
|
|
// &opclo_1d_vec.first().unwrap().close_time,
|
|
// |&BollingerBandData {
|
|
// sma,
|
|
// upperband,
|
|
// lowerband,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// current_price = get_current_price(&symbol, &alldata.price_vec).await;
|
|
|
|
// if current_price.is_some() {
|
|
// if current_price.unwrap().is_normal() {
|
|
// if (bb30_1d_vec[T].upperband
|
|
// > opclo_1d_vec.first().unwrap().opclo_price)
|
|
// && (opclo_1d_vec.first().unwrap().opclo_price
|
|
// > current_price.unwrap())
|
|
// {
|
|
// let result = bb30_1d_vec.binary_search_by_key(
|
|
// &opclo_1d_vec.last().unwrap().close_time,
|
|
// |&BollingerBandData {
|
|
// sma,
|
|
// upperband,
|
|
// lowerband,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if bb30_1d_vec[T].upperband
|
|
// > opclo_1d_vec.last().unwrap().opclo_price
|
|
// {
|
|
// filtered_1st_symbols.push(symbol.clone());
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 2nd filtering: check 5 samples of candle 30m has DOWN candles at least 4, the latest opclo_30m < EMA3_30m, the latest opclo_30m < SMA30_30m
|
|
// let mut opclo_30m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut ema3_30m_vec: Vec<EmaData> = Vec::new();
|
|
// let mut sma30_30m_vec: Vec<SmaData> = Vec::new();
|
|
// let mut filtered_2nd_symbols: Vec<String> = Vec::new();
|
|
// let mut cnt = 0;
|
|
// for symbol in filtered_1st_symbols {
|
|
// let opclo_30m_option = alldata
|
|
// .rt_price_30m_vec
|
|
// .iter()
|
|
// .position(|x| *x.0 == *symbol);
|
|
// let ema3_30m_option = alldata.ema3_30m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let sma30_30m_option = alldata.sma30_30m_data.iter().position(|x| *x.0 == *symbol);
|
|
|
|
// if opclo_30m_option.is_some() && ema3_30m_option.is_some() && sma30_30m_option.is_some() {
|
|
// opclo_30m_vec = alldata.rt_price_30m_vec[opclo_30m_option.unwrap()]
|
|
// .1
|
|
// .clone();
|
|
// ema3_30m_vec = alldata.ema3_30m_data[ema3_30m_option.unwrap()].1.clone();
|
|
// sma30_30m_vec = alldata.sma30_30m_data[sma30_30m_option.unwrap()].1.clone();
|
|
|
|
// if opclo_30m_vec.len() >= 5 && ema3_30m_vec.len() >= 1 && sma30_30m_vec.len() >= 1 {
|
|
// opclo_30m_vec.reverse();
|
|
// opclo_30m_vec.truncate(5);
|
|
// opclo_30m_vec.reverse();
|
|
|
|
// cnt = 0;
|
|
// for element in &opclo_30m_vec {
|
|
// if element.candle_type == "DOWN" {
|
|
// cnt += 1;
|
|
// }
|
|
// }
|
|
|
|
// if cnt >= 4 {
|
|
// let result = ema3_30m_vec.binary_search_by_key(
|
|
// &opclo_30m_vec.last().unwrap().close_time,
|
|
// |&EmaData {
|
|
// ema_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if ema3_30m_vec[T].ema_value > opclo_30m_vec.last().unwrap().opclo_price
|
|
// {
|
|
// let result = sma30_30m_vec.binary_search_by_key(
|
|
// &opclo_30m_vec.last().unwrap().close_time,
|
|
// |&SmaData {
|
|
// sma_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if sma30_30m_vec[T].sma_value
|
|
// > opclo_30m_vec.last().unwrap().opclo_price
|
|
// {
|
|
// filtered_2nd_symbols.push(symbol);
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 3rd filtering: low price 30m < BB30_30m lowerband
|
|
// let mut low_30m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut bb30_30m_vec: Vec<BollingerBandData> = Vec::new();
|
|
// let mut filtered_3rd_symbols: Vec<String> = Vec::new();
|
|
// for symbol in filtered_2nd_symbols {
|
|
// let low_30m_option = alldata
|
|
// .rt_price_30m_vec
|
|
// .iter()
|
|
// .position(|x| *x.0 == *symbol);
|
|
// let bb30_30m_option = alldata.bb30_30m_data.iter().position(|x| *x.0 == *symbol);
|
|
|
|
// if low_30m_option.is_some() && bb30_30m_option.is_some() {
|
|
// low_30m_vec = alldata.rt_price_30m_vec[low_30m_option.unwrap()].1.clone();
|
|
// bb30_30m_vec = alldata.bb30_30m_data[bb30_30m_option.unwrap()].1.clone();
|
|
|
|
// if low_30m_vec.len() >= 1 && bb30_30m_vec.len() >= 1 {
|
|
// let result = bb30_30m_vec.binary_search_by_key(
|
|
// &low_30m_vec.last().unwrap().close_time,
|
|
// |&BollingerBandData {
|
|
// sma,
|
|
// upperband,
|
|
// lowerband,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if bb30_30m_vec[T].lowerband > low_30m_vec.last().unwrap().low_price {
|
|
// filtered_3rd_symbols.push(symbol);
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 4th filtering: 30m RSI 3 < 15, 30m RSI 10 < 35
|
|
// let mut rsi3_30m_vec: Vec<RsiData> = Vec::new();
|
|
// let mut rsi10_30m_vec: Vec<RsiData> = Vec::new();
|
|
// let mut opclo_30m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut filtered_4th_symbols: Vec<String> = Vec::new();
|
|
// for symbol in filtered_3rd_symbols {
|
|
// let rsi3_30m_option = alldata.rsi3_30m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let rsi10_30m_option = alldata.rsi10_30m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let opclo_30m_option = alldata
|
|
// .rt_price_30m_vec
|
|
// .iter()
|
|
// .position(|x| *x.0 == *symbol);
|
|
|
|
// if rsi3_30m_option.is_some() && rsi10_30m_option.is_some() && opclo_30m_option.is_some() {
|
|
// rsi3_30m_vec = alldata.rsi3_30m_data[rsi3_30m_option.unwrap()].1.clone();
|
|
// rsi10_30m_vec = alldata.rsi10_30m_data[rsi10_30m_option.unwrap()].1.clone();
|
|
// opclo_30m_vec = alldata.rt_price_30m_vec[opclo_30m_option.unwrap()]
|
|
// .1
|
|
// .clone();
|
|
|
|
// if rsi3_30m_vec.len() >= 1 && rsi10_30m_vec.len() >= 1 && opclo_30m_vec.len() >= 1 {
|
|
// let result = rsi3_30m_vec.binary_search_by_key(
|
|
// &opclo_30m_vec.last().unwrap().close_time,
|
|
// |&RsiData {
|
|
// rsi_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if rsi3_30m_vec[T].rsi_value < 15.0 {
|
|
// let result = rsi10_30m_vec.binary_search_by_key(
|
|
// &opclo_30m_vec.last().unwrap().close_time,
|
|
// |&RsiData {
|
|
// rsi_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if rsi10_30m_vec[T].rsi_value < 35.0 {
|
|
// filtered_4th_symbols.push(symbol);
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 5th filtering: RSI3_1m < 10, RSI10_1m < 25
|
|
// let mut rsi3_1m_vec: Vec<RsiData> = Vec::new();
|
|
// let mut rsi10_1m_vec: Vec<RsiData> = Vec::new();
|
|
// let mut filtered_5th_symbols: Vec<String> = Vec::new(); // (symbol, closetime)
|
|
// for symbol in filtered_4th_symbols {
|
|
// let rsi3_1m_option = alldata.rsi3_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let rsi10_1m_option = alldata.rsi10_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
|
|
// if rsi3_1m_option.is_some() && rsi10_1m_option.is_some() {
|
|
// rsi3_1m_vec = alldata.rsi3_1m_data[rsi3_1m_option.unwrap()].1.clone();
|
|
// rsi10_1m_vec = alldata.rsi10_1m_data[rsi10_1m_option.unwrap()].1.clone();
|
|
|
|
// if rsi3_1m_vec.len() >= 1 && rsi10_1m_vec.len() >= 1 {
|
|
// if rsi3_1m_vec.last().unwrap().rsi_value < 10.0
|
|
// && rsi10_1m_vec.last().unwrap().rsi_value < 25.0
|
|
// {
|
|
// filtered_5th_symbols.push(symbol);
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 6th filtering: opclo_1m < EMA3_1m, opclo_1m < EMA10_1m, clo_1m < BB30_1m lowerband
|
|
// let mut opclo_1m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut opclo_30m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut ema3_1m_vec: Vec<EmaData> = Vec::new();
|
|
// let mut ema10_1m_vec: Vec<EmaData> = Vec::new();
|
|
// let mut bb30_1m_vec: Vec<BollingerBandData> = Vec::new();
|
|
// let mut filtered_6th_symbols: Vec<(String, i64)> = Vec::new(); // (symbol, closetime)
|
|
// for symbol in filtered_5th_symbols {
|
|
// let opclo_1m_option = alldata.rt_price_1m_vec.iter().position(|x| *x.0 == *symbol);
|
|
// let opclo_30m_option = alldata
|
|
// .rt_price_30m_vec
|
|
// .iter()
|
|
// .position(|x| *x.0 == *symbol);
|
|
// let ema3_1m_option = alldata.ema3_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let ema10_1m_option = alldata.ema10_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let bb30_1m_option = alldata.bb30_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
|
|
// if opclo_1m_option.is_some()
|
|
// && opclo_30m_option.is_some()
|
|
// && ema3_1m_option.is_some()
|
|
// && ema10_1m_option.is_some()
|
|
// && bb30_1m_option.is_some()
|
|
// {
|
|
// opclo_1m_vec = alldata.rt_price_1m_vec[opclo_1m_option.unwrap()].1.clone();
|
|
// opclo_30m_vec = alldata.rt_price_30m_vec[opclo_30m_option.unwrap()]
|
|
// .1
|
|
// .clone();
|
|
// ema3_1m_vec = alldata.ema3_1m_data[ema3_1m_option.unwrap()].1.clone();
|
|
// ema10_1m_vec = alldata.ema10_1m_data[ema10_1m_option.unwrap()].1.clone();
|
|
// bb30_1m_vec = alldata.bb30_1m_data[bb30_1m_option.unwrap()].1.clone();
|
|
|
|
// if opclo_1m_vec.len() >= 1
|
|
// && opclo_30m_vec.len() >= 1
|
|
// && ema3_1m_vec.len() >= 1
|
|
// && ema10_1m_vec.len() >= 1
|
|
// && bb30_1m_vec.len() >= 1
|
|
// {
|
|
// let result = ema3_1m_vec.binary_search_by_key(
|
|
// &opclo_1m_vec.last().unwrap().close_time,
|
|
// |&EmaData {
|
|
// ema_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if ema3_1m_vec[T].ema_value > opclo_1m_vec.last().unwrap().opclo_price {
|
|
// let result = ema10_1m_vec.binary_search_by_key(
|
|
// &opclo_1m_vec.last().unwrap().close_time,
|
|
// |&EmaData {
|
|
// ema_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if ema10_1m_vec[T].ema_value
|
|
// > opclo_1m_vec.last().unwrap().opclo_price
|
|
// {
|
|
// let result = bb30_1m_vec.binary_search_by_key(
|
|
// &opclo_1m_vec.last().unwrap().close_time,
|
|
// |&BollingerBandData {
|
|
// sma,
|
|
// upperband,
|
|
// lowerband,
|
|
// close_time,
|
|
// }| {
|
|
// close_time
|
|
// },
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if bb30_1m_vec[T].lowerband
|
|
// > opclo_1d_vec.last().unwrap().close_price
|
|
// {
|
|
// filtered_6th_symbols.push((
|
|
// symbol,
|
|
// opclo_30m_vec.last().unwrap().close_time,
|
|
// ));
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// insert_pre_suggested_coins(13, &filtered_6th_symbols, alldata).await;
|
|
|
|
// Ok(())
|
|
// }
|
|
|
|
// pub async fn strategist_014(
|
|
// alldata: &AllData,
|
|
// ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|
// // [strategist_014 procedure]
|
|
// // 1st filtering: the latest 2 opclo_1d < BB30_1d upper band, current price < previous opclo_1d,
|
|
// // 2nd filtering: the latest 2 opclo_1d < SMA3_1d (apply this filtering if 5days angle of marketcap is negative and marketcap opinion is DOWN or KEEP)
|
|
// // 3rd filtering: RSI3_1d < 20, RSI10_1d < 35, RSI30_1d < 45 (if 5days angle of marketcap is negative and marketcap opinion is UP, this filtering will be passed)
|
|
// // 4th filtering:
|
|
// // 1) check the latest candle is DOWN (common)
|
|
// // 2) DOWN candles having 0.3% below change is not counted
|
|
// // 3) check 5 samples of candle 30m has DOWN candles at least 4, the latest opclo_30m < EMA3_30m, the latest opclo_30m < SMA30_30m
|
|
// // 4) OR, check 5 samples of candle 30m has DOWN candles at least 3, the latest clo_30m < BB30_30m lowerband
|
|
// // 5th filtering: RSI3_30m < 20, RSI10_30m < 35
|
|
// // 6th filtering: RSI3_1m < 10, RSI10_1m < 25
|
|
// // 7th filtering: opclo_1m < EMA3_1m, opclo_1m < EMA10_1m, clo_1m < BB30_1m lowerband
|
|
// // 8th filtering: check the latest candle is DOWN and check 5 samples of candle 1m has DOWN candles at least 3
|
|
|
|
// let signal_opinions = select_signal_association_opinion().await;
|
|
// let market_cap_index = select_marketcap().await;
|
|
|
|
// // 1st filtering: the latest 2 opclo_1d < BB30_1d upper band and SMA3_1d, current price < previous opclo_1d,
|
|
// let mut opclo_1d_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut bb30_1d_vec: Vec<BollingerBandData> = Vec::new();
|
|
// let mut sma3_1d_vec: Vec<SmaData> = Vec::new();
|
|
// let mut filtered_1st_symbols: Vec<String> = Vec::new();
|
|
// let mut current_price: Option<f64>;
|
|
// for symbol in &alldata.valid_symbol_vec {
|
|
// let opclo_1d_option = alldata.rt_price_1d_vec.iter().position(|x| *x.0 == *symbol);
|
|
// let bb30_1d_option = alldata.bb30_1d_data.iter().position(|x| *x.0 == *symbol);
|
|
// let sma3_1d_option = alldata.sma3_1d_data.iter().position(|x| *x.0 == *symbol);
|
|
|
|
// if opclo_1d_option.is_some() && bb30_1d_option.is_some() && sma3_1d_option.is_some() {
|
|
// opclo_1d_vec = alldata.rt_price_1d_vec[opclo_1d_option.unwrap()].1.clone();
|
|
// bb30_1d_vec = alldata.bb30_1d_data[bb30_1d_option.unwrap()].1.clone();
|
|
// sma3_1d_vec = alldata.sma3_1d_data[sma3_1d_option.unwrap()].1.clone();
|
|
|
|
// if opclo_1d_vec.len() >= 2 && bb30_1d_vec.len() >= 2 && sma3_1d_vec.len() >= 2 {
|
|
// opclo_1d_vec.reverse();
|
|
// opclo_1d_vec.truncate(2);
|
|
// opclo_1d_vec.reverse();
|
|
// bb30_1d_vec.reverse();
|
|
// bb30_1d_vec.truncate(2);
|
|
// bb30_1d_vec.reverse();
|
|
// sma3_1d_vec.reverse();
|
|
// sma3_1d_vec.truncate(2);
|
|
// sma3_1d_vec.reverse();
|
|
|
|
// let result = bb30_1d_vec.binary_search_by_key(
|
|
// &opclo_1d_vec.first().unwrap().close_time,
|
|
// |&BollingerBandData {
|
|
// sma,
|
|
// upperband,
|
|
// lowerband,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// current_price = get_current_price(&symbol, &alldata.price_vec).await;
|
|
|
|
// if current_price.is_some() {
|
|
// if current_price.unwrap().is_normal() {
|
|
// if (bb30_1d_vec[T].upperband
|
|
// > opclo_1d_vec.first().unwrap().opclo_price)
|
|
// && (opclo_1d_vec.first().unwrap().opclo_price
|
|
// > current_price.unwrap())
|
|
// {
|
|
// let result = bb30_1d_vec.binary_search_by_key(
|
|
// &opclo_1d_vec.last().unwrap().close_time,
|
|
// |&BollingerBandData {
|
|
// sma,
|
|
// upperband,
|
|
// lowerband,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if bb30_1d_vec[T].upperband
|
|
// > opclo_1d_vec.last().unwrap().opclo_price
|
|
// {
|
|
// filtered_1st_symbols.push(symbol.clone());
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 2nd filtering: the latest 2 opclo_1d < SMA3_1d (apply this filtering if 5days angle of marketcap is negative and marketcap opinion is DOWN or KEEP)
|
|
// let mut opclo_1d_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut sma3_1d_vec: Vec<SmaData> = Vec::new();
|
|
// let mut filtered_2nd_symbols: Vec<String> = Vec::new();
|
|
// if (signal_opinions[0].opinion.contains("DOWN") || signal_opinions[0].opinion.contains("KEEP"))
|
|
// && market_cap_index[1].market_cap_index.is_sign_negative()
|
|
// {
|
|
// for symbol in &alldata.valid_symbol_vec {
|
|
// let opclo_1d_option = alldata.rt_price_1d_vec.iter().position(|x| *x.0 == *symbol);
|
|
// let sma3_1d_option = alldata.sma3_1d_data.iter().position(|x| *x.0 == *symbol);
|
|
|
|
// if opclo_1d_option.is_some() && sma3_1d_option.is_some() {
|
|
// opclo_1d_vec = alldata.rt_price_1d_vec[opclo_1d_option.unwrap()].1.clone();
|
|
// sma3_1d_vec = alldata.sma3_1d_data[sma3_1d_option.unwrap()].1.clone();
|
|
|
|
// if opclo_1d_vec.len() >= 2 && sma3_1d_vec.len() >= 2 {
|
|
// opclo_1d_vec.reverse();
|
|
// opclo_1d_vec.truncate(2);
|
|
// opclo_1d_vec.reverse();
|
|
// sma3_1d_vec.reverse();
|
|
// sma3_1d_vec.truncate(2);
|
|
// sma3_1d_vec.reverse();
|
|
|
|
// let result = sma3_1d_vec.binary_search_by_key(
|
|
// &opclo_1d_vec.first().unwrap().close_time,
|
|
// |&SmaData {
|
|
// sma_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if sma3_1d_vec[T].sma_value > opclo_1d_vec.first().unwrap().opclo_price
|
|
// {
|
|
// let result = sma3_1d_vec.binary_search_by_key(
|
|
// &opclo_1d_vec.last().unwrap().close_time,
|
|
// |&SmaData {
|
|
// sma_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if sma3_1d_vec[T].sma_value
|
|
// > opclo_1d_vec.last().unwrap().opclo_price
|
|
// {
|
|
// filtered_2nd_symbols.push(symbol.clone());
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// } else {
|
|
// filtered_2nd_symbols = filtered_1st_symbols;
|
|
// }
|
|
|
|
// // 3rd filtering: RSI3_1d < 20, RSI10_1d < 35, RSI30_1d < 45 (if 5days angle of marketcap is negative and marketcap opinion is UP, this filtering will be passed)
|
|
// let mut rsi3_1d_vec: Vec<RsiData> = Vec::new();
|
|
// let mut rsi10_1d_vec: Vec<RsiData> = Vec::new();
|
|
// let mut rsi30_1d_vec: Vec<RsiData> = Vec::new();
|
|
// let mut filtered_3rd_symbols: Vec<String> = Vec::new();
|
|
// if signal_opinions[0].opinion.contains("UP")
|
|
// && market_cap_index[1].market_cap_index.is_sign_negative()
|
|
// {
|
|
// filtered_3rd_symbols = filtered_2nd_symbols;
|
|
// } else {
|
|
// for symbol in filtered_2nd_symbols {
|
|
// let rsi3_1d_option = alldata.rsi3_1d_data.iter().position(|x| *x.0 == *symbol);
|
|
// let rsi10_1d_option = alldata.rsi10_1d_data.iter().position(|x| *x.0 == *symbol);
|
|
// let rsi30_1d_option = alldata.rsi30_1d_data.iter().position(|x| *x.0 == *symbol);
|
|
|
|
// if rsi3_1d_option.is_some() && rsi10_1d_option.is_some() && rsi30_1d_option.is_some() {
|
|
// rsi3_1d_vec = alldata.rsi3_1d_data[rsi3_1d_option.unwrap()].1.clone();
|
|
// rsi10_1d_vec = alldata.rsi10_1d_data[rsi10_1d_option.unwrap()].1.clone();
|
|
// rsi30_1d_vec = alldata.rsi30_1d_data[rsi30_1d_option.unwrap()].1.clone();
|
|
|
|
// if rsi3_1d_vec.len() >= 1 && rsi10_1d_vec.len() >= 1 && rsi30_1d_vec.len() >= 1 {
|
|
// if rsi3_1d_vec.last().unwrap().rsi_value < 20.0
|
|
// && rsi10_1d_vec.last().unwrap().rsi_value < 35.0
|
|
// && rsi30_1d_vec.last().unwrap().rsi_value < 45.0
|
|
// {
|
|
// filtered_3rd_symbols.push(symbol);
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 4th filtering:
|
|
// // 1) check the latest candle is DOWN (common)
|
|
// // 2) DOWN candles having 0.3% below change is not counted
|
|
// // 3) check 5 samples of candle 30m has DOWN candles at least 4, the latest opclo_30m < EMA3_30m, the latest opclo_30m < SMA30_30m
|
|
// // 4) OR, check 5 samples of candle 30m has DOWN candles at least 3, the latest clo_30m < BB30_30m lowerband
|
|
|
|
// let mut opclo_30m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut ema3_30m_vec: Vec<EmaData> = Vec::new();
|
|
// let mut sma30_30m_vec: Vec<SmaData> = Vec::new();
|
|
// let mut bb30_30m_vec: Vec<BollingerBandData> = Vec::new();
|
|
// let mut filtered_4th_symbols: Vec<String> = Vec::new();
|
|
// let mut cnt = 0;
|
|
// for symbol in filtered_3rd_symbols {
|
|
// let mut is_filtering_passed: bool = false;
|
|
// let opclo_30m_option = alldata
|
|
// .rt_price_30m_vec
|
|
// .iter()
|
|
// .position(|x| *x.0 == *symbol);
|
|
// let ema3_30m_option = alldata.ema3_30m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let sma30_30m_option = alldata.sma30_30m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let bb30_30m_option = alldata.bb30_30m_data.iter().position(|x| *x.0 == *symbol);
|
|
|
|
// if opclo_30m_option.is_some()
|
|
// && ema3_30m_option.is_some()
|
|
// && sma30_30m_option.is_some()
|
|
// && bb30_30m_option.is_some()
|
|
// {
|
|
// opclo_30m_vec = alldata.rt_price_30m_vec[opclo_30m_option.unwrap()]
|
|
// .1
|
|
// .clone();
|
|
// ema3_30m_vec = alldata.ema3_30m_data[ema3_30m_option.unwrap()].1.clone();
|
|
// sma30_30m_vec = alldata.sma30_30m_data[sma30_30m_option.unwrap()].1.clone();
|
|
// bb30_30m_vec = alldata.bb30_30m_data[bb30_30m_option.unwrap()].1.clone();
|
|
|
|
// if opclo_30m_vec.len() >= 5
|
|
// && ema3_30m_vec.len() >= 1
|
|
// && sma30_30m_vec.len() >= 1
|
|
// && bb30_30m_vec.len() >= 1
|
|
// {
|
|
// opclo_30m_vec.reverse();
|
|
// opclo_30m_vec.truncate(5);
|
|
// opclo_30m_vec.reverse();
|
|
|
|
// if opclo_30m_vec.last().unwrap().candle_type == "DOWN" {
|
|
// cnt = 0;
|
|
// for element in &opclo_30m_vec {
|
|
// if element.candle_type == "DOWN" {
|
|
// if (element.open_price / element.close_price) - 1.0 > 0.003 {
|
|
// cnt += 1;
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// if cnt >= 4 {
|
|
// let result = ema3_30m_vec.binary_search_by_key(
|
|
// &opclo_30m_vec.last().unwrap().close_time,
|
|
// |&EmaData {
|
|
// ema_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if ema3_30m_vec[T].ema_value
|
|
// > opclo_30m_vec.last().unwrap().opclo_price
|
|
// {
|
|
// let result = sma30_30m_vec.binary_search_by_key(
|
|
// &opclo_30m_vec.last().unwrap().close_time,
|
|
// |&SmaData {
|
|
// sma_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if sma30_30m_vec[T].sma_value
|
|
// > opclo_30m_vec.last().unwrap().opclo_price
|
|
// {
|
|
// is_filtering_passed = true;
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// } else if cnt == 3 {
|
|
// let result = bb30_30m_vec.binary_search_by_key(
|
|
// &opclo_30m_vec.last().unwrap().close_time,
|
|
// |&BollingerBandData {
|
|
// sma,
|
|
// upperband,
|
|
// lowerband,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if bb30_30m_vec[T].lowerband
|
|
// > opclo_30m_vec.last().unwrap().close_price
|
|
// {
|
|
// is_filtering_passed = true;
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// if is_filtering_passed == true {
|
|
// filtered_4th_symbols.push(symbol);
|
|
// }
|
|
// }
|
|
|
|
// // 5th filtering: RSI3_30m < 20, RSI10_30m < 35
|
|
// let mut rsi3_30m_vec: Vec<RsiData> = Vec::new();
|
|
// let mut rsi10_30m_vec: Vec<RsiData> = Vec::new();
|
|
// let mut opclo_30m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut filtered_5th_symbols: Vec<String> = Vec::new();
|
|
// for symbol in filtered_4th_symbols {
|
|
// let rsi3_30m_option = alldata.rsi3_30m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let rsi10_30m_option = alldata.rsi10_30m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let opclo_30m_option = alldata
|
|
// .rt_price_30m_vec
|
|
// .iter()
|
|
// .position(|x| *x.0 == *symbol);
|
|
|
|
// if rsi3_30m_option.is_some() && rsi10_30m_option.is_some() && opclo_30m_option.is_some() {
|
|
// rsi3_30m_vec = alldata.rsi3_30m_data[rsi3_30m_option.unwrap()].1.clone();
|
|
// rsi10_30m_vec = alldata.rsi10_30m_data[rsi10_30m_option.unwrap()].1.clone();
|
|
// opclo_30m_vec = alldata.rt_price_30m_vec[opclo_30m_option.unwrap()]
|
|
// .1
|
|
// .clone();
|
|
|
|
// if rsi3_30m_vec.len() >= 1 && rsi10_30m_vec.len() >= 1 && opclo_30m_vec.len() >= 1 {
|
|
// let result = rsi3_30m_vec.binary_search_by_key(
|
|
// &opclo_30m_vec.last().unwrap().close_time,
|
|
// |&RsiData {
|
|
// rsi_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if rsi3_30m_vec[T].rsi_value < 20.0 {
|
|
// let result = rsi10_30m_vec.binary_search_by_key(
|
|
// &opclo_30m_vec.last().unwrap().close_time,
|
|
// |&RsiData {
|
|
// rsi_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if rsi10_30m_vec[T].rsi_value < 35.0 {
|
|
// filtered_5th_symbols.push(symbol);
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 6th filtering: RSI3_1m < 10, RSI10_1m < 25
|
|
// let mut rsi3_1m_vec: Vec<RsiData> = Vec::new();
|
|
// let mut rsi10_1m_vec: Vec<RsiData> = Vec::new();
|
|
// let mut filtered_6th_symbols: Vec<String> = Vec::new();
|
|
// for symbol in filtered_5th_symbols {
|
|
// let rsi3_1m_option = alldata.rsi3_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let rsi10_1m_option = alldata.rsi10_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
|
|
// if rsi3_1m_option.is_some() && rsi10_1m_option.is_some() {
|
|
// rsi3_1m_vec = alldata.rsi3_1m_data[rsi3_1m_option.unwrap()].1.clone();
|
|
// rsi10_1m_vec = alldata.rsi10_1m_data[rsi10_1m_option.unwrap()].1.clone();
|
|
|
|
// if rsi3_1m_vec.len() >= 1 && rsi10_1m_vec.len() >= 1 {
|
|
// if rsi3_1m_vec.last().unwrap().rsi_value < 10.0
|
|
// && rsi10_1m_vec.last().unwrap().rsi_value < 25.0
|
|
// {
|
|
// filtered_6th_symbols.push(symbol);
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // // 6. 5th filtering symbols: 30m current vol > 30m previous vol * 2
|
|
// // let mut opclo_30m_vec: Vec<PriceData> = Vec::new();
|
|
// // let mut filtered_4th_symbols: Vec<(String, u64)> = Vec::new(); // (symbol, closetime)
|
|
// // for element in filtered_3rd_symbols {
|
|
// // let opclo_30m_result = read_price_into_vector("30m", &element).await;
|
|
|
|
// // if opclo_30m_result.is_ok() {
|
|
// // let opclo_30m_option = opclo_30m_result?;
|
|
// // if opclo_30m_option.is_some() {
|
|
// // opclo_30m_vec = opclo_30m_option.unwrap();
|
|
|
|
// // if opclo_30m_vec.len() >= 2 {
|
|
// // opclo_30m_vec.reverse();
|
|
// // opclo_30m_vec.truncate(2);
|
|
// // opclo_30m_vec.reverse();
|
|
|
|
// // if 2.0 * opclo_30m_vec.first().unwrap().quote_asset_volume < opclo_30m_vec.last().unwrap().quote_asset_volume && opclo_30m_vec.last().unwrap().candle_type == "DOWN" {
|
|
// // filtered_4th_symbols.push((element, opclo_30m_vec.last().unwrap().close_time));
|
|
// // }
|
|
// // }
|
|
// // }
|
|
// // }
|
|
// // }
|
|
|
|
// // 7th filtering: opclo_1m < EMA3_1m, opclo_1m < EMA10_1m, clo_1m < BB30_1m lowerband
|
|
// let mut opclo_1m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut ema3_1m_vec: Vec<EmaData> = Vec::new();
|
|
// let mut ema10_1m_vec: Vec<EmaData> = Vec::new();
|
|
// let mut bb30_1m_vec: Vec<BollingerBandData> = Vec::new();
|
|
// let mut filtered_7th_symbols: Vec<String> = Vec::new();
|
|
// for symbol in filtered_6th_symbols {
|
|
// let opclo_1m_option = alldata.rt_price_1m_vec.iter().position(|x| *x.0 == *symbol);
|
|
// let ema3_1m_option = alldata.ema3_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let ema10_1m_option = alldata.ema10_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let bb30_1m_option = alldata.bb30_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
|
|
// if opclo_1m_option.is_some()
|
|
// && ema3_1m_option.is_some()
|
|
// && ema10_1m_option.is_some()
|
|
// && bb30_1m_option.is_some()
|
|
// {
|
|
// opclo_1m_vec = alldata.rt_price_1m_vec[opclo_1m_option.unwrap()].1.clone();
|
|
// ema3_1m_vec = alldata.ema3_1m_data[ema3_1m_option.unwrap()].1.clone();
|
|
// ema10_1m_vec = alldata.ema10_1m_data[ema10_1m_option.unwrap()].1.clone();
|
|
// bb30_1m_vec = alldata.bb30_1m_data[bb30_1m_option.unwrap()].1.clone();
|
|
|
|
// if opclo_1m_vec.len() >= 1
|
|
// && ema3_1m_vec.len() >= 1
|
|
// && ema10_1m_vec.len() >= 1
|
|
// && bb30_1m_vec.len() >= 1
|
|
// {
|
|
// let result = ema3_1m_vec.binary_search_by_key(
|
|
// &opclo_1m_vec.last().unwrap().close_time,
|
|
// |&EmaData {
|
|
// ema_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if ema3_1m_vec[T].ema_value > opclo_1m_vec.last().unwrap().opclo_price {
|
|
// let result = ema10_1m_vec.binary_search_by_key(
|
|
// &opclo_1m_vec.last().unwrap().close_time,
|
|
// |&EmaData {
|
|
// ema_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if ema10_1m_vec[T].ema_value
|
|
// > opclo_1m_vec.last().unwrap().opclo_price
|
|
// {
|
|
// let result = bb30_1m_vec.binary_search_by_key(
|
|
// &opclo_1m_vec.last().unwrap().close_time,
|
|
// |&BollingerBandData {
|
|
// sma,
|
|
// upperband,
|
|
// lowerband,
|
|
// close_time,
|
|
// }| {
|
|
// close_time
|
|
// },
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if bb30_1m_vec[T].lowerband
|
|
// > opclo_1d_vec.last().unwrap().close_price
|
|
// {
|
|
// filtered_7th_symbols.push(symbol);
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 8th filtering:
|
|
// // check the latest candle is DOWN and check 5 samples of candle 30m has DOWN candles at least 3
|
|
// let mut opclo_1m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut opclo_30m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut filtered_8th_symbols: Vec<(String, i64)> = Vec::new(); // (symbol, closetime)
|
|
|
|
// let mut cnt = 0;
|
|
// for symbol in filtered_7th_symbols {
|
|
// let opclo_1m_option = alldata.rt_price_1m_vec.iter().position(|x| *x.0 == *symbol);
|
|
// let opclo_30m_option = alldata
|
|
// .rt_price_30m_vec
|
|
// .iter()
|
|
// .position(|x| *x.0 == *symbol);
|
|
|
|
// if opclo_30m_option.is_some() && opclo_1m_option.is_some() {
|
|
// opclo_1m_vec = alldata.rt_price_1m_vec[opclo_1m_option.unwrap()].1.clone();
|
|
// opclo_30m_vec = alldata.rt_price_30m_vec[opclo_30m_option.unwrap()]
|
|
// .1
|
|
// .clone();
|
|
|
|
// if opclo_1m_vec.len() >= 5 && opclo_30m_vec.len() >= 5 {
|
|
// opclo_1m_vec.reverse();
|
|
// opclo_1m_vec.truncate(5);
|
|
// opclo_1m_vec.reverse();
|
|
|
|
// if opclo_1m_vec.last().unwrap().candle_type == "DOWN" {
|
|
// cnt = 0;
|
|
// for element in &opclo_1m_vec {
|
|
// if element.candle_type == "DOWN" {
|
|
// cnt += 1;
|
|
// }
|
|
// }
|
|
|
|
// if cnt >= 3 {
|
|
// filtered_8th_symbols
|
|
// .push((symbol, opclo_30m_vec.last().unwrap().close_time));
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// insert_pre_suggested_coins(14, &filtered_8th_symbols, alldata).await;
|
|
|
|
// Ok(())
|
|
// }
|
|
|
|
// pub async fn strategist_015(
|
|
// alldata: &AllData,
|
|
// ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|
// // [strategist_015 procedure]
|
|
// // 1st filtering: the latest 2 opclo_1d < BB30_1d upper band, current price < previous opclo_1d
|
|
// // 2nd filtering: check 5 samples of candle 30m has DOWN candles at least 4, the latest opclo_30m < EMA3_30m, the latest opclo_30m < SMA30_30m
|
|
// // 3rd filtering: low price 30m < BB30_30m lowerband
|
|
// // 4th filtering: RSI3_30m < 15, RSI10_30m < 35
|
|
// // 5th filtering: RSI3_1m < 10, RSI10_1m < 25
|
|
|
|
// // 1st filtering: the latest 2 opclo_1d < BB30_1d upper band, current price < previous opclo_1d
|
|
// let mut opclo_1d_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut bb30_1d_vec: Vec<BollingerBandData> = Vec::new();
|
|
// let mut filtered_1st_symbols: Vec<String> = Vec::new();
|
|
// let mut current_price: Option<f64>;
|
|
// for symbol in &alldata.valid_symbol_vec {
|
|
// let opclo_1d_option = alldata.rt_price_1d_vec.iter().position(|x| *x.0 == *symbol);
|
|
// let bb30_1d_option = alldata.bb30_1d_data.iter().position(|x| *x.0 == *symbol);
|
|
|
|
// if opclo_1d_option.is_some() && bb30_1d_option.is_some() {
|
|
// opclo_1d_vec = alldata.rt_price_1d_vec[opclo_1d_option.unwrap()].1.clone();
|
|
// bb30_1d_vec = alldata.bb30_1d_data[bb30_1d_option.unwrap()].1.clone();
|
|
|
|
// if opclo_1d_vec.len() >= 2 && bb30_1d_vec.len() >= 2 {
|
|
// opclo_1d_vec.reverse();
|
|
// opclo_1d_vec.truncate(2);
|
|
// opclo_1d_vec.reverse();
|
|
// bb30_1d_vec.reverse();
|
|
// bb30_1d_vec.truncate(2);
|
|
// bb30_1d_vec.reverse();
|
|
|
|
// let result = bb30_1d_vec.binary_search_by_key(
|
|
// &opclo_1d_vec.first().unwrap().close_time,
|
|
// |&BollingerBandData {
|
|
// sma,
|
|
// upperband,
|
|
// lowerband,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// current_price = get_current_price(&symbol, &alldata.price_vec).await;
|
|
|
|
// if current_price.is_some() {
|
|
// if current_price.unwrap().is_normal() {
|
|
// if (bb30_1d_vec[T].upperband
|
|
// > opclo_1d_vec.first().unwrap().opclo_price)
|
|
// && (opclo_1d_vec.first().unwrap().opclo_price
|
|
// > current_price.unwrap())
|
|
// {
|
|
// let result = bb30_1d_vec.binary_search_by_key(
|
|
// &opclo_1d_vec.last().unwrap().close_time,
|
|
// |&BollingerBandData {
|
|
// sma,
|
|
// upperband,
|
|
// lowerband,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if bb30_1d_vec[T].upperband
|
|
// > opclo_1d_vec.last().unwrap().opclo_price
|
|
// {
|
|
// filtered_1st_symbols.push(symbol.clone());
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 2nd filtering: check 5 samples of candle 30m has DOWN candles at least 4, the latest opclo_30m < EMA3_30m, the latest opclo_30m < SMA30_30m
|
|
// let mut opclo_30m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut ema3_30m_vec: Vec<EmaData> = Vec::new();
|
|
// let mut sma30_30m_vec: Vec<SmaData> = Vec::new();
|
|
// let mut filtered_2nd_symbols: Vec<String> = Vec::new();
|
|
// let mut cnt = 0;
|
|
// for symbol in filtered_1st_symbols {
|
|
// let opclo_30m_option = alldata
|
|
// .rt_price_30m_vec
|
|
// .iter()
|
|
// .position(|x| *x.0 == *symbol);
|
|
// let ema3_30m_option = alldata.ema3_30m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let sma30_30m_option = alldata.sma30_30m_data.iter().position(|x| *x.0 == *symbol);
|
|
|
|
// if opclo_30m_option.is_some() && ema3_30m_option.is_some() && sma30_30m_option.is_some() {
|
|
// opclo_30m_vec = alldata.rt_price_30m_vec[opclo_30m_option.unwrap()]
|
|
// .1
|
|
// .clone();
|
|
// ema3_30m_vec = alldata.ema3_30m_data[ema3_30m_option.unwrap()].1.clone();
|
|
// sma30_30m_vec = alldata.sma30_30m_data[sma30_30m_option.unwrap()].1.clone();
|
|
|
|
// if opclo_30m_vec.len() >= 5 && ema3_30m_vec.len() >= 1 && sma30_30m_vec.len() >= 1 {
|
|
// opclo_30m_vec.reverse();
|
|
// opclo_30m_vec.truncate(5);
|
|
// opclo_30m_vec.reverse();
|
|
|
|
// cnt = 0;
|
|
// for element in &opclo_30m_vec {
|
|
// if element.candle_type == "DOWN" {
|
|
// cnt += 1;
|
|
// }
|
|
// }
|
|
|
|
// if cnt >= 4 {
|
|
// let result = ema3_30m_vec.binary_search_by_key(
|
|
// &opclo_30m_vec.last().unwrap().close_time,
|
|
// |&EmaData {
|
|
// ema_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if ema3_30m_vec[T].ema_value > opclo_30m_vec.last().unwrap().opclo_price
|
|
// {
|
|
// let result = sma30_30m_vec.binary_search_by_key(
|
|
// &opclo_30m_vec.last().unwrap().close_time,
|
|
// |&SmaData {
|
|
// sma_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if sma30_30m_vec[T].sma_value
|
|
// > opclo_30m_vec.last().unwrap().opclo_price
|
|
// {
|
|
// filtered_2nd_symbols.push(symbol);
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 3rd filtering: low price 30m < BB30_30m lowerband
|
|
// let mut low_30m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut bb30_30m_vec: Vec<BollingerBandData> = Vec::new();
|
|
// let mut filtered_3rd_symbols: Vec<String> = Vec::new();
|
|
// for symbol in filtered_2nd_symbols {
|
|
// let low_30m_option = alldata
|
|
// .rt_price_30m_vec
|
|
// .iter()
|
|
// .position(|x| *x.0 == *symbol);
|
|
// let bb30_30m_option = alldata.bb30_30m_data.iter().position(|x| *x.0 == *symbol);
|
|
|
|
// if low_30m_option.is_some() && bb30_30m_option.is_some() {
|
|
// low_30m_vec = alldata.rt_price_30m_vec[low_30m_option.unwrap()].1.clone();
|
|
// bb30_30m_vec = alldata.bb30_30m_data[bb30_30m_option.unwrap()].1.clone();
|
|
|
|
// if low_30m_vec.len() >= 1 && bb30_30m_vec.len() >= 1 {
|
|
// let result = bb30_30m_vec.binary_search_by_key(
|
|
// &low_30m_vec.last().unwrap().close_time,
|
|
// |&BollingerBandData {
|
|
// sma,
|
|
// upperband,
|
|
// lowerband,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if bb30_30m_vec[T].lowerband > low_30m_vec.last().unwrap().low_price {
|
|
// filtered_3rd_symbols.push(symbol);
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 4th filtering: 30m RSI 3 < 15, 30m RSI 10 < 35
|
|
// let mut rsi3_30m_vec: Vec<RsiData> = Vec::new();
|
|
// let mut rsi10_30m_vec: Vec<RsiData> = Vec::new();
|
|
// let mut opclo_30m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut filtered_4th_symbols: Vec<String> = Vec::new();
|
|
// for symbol in filtered_3rd_symbols {
|
|
// let rsi3_30m_option = alldata.rsi3_30m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let rsi10_30m_option = alldata.rsi10_30m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let opclo_30m_option = alldata
|
|
// .rt_price_30m_vec
|
|
// .iter()
|
|
// .position(|x| *x.0 == *symbol);
|
|
|
|
// if rsi3_30m_option.is_some() && rsi10_30m_option.is_some() && opclo_30m_option.is_some() {
|
|
// rsi3_30m_vec = alldata.rsi3_30m_data[rsi3_30m_option.unwrap()].1.clone();
|
|
// rsi10_30m_vec = alldata.rsi10_30m_data[rsi10_30m_option.unwrap()].1.clone();
|
|
// opclo_30m_vec = alldata.rt_price_30m_vec[opclo_30m_option.unwrap()]
|
|
// .1
|
|
// .clone();
|
|
|
|
// if rsi3_30m_vec.len() >= 1 && rsi10_30m_vec.len() >= 1 && opclo_30m_vec.len() >= 1 {
|
|
// let result = rsi3_30m_vec.binary_search_by_key(
|
|
// &opclo_30m_vec.last().unwrap().close_time,
|
|
// |&RsiData {
|
|
// rsi_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if rsi3_30m_vec[T].rsi_value < 15.0 {
|
|
// let result = rsi10_30m_vec.binary_search_by_key(
|
|
// &opclo_30m_vec.last().unwrap().close_time,
|
|
// |&RsiData {
|
|
// rsi_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if rsi10_30m_vec[T].rsi_value < 35.0 {
|
|
// filtered_4th_symbols.push(symbol);
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 5th filtering: RSI3_1m < 10, RSI10_1m < 25
|
|
// let mut rsi3_1m_vec: Vec<RsiData> = Vec::new();
|
|
// let mut rsi10_1m_vec: Vec<RsiData> = Vec::new();
|
|
// let mut opclo_30m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut filtered_5th_symbols: Vec<(String, i64)> = Vec::new(); // (symbol, closetime)
|
|
// for symbol in filtered_4th_symbols {
|
|
// let rsi3_1m_option = alldata.rsi3_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let rsi10_1m_option = alldata.rsi10_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let opclo_30m_option = alldata
|
|
// .rt_price_30m_vec
|
|
// .iter()
|
|
// .position(|x| *x.0 == *symbol);
|
|
|
|
// if rsi3_1m_option.is_some() && rsi10_1m_option.is_some() && opclo_30m_option.is_some() {
|
|
// rsi3_1m_vec = alldata.rsi3_1m_data[rsi3_1m_option.unwrap()].1.clone();
|
|
// rsi10_1m_vec = alldata.rsi10_1m_data[rsi10_1m_option.unwrap()].1.clone();
|
|
// opclo_30m_vec = alldata.rt_price_30m_vec[opclo_30m_option.unwrap()]
|
|
// .1
|
|
// .clone();
|
|
|
|
// if rsi3_1m_vec.len() >= 1 && rsi10_1m_vec.len() >= 1 && opclo_30m_vec.len() >= 1 {
|
|
// if rsi3_1m_vec.last().unwrap().rsi_value < 10.0
|
|
// && rsi10_1m_vec.last().unwrap().rsi_value < 25.0
|
|
// {
|
|
// filtered_5th_symbols.push((symbol, opclo_30m_vec.last().unwrap().close_time));
|
|
// }
|
|
// }
|
|
|
|
// // if rsi3_1m_vec.len() >= 1 && rsi10_1m_vec.len() >= 1 && opclo_30m_vec.len() >= 1 {
|
|
// // let result = rsi3_1m_vec.binary_search_by_key(&opclo_30m_vec.last().unwrap().close_time, |&RsiData{rsi_value, close_time}|close_time);
|
|
// // match result {
|
|
// // Ok(T) => {
|
|
// // if rsi3_1m_vec[T].rsi_value < 10.0 {
|
|
// // let result = rsi10_1m_vec.binary_search_by_key(&opclo_30m_vec.last().unwrap().close_time, |&RsiData{rsi_value, close_time}|close_time);
|
|
// // match result {
|
|
// // Ok(T) => {
|
|
// // if rsi10_1m_vec[T].rsi_value < 25.0 {
|
|
// // filtered_5th_symbols.push((symbol, opclo_30m_vec.last().unwrap().close_time));
|
|
// // }
|
|
// // },
|
|
// // Err(E) => {}
|
|
// // }
|
|
// // }
|
|
// // },
|
|
// // Err(E) => {}
|
|
// // }
|
|
// // }
|
|
// }
|
|
// }
|
|
// // // 6. 5th filtering symbols: 30m current vol > 30m previous vol * 2
|
|
// // let mut opclo_30m_vec: Vec<PriceData> = Vec::new();
|
|
// // let mut filtered_5th_symbols: Vec<(String, u64)> = Vec::new(); // (symbol, closetime)
|
|
// // for element in filtered_4th_symbols {
|
|
// // let opclo_30m_result = read_price_into_vector("30m", &element).await;
|
|
|
|
// // if opclo_30m_result.is_ok() {
|
|
// // let opclo_30m_option = opclo_30m_result?;
|
|
// // if opclo_30m_option.is_some() {
|
|
// // opclo_30m_vec = opclo_30m_option.unwrap();
|
|
|
|
// // if opclo_30m_vec.len() >= 2 {
|
|
// // opclo_30m_vec.reverse();
|
|
// // opclo_30m_vec.truncate(2);
|
|
// // opclo_30m_vec.reverse();
|
|
|
|
// // if 2.0 * opclo_30m_vec.first().unwrap().quote_asset_volume < opclo_30m_vec.last().unwrap().quote_asset_volume && opclo_30m_vec.last().unwrap().candle_type == "DOWN" {
|
|
// // filtered_5th_symbols.push((element, opclo_30m_vec.last().unwrap().close_time));
|
|
// // }
|
|
// // }
|
|
// // }
|
|
// // }
|
|
// // }
|
|
// // println!("5: {:?}", filtered_5th_symbols);
|
|
// // 7. insert record into [pre_suggested_coin_list]
|
|
// insert_pre_suggested_coins(15, &filtered_5th_symbols, alldata).await;
|
|
|
|
// Ok(())
|
|
// }
|
|
|
|
// pub async fn strategist_016(
|
|
// alldata: &AllData,
|
|
// ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|
// // [strategist_016 procedure]
|
|
// // 1st filtering: the latest 2 opclo_1d < BB30_1d upper band, current price < previous opclo_1d
|
|
// // 2nd filtering: check 5 samples of candle 30m has DOWN candles at least 4, the latest opclo_30m < EMA3_30m, the latest opclo_30m < SMA30_30m
|
|
// // 3rd filtering: RSI3_30m < 15, RSI10_30m < 35
|
|
// // 4th filtering: RSI3_1m < 10, RSI10_1m < 25
|
|
|
|
// // 1st filtering: the latest 2 opclo_1d < BB30_1d upper band, current price < previous opclo_1d
|
|
// let mut opclo_1d_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut bb30_1d_vec: Vec<BollingerBandData> = Vec::new();
|
|
// let mut filtered_1st_symbols: Vec<String> = Vec::new();
|
|
// let mut current_price: Option<f64>;
|
|
// for symbol in &alldata.valid_symbol_vec {
|
|
// let opclo_1d_option = alldata.rt_price_1d_vec.iter().position(|x| *x.0 == *symbol);
|
|
// let bb30_1d_option = alldata.bb30_1d_data.iter().position(|x| *x.0 == *symbol);
|
|
|
|
// if opclo_1d_option.is_some() && bb30_1d_option.is_some() {
|
|
// opclo_1d_vec = alldata.rt_price_1d_vec[opclo_1d_option.unwrap()].1.clone();
|
|
// bb30_1d_vec = alldata.bb30_1d_data[bb30_1d_option.unwrap()].1.clone();
|
|
|
|
// if opclo_1d_vec.len() >= 2 && bb30_1d_vec.len() >= 2 {
|
|
// opclo_1d_vec.reverse();
|
|
// opclo_1d_vec.truncate(2);
|
|
// opclo_1d_vec.reverse();
|
|
// bb30_1d_vec.reverse();
|
|
// bb30_1d_vec.truncate(2);
|
|
// bb30_1d_vec.reverse();
|
|
|
|
// let result = bb30_1d_vec.binary_search_by_key(
|
|
// &opclo_1d_vec.first().unwrap().close_time,
|
|
// |&BollingerBandData {
|
|
// sma,
|
|
// upperband,
|
|
// lowerband,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// current_price = get_current_price(&symbol, &alldata.price_vec).await;
|
|
|
|
// if current_price.is_some() {
|
|
// if current_price.unwrap().is_normal() {
|
|
// if (bb30_1d_vec[T].upperband
|
|
// > opclo_1d_vec.first().unwrap().opclo_price)
|
|
// && (opclo_1d_vec.first().unwrap().opclo_price
|
|
// > current_price.unwrap())
|
|
// {
|
|
// let result = bb30_1d_vec.binary_search_by_key(
|
|
// &opclo_1d_vec.last().unwrap().close_time,
|
|
// |&BollingerBandData {
|
|
// sma,
|
|
// upperband,
|
|
// lowerband,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if bb30_1d_vec[T].upperband
|
|
// > opclo_1d_vec.last().unwrap().opclo_price
|
|
// {
|
|
// filtered_1st_symbols.push(symbol.clone());
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 2nd filtering: check 5 samples of candle 30m has DOWN candles at least 4, the latest opclo_30m < EMA3_30m, the latest opclo_30m < SMA30_30m
|
|
// let mut opclo_30m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut ema3_30m_vec: Vec<EmaData> = Vec::new();
|
|
// let mut sma30_30m_vec: Vec<SmaData> = Vec::new();
|
|
// let mut filtered_2nd_symbols: Vec<String> = Vec::new();
|
|
// let mut cnt = 0;
|
|
// for symbol in filtered_1st_symbols {
|
|
// let opclo_30m_option = alldata
|
|
// .rt_price_30m_vec
|
|
// .iter()
|
|
// .position(|x| *x.0 == *symbol);
|
|
// let ema3_30m_option = alldata.ema3_30m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let sma30_30m_option = alldata.sma30_30m_data.iter().position(|x| *x.0 == *symbol);
|
|
|
|
// if opclo_30m_option.is_some() && ema3_30m_option.is_some() && sma30_30m_option.is_some() {
|
|
// opclo_30m_vec = alldata.rt_price_30m_vec[opclo_30m_option.unwrap()]
|
|
// .1
|
|
// .clone();
|
|
// ema3_30m_vec = alldata.ema3_30m_data[ema3_30m_option.unwrap()].1.clone();
|
|
// sma30_30m_vec = alldata.sma30_30m_data[sma30_30m_option.unwrap()].1.clone();
|
|
|
|
// if opclo_30m_vec.len() >= 5 && ema3_30m_vec.len() >= 1 && sma30_30m_vec.len() >= 1 {
|
|
// opclo_30m_vec.reverse();
|
|
// opclo_30m_vec.truncate(5);
|
|
// opclo_30m_vec.reverse();
|
|
|
|
// cnt = 0;
|
|
// for element in &opclo_30m_vec {
|
|
// if element.candle_type == "DOWN" {
|
|
// cnt += 1;
|
|
// }
|
|
// }
|
|
|
|
// if cnt >= 4 {
|
|
// let result = ema3_30m_vec.binary_search_by_key(
|
|
// &opclo_30m_vec.last().unwrap().close_time,
|
|
// |&EmaData {
|
|
// ema_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if ema3_30m_vec[T].ema_value > opclo_30m_vec.last().unwrap().opclo_price
|
|
// {
|
|
// let result = sma30_30m_vec.binary_search_by_key(
|
|
// &opclo_30m_vec.last().unwrap().close_time,
|
|
// |&SmaData {
|
|
// sma_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if sma30_30m_vec[T].sma_value
|
|
// > opclo_30m_vec.last().unwrap().opclo_price
|
|
// {
|
|
// filtered_2nd_symbols.push(symbol);
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 3rd filtering: RSI3_30m < 15, RSI10_30m < 35
|
|
// let mut rsi3_30m_vec: Vec<RsiData> = Vec::new();
|
|
// let mut rsi10_30m_vec: Vec<RsiData> = Vec::new();
|
|
// let mut opclo_30m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut filtered_3rd_symbols: Vec<String> = Vec::new();
|
|
// for symbol in filtered_2nd_symbols {
|
|
// let rsi3_30m_option = alldata.rsi3_30m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let rsi10_30m_option = alldata.rsi10_30m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let opclo_30m_option = alldata
|
|
// .rt_price_30m_vec
|
|
// .iter()
|
|
// .position(|x| *x.0 == *symbol);
|
|
|
|
// if rsi3_30m_option.is_some() && rsi10_30m_option.is_some() && opclo_30m_option.is_some() {
|
|
// rsi3_30m_vec = alldata.rsi3_30m_data[rsi3_30m_option.unwrap()].1.clone();
|
|
// rsi10_30m_vec = alldata.rsi10_30m_data[rsi10_30m_option.unwrap()].1.clone();
|
|
// opclo_30m_vec = alldata.rt_price_30m_vec[opclo_30m_option.unwrap()]
|
|
// .1
|
|
// .clone();
|
|
|
|
// if rsi3_30m_vec.len() >= 1 && rsi10_30m_vec.len() >= 1 && opclo_30m_vec.len() >= 1 {
|
|
// let result = rsi3_30m_vec.binary_search_by_key(
|
|
// &opclo_30m_vec.last().unwrap().close_time,
|
|
// |&RsiData {
|
|
// rsi_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if rsi3_30m_vec[T].rsi_value < 15.0 {
|
|
// let result = rsi10_30m_vec.binary_search_by_key(
|
|
// &opclo_30m_vec.last().unwrap().close_time,
|
|
// |&RsiData {
|
|
// rsi_value,
|
|
// close_time,
|
|
// }| close_time,
|
|
// );
|
|
// match result {
|
|
// Ok(T) => {
|
|
// if rsi10_30m_vec[T].rsi_value < 35.0 {
|
|
// filtered_3rd_symbols.push(symbol);
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// Err(E) => {}
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// // 4th filtering: RSI3_1m < 10, RSI10_1m < 25
|
|
// let mut rsi3_1m_vec: Vec<RsiData> = Vec::new();
|
|
// let mut rsi10_1m_vec: Vec<RsiData> = Vec::new();
|
|
// let mut opclo_30m_vec: Vec<RealtimePriceData> = Vec::new();
|
|
// let mut filtered_4th_symbols: Vec<(String, i64)> = Vec::new(); // (symbol, closetime)
|
|
// for symbol in filtered_3rd_symbols {
|
|
// let rsi3_1m_option = alldata.rsi3_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let rsi10_1m_option = alldata.rsi10_1m_data.iter().position(|x| *x.0 == *symbol);
|
|
// let opclo_30m_option = alldata
|
|
// .rt_price_30m_vec
|
|
// .iter()
|
|
// .position(|x| *x.0 == *symbol);
|
|
|
|
// if rsi3_1m_option.is_some() && rsi10_1m_option.is_some() && opclo_30m_option.is_some() {
|
|
// rsi3_1m_vec = alldata.rsi3_1m_data[rsi3_1m_option.unwrap()].1.clone();
|
|
// rsi10_1m_vec = alldata.rsi10_1m_data[rsi10_1m_option.unwrap()].1.clone();
|
|
// opclo_30m_vec = alldata.rt_price_30m_vec[opclo_30m_option.unwrap()]
|
|
// .1
|
|
// .clone();
|
|
|
|
// if rsi3_1m_vec.len() >= 1 && rsi10_1m_vec.len() >= 1 && opclo_30m_vec.len() >= 1 {
|
|
// if rsi3_1m_vec.last().unwrap().rsi_value < 10.0
|
|
// && rsi10_1m_vec.last().unwrap().rsi_value < 25.0
|
|
// {
|
|
// filtered_4th_symbols.push((symbol, opclo_30m_vec.last().unwrap().close_time));
|
|
// }
|
|
// }
|
|
|
|
// // if rsi3_1m_vec.len() >= 1 && rsi10_1m_vec.len() >= 1 && opclo_30m_vec.len() >= 1 {
|
|
// // let result = rsi3_1m_vec.binary_search_by_key(&opclo_30m_vec.last().unwrap().close_time, |&RsiData{rsi_value, close_time}|close_time);
|
|
// // match result {
|
|
// // Ok(T) => {
|
|
// // if rsi3_1m_vec[T].rsi_value < 10.0 {
|
|
// // let result = rsi10_1m_vec.binary_search_by_key(&opclo_30m_vec.last().unwrap().close_time, |&RsiData{rsi_value, close_time}|close_time);
|
|
// // match result {
|
|
// // Ok(T) => {
|
|
// // if rsi10_1m_vec[T].rsi_value < 25.0 {
|
|
// // filtered_5th_symbols.push((symbol, opclo_30m_vec.last().unwrap().close_time));
|
|
// // }
|
|
// // },
|
|
// // Err(E) => {}
|
|
// // }
|
|
// // }
|
|
// // },
|
|
// // Err(E) => {}
|
|
// // }
|
|
// // }
|
|
// }
|
|
// }
|
|
|
|
// // // 6. 5th filtering symbols: 30m current vol > 30m previous vol * 2
|
|
// // let mut opclo_30m_vec: Vec<PriceData> = Vec::new();
|
|
// // let mut filtered_4th_symbols: Vec<(String, u64)> = Vec::new(); // (symbol, closetime)
|
|
// // for element in filtered_3rd_symbols {
|
|
// // let opclo_30m_result = read_price_into_vector("30m", &element).await;
|
|
|
|
// // if opclo_30m_result.is_ok() {
|
|
// // let opclo_30m_option = opclo_30m_result?;
|
|
// // if opclo_30m_option.is_some() {
|
|
// // opclo_30m_vec = opclo_30m_option.unwrap();
|
|
|
|
// // if opclo_30m_vec.len() >= 2 {
|
|
// // opclo_30m_vec.reverse();
|
|
// // opclo_30m_vec.truncate(2);
|
|
// // opclo_30m_vec.reverse();
|
|
|
|
// // if 2.0 * opclo_30m_vec.first().unwrap().quote_asset_volume < opclo_30m_vec.last().unwrap().quote_asset_volume && opclo_30m_vec.last().unwrap().candle_type == "DOWN" {
|
|
// // filtered_4th_symbols.push((element, opclo_30m_vec.last().unwrap().close_time));
|
|
// // }
|
|
// // }
|
|
// // }
|
|
// // }
|
|
// // }
|
|
// // println!("4: {:?}", filtered_4th_symbols);
|
|
// // 7. insert record into [pre_suggested_coin_list]
|
|
// insert_pre_suggested_coins(16, &filtered_4th_symbols, alldata).await;
|
|
|
|
// Ok(())
|
|
// }
|
|
|
|
// useful functions for strategists
|
|
pub async fn get_current_price(symbol: &String, rt_price_vec: &Vec<(String, Vec<RealtimePriceData>)>) -> Option<f64> {
|
|
let index_result = rt_price_vec.iter().position(|x| *x.0 == *symbol);
|
|
match index_result {
|
|
Some(T) => {
|
|
if rt_price_vec[T].1.last().is_some() {
|
|
Some(rt_price_vec[T].1.last().unwrap().close_price)
|
|
} else {
|
|
None
|
|
}
|
|
},
|
|
None => None,
|
|
}
|
|
}
|
|
|
|
async fn insert_pre_suggested_coins(
|
|
registerer: i32,
|
|
filtered_symbols: &Vec<(String, i64, f64)>,
|
|
alldata: &AllData,
|
|
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|
// Check the existance of record that is registered by this strategist
|
|
let mut dest_table_name = String::from("suggested_coin_list");
|
|
let mut dest2_table_name = String::from("buy_ordered_coin_list");
|
|
let mut dest3_table_name = String::from("pre_suggested_coin_list");
|
|
let mut insert_table_name = String::from("pre_suggested_coin_list");
|
|
let mut exists_condition_build = String::from("registerer=");
|
|
exists_condition_build.push_str(registerer.to_string().as_str());
|
|
let mut exists_condition = Some(exists_condition_build);
|
|
let exists_result1 = exists_record(&dest_table_name, &exists_condition).await;
|
|
let exists_result2 = exists_record(&dest2_table_name, &exists_condition).await;
|
|
let exists_result3 = exists_record(&dest3_table_name, &exists_condition).await;
|
|
let insert_columns = vec![
|
|
"symbol",
|
|
"close_time",
|
|
"suggested_price",
|
|
"current_price",
|
|
"registered_server_epoch",
|
|
"profit_percent",
|
|
"minimum_profit_percent",
|
|
"maximum_profit_percent",
|
|
"registerer",
|
|
];
|
|
|
|
if exists_result1 == true && exists_result2 == true && exists_result3 == true {
|
|
// Bring the current list of pre-suggested coins from [pre_suggested_coin_list] and [ordered_coin_list]
|
|
#[derive(FromRow)]
|
|
struct SelectData {
|
|
symbol: String,
|
|
close_time: i64,
|
|
}
|
|
#[derive(FromRow)]
|
|
struct SelectData2 {
|
|
symbol: String,
|
|
close_time: i64,
|
|
}
|
|
let mut select_columns = String::from("symbol, close_time");
|
|
let mut condition_build = String::from("WHERE registerer=");
|
|
condition_build.push_str(registerer.to_string().as_str());
|
|
let select_condition = Some(condition_build);
|
|
let select_data_structure = SelectData {
|
|
symbol: String::new(),
|
|
close_time: 0,
|
|
};
|
|
let mut select_columns2 = String::from("symbol, close_time");
|
|
let select_data_structure2 = SelectData2 {
|
|
symbol: String::new(),
|
|
close_time: 0,
|
|
};
|
|
let suggested_coin_list = try_select_record(
|
|
&dest_table_name,
|
|
&select_columns,
|
|
&select_condition,
|
|
&select_data_structure,
|
|
)
|
|
.await?;
|
|
let ordered_coin_list = try_select_record(
|
|
&dest2_table_name,
|
|
&select_columns2,
|
|
&select_condition,
|
|
&select_data_structure2,
|
|
)
|
|
.await?;
|
|
let pre_suggested_coin_list = try_select_record(
|
|
&dest3_table_name,
|
|
&select_columns,
|
|
&select_condition,
|
|
&select_data_structure,
|
|
)
|
|
.await?;
|
|
|
|
// insert record without duplicate(registerer, closetime, symbol) into [pre_suggested_coin_list]
|
|
for filtered_element in filtered_symbols {
|
|
let mut is_dupe = false; // initialize
|
|
|
|
for list_element in &suggested_coin_list {
|
|
if (filtered_element.0 == list_element.symbol)
|
|
&& (filtered_element.1 == list_element.close_time)
|
|
{
|
|
is_dupe = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
for list_element in &ordered_coin_list {
|
|
if (filtered_element.0 == list_element.symbol)
|
|
&& (filtered_element.1 == list_element.close_time)
|
|
{
|
|
is_dupe = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
for list_element in &pre_suggested_coin_list {
|
|
if (filtered_element.0 == list_element.symbol)
|
|
&& (filtered_element.1 == list_element.close_time)
|
|
{
|
|
is_dupe = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if is_dupe == false {
|
|
let insert_values = vec![
|
|
filtered_element.0.clone(), // symbol
|
|
filtered_element.1.to_string(), // close_time
|
|
filtered_element.2.to_string(), // suggested_price
|
|
filtered_element.2.to_string(), // current_price
|
|
server_epoch().await.to_string(), // registered_server_epoch
|
|
0.0.to_string(), // profit_percent
|
|
0.0.to_string(), // minimum_profit_percent
|
|
0.0.to_string(), // maximum_profit_percent
|
|
registerer.to_string(), // registerer
|
|
];
|
|
insert_one_record(&insert_table_name, &insert_columns, &insert_values).await;
|
|
}
|
|
}
|
|
} else if exists_result1 == true && exists_result2 == true && exists_result3 == false {
|
|
// Bring the current list of pre-suggested coins from [pre_suggested_coin_list] and [ordered_coin_list]
|
|
#[derive(FromRow)]
|
|
struct SelectData {
|
|
symbol: String,
|
|
close_time: i64,
|
|
}
|
|
#[derive(FromRow)]
|
|
struct SelectData2 {
|
|
symbol: String,
|
|
close_time: i64,
|
|
}
|
|
let mut select_columns = String::from("symbol, close_time");
|
|
let mut condition_build = String::from("WHERE registerer=");
|
|
condition_build.push_str(registerer.to_string().as_str());
|
|
let select_condition = Some(condition_build);
|
|
let select_data_structure = SelectData {
|
|
symbol: String::new(),
|
|
close_time: 0,
|
|
};
|
|
let mut select_columns2 = String::from("symbol, close_time");
|
|
let select_data_structure2 = SelectData2 {
|
|
symbol: String::new(),
|
|
close_time: 0,
|
|
};
|
|
let suggested_coin_list = try_select_record(
|
|
&dest_table_name,
|
|
&select_columns,
|
|
&select_condition,
|
|
&select_data_structure,
|
|
)
|
|
.await?;
|
|
let ordered_coin_list = try_select_record(
|
|
&dest2_table_name,
|
|
&select_columns2,
|
|
&select_condition,
|
|
&select_data_structure2,
|
|
)
|
|
.await?;
|
|
|
|
// insert record without duplicate(registerer, closetime, symbol) into [pre_suggested_coin_list]
|
|
for filtered_element in filtered_symbols {
|
|
let mut is_dupe = false; // initialize
|
|
|
|
for list_element in &suggested_coin_list {
|
|
if (filtered_element.0 == list_element.symbol)
|
|
&& (filtered_element.1 == list_element.close_time)
|
|
{
|
|
is_dupe = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
for list_element in &ordered_coin_list {
|
|
if (filtered_element.0 == list_element.symbol)
|
|
&& (filtered_element.1 == list_element.close_time)
|
|
{
|
|
is_dupe = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if is_dupe == false {
|
|
let insert_values = vec![
|
|
filtered_element.0.clone(), // symbol
|
|
filtered_element.1.to_string(), // close_time
|
|
filtered_element.2.to_string(), // suggested_price
|
|
filtered_element.2.to_string(), // current_price
|
|
server_epoch().await.to_string(), // registered_server_epoch
|
|
0.0.to_string(), // profit_percent
|
|
0.0.to_string(), // minimum_profit_percent
|
|
0.0.to_string(), // maximum_profit_percent
|
|
registerer.to_string(), // registerer
|
|
];
|
|
insert_one_record(&insert_table_name, &insert_columns, &insert_values).await;
|
|
}
|
|
}
|
|
} else if exists_result1 == true && exists_result2 == false && exists_result3 == true {
|
|
// Bring the current list of pre-suggested coins from [pre_suggested_coin_list] and [ordered_coin_list]
|
|
#[derive(FromRow)]
|
|
struct SelectData {
|
|
symbol: String,
|
|
close_time: i64,
|
|
}
|
|
let mut select_columns = String::from("symbol, close_time");
|
|
let mut condition_build = String::from("WHERE registerer=");
|
|
condition_build.push_str(registerer.to_string().as_str());
|
|
let select_condition = Some(condition_build);
|
|
let select_data_structure = SelectData {
|
|
symbol: String::new(),
|
|
close_time: 0,
|
|
};
|
|
let suggested_coin_list = try_select_record(
|
|
&dest_table_name,
|
|
&select_columns,
|
|
&select_condition,
|
|
&select_data_structure,
|
|
)
|
|
.await?;
|
|
let pre_suggested_coin_list = try_select_record(
|
|
&dest3_table_name,
|
|
&select_columns,
|
|
&select_condition,
|
|
&select_data_structure,
|
|
)
|
|
.await?;
|
|
|
|
// insert record without duplicate(registerer, closetime, symbol) into [pre_suggested_coin_list]
|
|
for filtered_element in filtered_symbols {
|
|
let mut is_dupe = false; // initialize
|
|
|
|
for list_element in &suggested_coin_list {
|
|
if (filtered_element.0 == list_element.symbol)
|
|
&& (filtered_element.1 == list_element.close_time)
|
|
{
|
|
is_dupe = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
for list_element in &pre_suggested_coin_list {
|
|
if (filtered_element.0 == list_element.symbol)
|
|
&& (filtered_element.1 == list_element.close_time)
|
|
{
|
|
is_dupe = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if is_dupe == false {
|
|
let insert_values = vec![
|
|
filtered_element.0.clone(), // symbol
|
|
filtered_element.1.to_string(), // close_time
|
|
filtered_element.2.to_string(), // suggested_price
|
|
filtered_element.2.to_string(), // current_price
|
|
server_epoch().await.to_string(), // registered_server_epoch
|
|
0.0.to_string(), // profit_percent
|
|
0.0.to_string(), // minimum_profit_percent
|
|
0.0.to_string(), // maximum_profit_percent
|
|
registerer.to_string(), // registerer
|
|
];
|
|
insert_one_record(&insert_table_name, &insert_columns, &insert_values).await;
|
|
}
|
|
}
|
|
} else if exists_result1 == true && exists_result2 == false && exists_result3 == false {
|
|
// Bring the current list of pre-suggested coins from [pre_suggested_coin_list] and [ordered_coin_list]
|
|
#[derive(FromRow)]
|
|
struct SelectData {
|
|
symbol: String,
|
|
close_time: i64,
|
|
}
|
|
let mut select_columns = String::from("symbol, close_time");
|
|
let mut condition_build = String::from("WHERE registerer=");
|
|
condition_build.push_str(registerer.to_string().as_str());
|
|
let select_condition = Some(condition_build);
|
|
let select_data_structure = SelectData {
|
|
symbol: String::new(),
|
|
close_time: 0,
|
|
};
|
|
let suggested_coin_list = try_select_record(
|
|
&dest_table_name,
|
|
&select_columns,
|
|
&select_condition,
|
|
&select_data_structure,
|
|
)
|
|
.await?;
|
|
|
|
// insert record without duplicate(registerer, closetime, symbol) into [pre_suggested_coin_list]
|
|
for filtered_element in filtered_symbols {
|
|
let mut is_dupe = false; // initialize
|
|
|
|
for list_element in &suggested_coin_list {
|
|
if (filtered_element.0 == list_element.symbol)
|
|
&& (filtered_element.1 == list_element.close_time)
|
|
{
|
|
is_dupe = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if is_dupe == false {
|
|
let insert_values = vec![
|
|
filtered_element.0.clone(), // symbol
|
|
filtered_element.1.to_string(), // close_time
|
|
filtered_element.2.to_string(), // suggested_price
|
|
filtered_element.2.to_string(), // current_price
|
|
server_epoch().await.to_string(), // registered_server_epoch
|
|
0.0.to_string(), // profit_percent
|
|
0.0.to_string(), // minimum_profit_percent
|
|
0.0.to_string(), // maximum_profit_percent
|
|
registerer.to_string(), // registerer
|
|
];
|
|
insert_one_record(&insert_table_name, &insert_columns, &insert_values).await;
|
|
}
|
|
}
|
|
} else if exists_result1 == false && exists_result2 == true && exists_result3 == true {
|
|
// Bring the current list of pre-suggested coins from [pre_suggested_coin_list] and [ordered_coin_list]
|
|
#[derive(FromRow)]
|
|
struct SelectData {
|
|
symbol: String,
|
|
close_time: i64,
|
|
}
|
|
#[derive(FromRow)]
|
|
struct SelectData2 {
|
|
symbol: String,
|
|
close_time: i64,
|
|
}
|
|
let mut select_columns = String::from("symbol, close_time");
|
|
let mut condition_build = String::from("WHERE registerer=");
|
|
condition_build.push_str(registerer.to_string().as_str());
|
|
let select_condition = Some(condition_build);
|
|
let select_data_structure = SelectData {
|
|
symbol: String::new(),
|
|
close_time: 0,
|
|
};
|
|
let mut select_columns2 = String::from("symbol, close_time");
|
|
let select_data_structure2 = SelectData2 {
|
|
symbol: String::new(),
|
|
close_time: 0,
|
|
};
|
|
let ordered_coin_list = try_select_record(
|
|
&dest2_table_name,
|
|
&select_columns2,
|
|
&select_condition,
|
|
&select_data_structure2,
|
|
)
|
|
.await?;
|
|
let pre_suggested_coin_list = try_select_record(
|
|
&dest3_table_name,
|
|
&select_columns,
|
|
&select_condition,
|
|
&select_data_structure,
|
|
)
|
|
.await?;
|
|
|
|
// insert record without duplicate(registerer, close_time, symbol) into [pre_suggested_coin_list]
|
|
for filtered_element in filtered_symbols {
|
|
let mut is_dupe = false; // initialize
|
|
|
|
for list_element in &ordered_coin_list {
|
|
if (filtered_element.0 == list_element.symbol)
|
|
&& (filtered_element.1 == list_element.close_time)
|
|
{
|
|
is_dupe = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
for list_element in &pre_suggested_coin_list {
|
|
if (filtered_element.0 == list_element.symbol)
|
|
&& (filtered_element.1 == list_element.close_time)
|
|
{
|
|
is_dupe = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if is_dupe == false {
|
|
let insert_values = vec![
|
|
filtered_element.0.clone(), // symbol
|
|
filtered_element.1.to_string(), // close_time
|
|
filtered_element.2.to_string(), // suggested_price
|
|
filtered_element.2.to_string(), // current_price
|
|
server_epoch().await.to_string(), // registered_server_epoch
|
|
0.0.to_string(), // profit_percent
|
|
0.0.to_string(), // minimum_profit_percent
|
|
0.0.to_string(), // maximum_profit_percent
|
|
registerer.to_string(), // registerer
|
|
];
|
|
insert_one_record(&insert_table_name, &insert_columns, &insert_values).await;
|
|
}
|
|
}
|
|
} else if exists_result1 == false && exists_result2 == true && exists_result3 == false {
|
|
// Bring the current list of pre-suggested coins from [pre_suggested_coin_list] and [ordered_coin_list]
|
|
#[derive(FromRow)]
|
|
struct SelectData {
|
|
symbol: String,
|
|
close_time: i64,
|
|
}
|
|
#[derive(FromRow)]
|
|
struct SelectData2 {
|
|
symbol: String,
|
|
close_time: i64,
|
|
}
|
|
let mut select_columns = String::from("symbol, close_time");
|
|
let mut condition_build = String::from("WHERE registerer=");
|
|
condition_build.push_str(registerer.to_string().as_str());
|
|
let select_condition = Some(condition_build);
|
|
let select_data_structure = SelectData {
|
|
symbol: String::new(),
|
|
close_time: 0,
|
|
};
|
|
let mut select_columns2 = String::from("symbol, close_time");
|
|
let select_data_structure2 = SelectData2 {
|
|
symbol: String::new(),
|
|
close_time: 0,
|
|
};
|
|
let ordered_coin_list = try_select_record(
|
|
&dest2_table_name,
|
|
&select_columns2,
|
|
&select_condition,
|
|
&select_data_structure2,
|
|
)
|
|
.await?;
|
|
|
|
// insert record without duplicate(registerer, closetime, symbol) into [pre_suggested_coin_list]
|
|
for filtered_element in filtered_symbols {
|
|
let mut is_dupe = false; // initialize
|
|
|
|
for list_element in &ordered_coin_list {
|
|
if (filtered_element.0 == list_element.symbol)
|
|
&& (filtered_element.1 == list_element.close_time)
|
|
{
|
|
is_dupe = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if is_dupe == false {
|
|
let insert_values = vec![
|
|
filtered_element.0.clone(), // symbol
|
|
filtered_element.1.to_string(), // close_time
|
|
filtered_element.2.to_string(), // suggested_price
|
|
filtered_element.2.to_string(), // current_price
|
|
server_epoch().await.to_string(), // registered_server_epoch
|
|
0.0.to_string(), // profit_percent
|
|
0.0.to_string(), // minimum_profit_percent
|
|
0.0.to_string(), // maximum_profit_percent
|
|
registerer.to_string(), // registerer
|
|
];
|
|
insert_one_record(&insert_table_name, &insert_columns, &insert_values).await;
|
|
}
|
|
}
|
|
} else if exists_result1 == false && exists_result2 == false && exists_result3 == true {
|
|
// Bring the current list of pre-suggested coins from [pre_suggested_coin_list] and [ordered_coin_list]
|
|
#[derive(FromRow)]
|
|
struct SelectData {
|
|
symbol: String,
|
|
close_time: i64,
|
|
}
|
|
let mut select_columns = String::from("symbol, close_time");
|
|
let mut condition_build = String::from("WHERE registerer=");
|
|
condition_build.push_str(registerer.to_string().as_str());
|
|
let select_condition = Some(condition_build);
|
|
let select_data_structure = SelectData {
|
|
symbol: String::new(),
|
|
close_time: 0,
|
|
};
|
|
let pre_suggested_coin_list = try_select_record(
|
|
&dest3_table_name,
|
|
&select_columns,
|
|
&select_condition,
|
|
&select_data_structure,
|
|
)
|
|
.await?;
|
|
|
|
// insert record without duplicate(registerer, closetime, symbol) into [pre_suggested_coin_list]
|
|
for filtered_element in filtered_symbols {
|
|
let mut is_dupe = false; // initialize
|
|
|
|
for list_element in &pre_suggested_coin_list {
|
|
if (filtered_element.0 == list_element.symbol)
|
|
&& (filtered_element.1 == list_element.close_time)
|
|
{
|
|
is_dupe = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if is_dupe == false {
|
|
let insert_values = vec![
|
|
filtered_element.0.clone(), // symbol
|
|
filtered_element.1.to_string(), // close_time
|
|
filtered_element.2.to_string(), // suggested_price
|
|
filtered_element.2.to_string(), // current_price
|
|
server_epoch().await.to_string(), // registered_server_epoch
|
|
0.0.to_string(), // profit_percent
|
|
0.0.to_string(), // minimum_profit_percent
|
|
0.0.to_string(), // maximum_profit_percent
|
|
registerer.to_string(), // registerer
|
|
];
|
|
insert_one_record(&insert_table_name, &insert_columns, &insert_values).await;
|
|
}
|
|
}
|
|
} else {
|
|
for filtered_element in filtered_symbols {
|
|
let insert_values = vec![
|
|
filtered_element.0.clone(), // symbol
|
|
filtered_element.1.to_string(), // close_time
|
|
filtered_element.2.to_string(), // suggested_price
|
|
filtered_element.2.to_string(), // current_price
|
|
server_epoch().await.to_string(), // registered_server_epoch
|
|
0.0.to_string(), // profit_percent
|
|
0.0.to_string(), // minimum_profit_percent
|
|
0.0.to_string(), // maximum_profit_percent
|
|
registerer.to_string(), // registerer
|
|
];
|
|
insert_one_record(&insert_table_name, &insert_columns, &insert_values).await;
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|