Formatting
This commit is contained in:
parent
e85690fd41
commit
23066cf0f3
|
|
@ -6,12 +6,12 @@ use crate::database_control::*;
|
|||
use crate::decimal_funcs::*;
|
||||
use crate::RunningMode::*;
|
||||
use crate::RUNNING_MODE;
|
||||
use log;
|
||||
use reqwest::Client;
|
||||
use rust_decimal::{prelude::ToPrimitive, Decimal, RoundingStrategy};
|
||||
use rust_decimal_macros::dec;
|
||||
use serde_json::{Result, Value};
|
||||
use sqlx::FromRow;
|
||||
use log;
|
||||
|
||||
#[derive(Debug, FromRow)]
|
||||
pub struct AchievementEvaluationInfo {
|
||||
|
|
@ -156,7 +156,7 @@ pub async fn add_extra_usdt(extra_usdt: Decimal) {
|
|||
|
||||
// add additional_usdt into [wallet_simul]
|
||||
let mut update_table_name = String::new();
|
||||
unsafe{
|
||||
unsafe {
|
||||
if RUNNING_MODE == SIMUL {
|
||||
let update_table_name = String::from("wallet");
|
||||
let mut value_build = String::from("free + ");
|
||||
|
|
@ -541,7 +541,7 @@ pub async fn select_asset_manage_announcement() -> AssetInfo {
|
|||
pub async fn fetch_free_usdt() -> Decimal {
|
||||
let wallet_info = WalletInfo::new();
|
||||
let select_table_name = {
|
||||
unsafe{
|
||||
unsafe {
|
||||
if RUNNING_MODE == SIMUL || RUNNING_MODE == REAL {
|
||||
String::from("wallet")
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -257,7 +257,9 @@ pub async fn buy_coin(
|
|||
.unwrap();
|
||||
for element in &filtered_suggested_coin_vec {
|
||||
if is_tradable == true {
|
||||
if exchange_info_map.contains_key(&element.symbol) && trade_fee_map.contains_key(&element.symbol) {
|
||||
if exchange_info_map.contains_key(&element.symbol)
|
||||
&& trade_fee_map.contains_key(&element.symbol)
|
||||
{
|
||||
let exchange_info = exchange_info_map.get(&element.symbol).unwrap();
|
||||
let lot_step_size = exchange_info.stepsize;
|
||||
let tick_size = exchange_info.ticksize;
|
||||
|
|
@ -375,10 +377,15 @@ pub async fn buy_coin_for_test(
|
|||
|
||||
let insert_table_name = String::from("buy_ordered_coin_list");
|
||||
for element in &filtered_suggested_coin_vec {
|
||||
if exchange_info_map.contains_key(&element.symbol) && trade_fee_map.contains_key(&element.symbol){
|
||||
if exchange_info_map.contains_key(&element.symbol)
|
||||
&& trade_fee_map.contains_key(&element.symbol)
|
||||
{
|
||||
let lot_step_size = exchange_info_map.get(&element.symbol).unwrap().stepsize;
|
||||
let tick_size = exchange_info_map.get(&element.symbol).unwrap().ticksize;
|
||||
let base_commission_precision = exchange_info_map.get(&element.symbol).unwrap().base_commission_precision;
|
||||
let base_commission_precision = exchange_info_map
|
||||
.get(&element.symbol)
|
||||
.unwrap()
|
||||
.base_commission_precision;
|
||||
let trade_fee = trade_fee_map.get(&element.symbol).unwrap().takercommission;
|
||||
|
||||
// buy the suggested coin and transfer it into [buy_ordered_coin_list]
|
||||
|
|
@ -387,8 +394,10 @@ pub async fn buy_coin_for_test(
|
|||
// let order_price = current_price;
|
||||
let order_price = element.suggested_price;
|
||||
|
||||
base_qty_ordered = decimal_div(unit_trade_usdt, order_price)
|
||||
.round_dp_with_strategy(lot_step_size.normalize().scale(), RoundingStrategy::ToZero);
|
||||
base_qty_ordered = decimal_div(unit_trade_usdt, order_price).round_dp_with_strategy(
|
||||
lot_step_size.normalize().scale(),
|
||||
RoundingStrategy::ToZero,
|
||||
);
|
||||
base_qty_fee_adjusted = decimal_mul(base_qty_ordered, decimal_sub(dec!(1), trade_fee))
|
||||
.round_dp_with_strategy(base_commission_precision, RoundingStrategy::ToZero);
|
||||
used_usdt = decimal_mul(base_qty_ordered, order_price)
|
||||
|
|
@ -865,7 +874,8 @@ pub async fn update_profit_percent() {
|
|||
profit_percent = (decimal_sub(
|
||||
decimal_div(element.usdt_profit, element.invested_usdt),
|
||||
dec!(1),
|
||||
)).round_dp(2)
|
||||
))
|
||||
.round_dp(2)
|
||||
.to_f64()
|
||||
.unwrap()
|
||||
* 100.0;
|
||||
|
|
|
|||
|
|
@ -24,14 +24,14 @@ use crate::value_estimation_team::indicators::supertrend::{supertrend, Supertren
|
|||
use futures::future::try_join_all;
|
||||
use hex::ToHex;
|
||||
use hmac_sha256::HMAC;
|
||||
use log;
|
||||
use reqwest::{Client, ClientBuilder};
|
||||
use rust_decimal::{prelude::FromPrimitive, prelude::ToPrimitive, Decimal, RoundingStrategy};
|
||||
use rust_decimal_macros::dec;
|
||||
use serde_json::Value;
|
||||
use sqlx::FromRow;
|
||||
use tokio::time::*;
|
||||
use std::collections::HashMap;
|
||||
use log;
|
||||
use tokio::time::*;
|
||||
|
||||
pub enum OrderSide {
|
||||
Buy,
|
||||
|
|
@ -199,7 +199,7 @@ pub async fn limit_order_buy_test(
|
|||
// building URL and API-keys
|
||||
let mut url = String::new();
|
||||
let mut api_key = String::new();
|
||||
unsafe{
|
||||
unsafe {
|
||||
if RUNNING_MODE == TEST {
|
||||
url.push_str(URL_TEST);
|
||||
api_key = API_KEY_TESTNET.to_string();
|
||||
|
|
@ -598,15 +598,23 @@ async fn update_repeat_task(
|
|||
for element in buy_ordered_coin_vec {
|
||||
// build update values
|
||||
update_record_build.clear();
|
||||
if coin_price_map.contains_key(&element.symbol) && exchange_info_map.contains_key(&element.symbol) && trade_fee_map.contains_key(&element.symbol) {
|
||||
price = rust_decimal::prelude::FromPrimitive::from_f64(*coin_price_map.get(&element.symbol).unwrap()).unwrap();
|
||||
if coin_price_map.contains_key(&element.symbol)
|
||||
&& exchange_info_map.contains_key(&element.symbol)
|
||||
&& trade_fee_map.contains_key(&element.symbol)
|
||||
{
|
||||
price = rust_decimal::prelude::FromPrimitive::from_f64(
|
||||
*coin_price_map.get(&element.symbol).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
if !price.is_zero() {
|
||||
// to get quote_commission_precision
|
||||
let trade_fee = trade_fee_map.get(&element.symbol).unwrap().takercommission;
|
||||
let lot_step_size = exchange_info_map.get(&element.symbol).unwrap().stepsize;
|
||||
let quote_commission_precision = exchange_info_map.get(&element.symbol).unwrap().quote_commission_precision;
|
||||
let base_qty_to_be_ordered =
|
||||
element.base_qty_fee_adjusted.round_dp_with_strategy(
|
||||
let quote_commission_precision = exchange_info_map
|
||||
.get(&element.symbol)
|
||||
.unwrap()
|
||||
.quote_commission_precision;
|
||||
let base_qty_to_be_ordered = element.base_qty_fee_adjusted.round_dp_with_strategy(
|
||||
lot_step_size.normalize().scale(),
|
||||
RoundingStrategy::ToZero,
|
||||
);
|
||||
|
|
@ -705,9 +713,17 @@ pub async fn limit_order_sell(
|
|||
let mut insert_value_container: Vec<String> = Vec::new();
|
||||
unsafe {
|
||||
if RUNNING_MODE == SIMUL && buy_ordered_coin.status == "SIMUL" {
|
||||
if exchange_info_map.contains_key(&buy_ordered_coin.symbol) && trade_fee_map.contains_key(&buy_ordered_coin.symbol) {
|
||||
let quote_asset_precision = exchange_info_map.get(&buy_ordered_coin.symbol).unwrap().quote_asset_precision;
|
||||
let trade_fee = trade_fee_map.get(&buy_ordered_coin.symbol).unwrap().takercommission;
|
||||
if exchange_info_map.contains_key(&buy_ordered_coin.symbol)
|
||||
&& trade_fee_map.contains_key(&buy_ordered_coin.symbol)
|
||||
{
|
||||
let quote_asset_precision = exchange_info_map
|
||||
.get(&buy_ordered_coin.symbol)
|
||||
.unwrap()
|
||||
.quote_asset_precision;
|
||||
let trade_fee = trade_fee_map
|
||||
.get(&buy_ordered_coin.symbol)
|
||||
.unwrap()
|
||||
.takercommission;
|
||||
|
||||
let get_usdt = decimal_mul(sell_base_quantity, sell_base_price)
|
||||
.round_dp_with_strategy(quote_asset_precision, RoundingStrategy::ToZero);
|
||||
|
|
@ -735,7 +751,8 @@ pub async fn limit_order_sell(
|
|||
dec!(1),
|
||||
),
|
||||
dec!(100),
|
||||
).round_dp(2);
|
||||
)
|
||||
.round_dp(2);
|
||||
insert_value_container.push(pure_profit_percent.to_string()); // pure_profit_percent
|
||||
insert_value_container.push(buy_ordered_coin.maximum_profit_percent.to_string()); // maximum_profit_percent
|
||||
insert_value_container.push(buy_ordered_coin.registerer.to_string()); // registerer
|
||||
|
|
@ -811,9 +828,17 @@ pub async fn limit_order_sell(
|
|||
.push(T.get("status").unwrap().as_str().unwrap().to_string()); // status
|
||||
insert_value_container.push(buy_ordered_coin.used_usdt.to_string()); // used_usdt
|
||||
|
||||
if exchange_info_map.contains_key(&buy_ordered_coin.symbol) && trade_fee_map.contains_key(&buy_ordered_coin.symbol) {
|
||||
let quote_asset_precision = exchange_info_map.get(&buy_ordered_coin.symbol).unwrap().quote_asset_precision;
|
||||
let trade_fee = trade_fee_map.get(&buy_ordered_coin.symbol).unwrap().takercommission;
|
||||
if exchange_info_map.contains_key(&buy_ordered_coin.symbol)
|
||||
&& trade_fee_map.contains_key(&buy_ordered_coin.symbol)
|
||||
{
|
||||
let quote_asset_precision = exchange_info_map
|
||||
.get(&buy_ordered_coin.symbol)
|
||||
.unwrap()
|
||||
.quote_asset_precision;
|
||||
let trade_fee = trade_fee_map
|
||||
.get(&buy_ordered_coin.symbol)
|
||||
.unwrap()
|
||||
.takercommission;
|
||||
let get_usdt = rust_decimal::prelude::FromStr::from_str(
|
||||
T.get("cummulativeQuoteQty").unwrap().as_str().unwrap(),
|
||||
)
|
||||
|
|
@ -859,11 +884,15 @@ pub async fn limit_order_sell(
|
|||
if T.get("status").unwrap().as_str().unwrap() == "FILLED" {
|
||||
let pure_profit_percent = decimal_mul(
|
||||
decimal_sub(
|
||||
decimal_div(get_usdt_fee_adjusted, buy_ordered_coin.used_usdt),
|
||||
decimal_div(
|
||||
get_usdt_fee_adjusted,
|
||||
buy_ordered_coin.used_usdt,
|
||||
),
|
||||
dec!(1),
|
||||
),
|
||||
dec!(100),
|
||||
).round_dp(2);
|
||||
)
|
||||
.round_dp(2);
|
||||
insert_value_container
|
||||
.push(buy_ordered_coin.pure_profit_percent.to_string());
|
||||
// pure_profit_percent
|
||||
|
|
@ -876,7 +905,8 @@ pub async fn limit_order_sell(
|
|||
insert_value_container.push(buy_ordered_coin.is_long.to_string()); // is_long
|
||||
|
||||
insert_values.push(insert_value_container.clone());
|
||||
insert_records(&insert_table_name, &insert_columns, &insert_values).await;
|
||||
insert_records(&insert_table_name, &insert_columns, &insert_values)
|
||||
.await;
|
||||
|
||||
// delete record in buy_ordered_coin_list
|
||||
let delete_table_name = String::from("buy_ordered_coin_list");
|
||||
|
|
@ -962,7 +992,9 @@ pub async fn monitoring_filled_sell_order(
|
|||
for element in filled_sell_orders {
|
||||
// build insert value
|
||||
let pure_profit_usdt = decimal_sub(element.get_usdt_fee_adjusted, element.used_usdt);
|
||||
let pure_profit_percent = decimal_mul(decimal_div(pure_profit_usdt, element.used_usdt), dec!(100)).round_dp(2);
|
||||
let pure_profit_percent =
|
||||
decimal_mul(decimal_div(pure_profit_usdt, element.used_usdt), dec!(100))
|
||||
.round_dp(2);
|
||||
insert_value_build.clear();
|
||||
insert_value_build.push(element.symbol.clone()); // symbol
|
||||
insert_value_build.push(server_epoch.to_string()); // soldtime
|
||||
|
|
@ -1164,7 +1196,8 @@ pub async fn cancel_buy_order(
|
|||
|
||||
// calculate values to be updated
|
||||
if trade_fee_map.contains_key(&order.symbol) {
|
||||
let trade_fee = trade_fee_map.get(&order.symbol).unwrap().takercommission;
|
||||
let trade_fee =
|
||||
trade_fee_map.get(&order.symbol).unwrap().takercommission;
|
||||
let base_qty_ordered = rust_decimal::prelude::FromStr::from_str(
|
||||
T.get("executedQty").unwrap().as_str().unwrap(),
|
||||
)
|
||||
|
|
@ -1344,9 +1377,15 @@ pub async fn cancel_sell_order(
|
|||
insert_values.push(insert_value_container.clone());
|
||||
insert_records(&insert_table_name, &insert_columns, &insert_values).await;
|
||||
} else {
|
||||
if exchange_info_map.contains_key(&order.symbol) && trade_fee_map.contains_key(&order.symbol) {
|
||||
let quote_asset_precision = exchange_info_map.get(&order.symbol).unwrap().quote_asset_precision;
|
||||
let trade_fee = trade_fee_map.get(&order.symbol).unwrap().takercommission;
|
||||
if exchange_info_map.contains_key(&order.symbol)
|
||||
&& trade_fee_map.contains_key(&order.symbol)
|
||||
{
|
||||
let quote_asset_precision = exchange_info_map
|
||||
.get(&order.symbol)
|
||||
.unwrap()
|
||||
.quote_asset_precision;
|
||||
let trade_fee =
|
||||
trade_fee_map.get(&order.symbol).unwrap().takercommission;
|
||||
if base_qty_executed == base_qty_ordered {
|
||||
// FILLED case
|
||||
// update status FILLED
|
||||
|
|
@ -1371,7 +1410,8 @@ pub async fn cancel_sell_order(
|
|||
dec!(1),
|
||||
),
|
||||
dec!(100),
|
||||
).round_dp(2);
|
||||
)
|
||||
.round_dp(2);
|
||||
|
||||
let table_name = String::from("sell_ordered_coin_list");
|
||||
let mut value_build = String::from("\'");
|
||||
|
|
@ -1422,7 +1462,8 @@ pub async fn cancel_sell_order(
|
|||
dec!(1),
|
||||
),
|
||||
dec!(100),
|
||||
).round_dp(2);
|
||||
)
|
||||
.round_dp(2);
|
||||
|
||||
let table_name = String::from("sell_ordered_coin_list");
|
||||
let mut value_build = String::from("\'");
|
||||
|
|
@ -1756,11 +1797,18 @@ pub async fn query_sell_order(
|
|||
|
||||
match v {
|
||||
Ok(T) => {
|
||||
if T.get("status").is_some_and(|a| a.as_str().unwrap() == "FILLED")
|
||||
|| T.get("status").is_some_and(|a| a.as_str().unwrap() == "PARTIALLY_FILLED")
|
||||
if T.get("status")
|
||||
.is_some_and(|a| a.as_str().unwrap() == "FILLED")
|
||||
|| T.get("status")
|
||||
.is_some_and(|a| a.as_str().unwrap() == "PARTIALLY_FILLED")
|
||||
{
|
||||
if exchange_info_map.contains_key(&order.symbol) && trade_fee_map.contains_key(&order.symbol) {
|
||||
let quote_asset_precision = exchange_info_map.get(&order.symbol).unwrap().quote_asset_precision;
|
||||
if exchange_info_map.contains_key(&order.symbol)
|
||||
&& trade_fee_map.contains_key(&order.symbol)
|
||||
{
|
||||
let quote_asset_precision = exchange_info_map
|
||||
.get(&order.symbol)
|
||||
.unwrap()
|
||||
.quote_asset_precision;
|
||||
let trade_fee = trade_fee_map.get(&order.symbol).unwrap().takercommission;
|
||||
let get_usdt = rust_decimal::prelude::FromStr::from_str(
|
||||
T.get("cummulativeQuoteQty").unwrap().as_str().unwrap(),
|
||||
|
|
@ -1781,7 +1829,8 @@ pub async fn query_sell_order(
|
|||
let pure_profit_percent = decimal_mul(
|
||||
decimal_sub(decimal_div(get_usdt_fee_adjusted, order.used_usdt), dec!(1)),
|
||||
dec!(100),
|
||||
).round_dp(2);
|
||||
)
|
||||
.round_dp(2);
|
||||
|
||||
let table_name = String::from("sell_ordered_coin_list");
|
||||
let mut value_build = String::from("\'");
|
||||
|
|
|
|||
|
|
@ -11,9 +11,9 @@ use serde::Deserialize;
|
|||
use serde_json::Value;
|
||||
use sqlx::{Error, FromRow};
|
||||
use std::borrow::{Borrow, BorrowMut};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::sync::Arc;
|
||||
use tokio::{join, sync::Mutex, time::*};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
#[derive(Debug, FromRow)]
|
||||
struct AllCoinProfitChangeAvgList {
|
||||
|
|
@ -152,7 +152,8 @@ pub async fn collect_valid_usde_trade(
|
|||
.unwrap();
|
||||
let step_size = value.stepsize;
|
||||
let step_price = decimal_mul(step_size, avg_price);
|
||||
let unit_trade_usdt = crate::coex::assets_managing_team::get_unit_trade_usdt().await;
|
||||
let unit_trade_usdt =
|
||||
crate::coex::assets_managing_team::get_unit_trade_usdt().await;
|
||||
|
||||
// exclude USDT trades whose step_price is over than 1% of unit_trade_usdt
|
||||
if step_price > decimal_mul(unit_trade_usdt, dec!(0.01)) {
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@ use serde::Deserialize;
|
|||
use serde_json::Value;
|
||||
use sqlx::{Error, FromRow};
|
||||
use std::borrow::{Borrow, BorrowMut};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use tokio::{join, sync::Mutex, time::*};
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CandleData {
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
use crate::database_control::*;
|
||||
use hex::ToHex;
|
||||
use hmac_sha256::HMAC;
|
||||
use log;
|
||||
use reqwest::{Client, ClientBuilder, Response};
|
||||
use rust_decimal::{prelude::FromPrimitive, prelude::ToPrimitive, Decimal, RoundingStrategy};
|
||||
use serde::Deserialize;
|
||||
use serde_json::Value;
|
||||
use sqlx::{Error, FromRow};
|
||||
use std::borrow::{Borrow, BorrowMut};
|
||||
use std::collections::HashMap;
|
||||
use std::collections::HashSet;
|
||||
use std::sync::Arc;
|
||||
use std::collections::HashMap;
|
||||
use tokio::{join, sync::Mutex, time::*};
|
||||
use log;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TradeFee {
|
||||
|
|
@ -374,8 +374,7 @@ pub async fn request_exchange_infomation(
|
|||
.unwrap()
|
||||
.ends_with("USDT")
|
||||
{
|
||||
symbol =
|
||||
(element.get("symbol").unwrap().as_str().unwrap().to_string());
|
||||
symbol = (element.get("symbol").unwrap().as_str().unwrap().to_string());
|
||||
exchange_info.base_asset_precision =
|
||||
(element.get("baseAssetPrecision").unwrap().as_u64().unwrap()) as u32;
|
||||
exchange_info.base_commission_precision = (element
|
||||
|
|
@ -442,7 +441,7 @@ pub async fn request_delist_symbols(
|
|||
secret_key: &str,
|
||||
local_epoch: u128,
|
||||
difference_epoch: i64,
|
||||
client: &Client
|
||||
client: &Client,
|
||||
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||
let mut base_url = String::from("https://api.binance.com/sapi/v1/spot/delist-schedule?");
|
||||
|
||||
|
|
@ -515,8 +514,7 @@ async fn de_deilst_symbol_json(
|
|||
|
||||
for element in object_map_iter {
|
||||
match element.0.as_str() {
|
||||
"delistTime" => {
|
||||
},
|
||||
"delistTime" => {}
|
||||
"symbols" => {
|
||||
if let Some(array) = element.1.as_array() {
|
||||
for delist_symbol in array {
|
||||
|
|
@ -527,13 +525,12 @@ async fn de_deilst_symbol_json(
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
_ => {
|
||||
log::error!("Elements in body msg are changed. Please update both your delist table and vectors.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if delist_hashset.len() != 0 {
|
||||
|
|
|
|||
|
|
@ -907,7 +907,8 @@ async fn initialize_database() {
|
|||
let mut symbols = Symbols {
|
||||
symbol: String::new(),
|
||||
};
|
||||
let symbols_vec = select_record(&fetch_table_name, &column_name, &condition, &symbols)
|
||||
let symbols_vec =
|
||||
select_record(&fetch_table_name, &column_name, &condition, &symbols)
|
||||
.await
|
||||
.expect("Failed to fetch records!");
|
||||
let insert_table_name = String::from("wallet");
|
||||
|
|
|
|||
81
src/main.rs
81
src/main.rs
|
|
@ -8,8 +8,11 @@ use crate::server_health_check_team::ServerHealth;
|
|||
use crate::strategy_team::AllData;
|
||||
use crate::time_checking_team::UserTime;
|
||||
use crate::value_estimation_team::datapoints::price_data::RealtimePriceData;
|
||||
use clap::{arg, Command};
|
||||
use log::Level;
|
||||
use reqwest::{Client, ClientBuilder};
|
||||
use rust_decimal::Decimal;
|
||||
use simple_logger::set_up_color_terminal;
|
||||
use sqlx::{mysql::*, Connection, Executor, FromRow, Row};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::{
|
||||
|
|
@ -18,9 +21,6 @@ use std::{
|
|||
};
|
||||
use tokio::{fs::*, join, sync::mpsc, sync::watch, sync::Mutex, task::*, time::*};
|
||||
use tradingbot::{RunningMode::*, *};
|
||||
use clap::{arg, Command};
|
||||
use log::Level;
|
||||
use simple_logger::set_up_color_terminal;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
|
@ -330,14 +330,18 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
|
||||
match result {
|
||||
Ok(T) => {
|
||||
local_epoch_tx1.send(usertime.local_epoch)
|
||||
local_epoch_tx1
|
||||
.send(usertime.local_epoch)
|
||||
.expect("local_epoch_tx1-local_epoch_rx1 channel has been closed.");
|
||||
epoch_difference_tx1.send(usertime.epoch_difference)
|
||||
.expect("epoch_difference_tx1-epoch_difference_rx1 channel has been closed.");
|
||||
local_epoch_tx2.send(usertime.local_epoch)
|
||||
epoch_difference_tx1.send(usertime.epoch_difference).expect(
|
||||
"epoch_difference_tx1-epoch_difference_rx1 channel has been closed.",
|
||||
);
|
||||
local_epoch_tx2
|
||||
.send(usertime.local_epoch)
|
||||
.expect("local_epoch_tx2-local_epoch_rx2 channel has been closed.");
|
||||
epoch_difference_tx2.send(usertime.epoch_difference)
|
||||
.expect("epoch_difference_tx2-epoch_difference_rx2 channel has been closed.");
|
||||
epoch_difference_tx2.send(usertime.epoch_difference).expect(
|
||||
"epoch_difference_tx2-epoch_difference_rx2 channel has been closed.",
|
||||
);
|
||||
tx_task1.send(1).expect("The mpsc channel has been closed.");
|
||||
}
|
||||
Err(E) => {}
|
||||
|
|
@ -429,7 +433,6 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
|
||||
tx_tradefee_map.send_modify(|vec| *vec = tradefee_vec_temp);
|
||||
tx_task2.send(2).expect("The mpsc channel has been closed.");
|
||||
|
||||
}
|
||||
Err(E) => {
|
||||
panic!("tx2-rx2 channel has been closed.")
|
||||
|
|
@ -472,7 +475,6 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
tx_exchange_info_map.send_modify(|vec| *vec = exchange_info_map_temp);
|
||||
tx_task3.send(3).expect("The mpsc channel has been closed.");
|
||||
|
||||
|
|
@ -506,8 +508,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
)
|
||||
.await;
|
||||
|
||||
tx_valid_usdt_trade_set
|
||||
.send_modify(|vec| *vec = valid_usdt_trade_set_temp);
|
||||
tx_valid_usdt_trade_set.send_modify(|vec| *vec = valid_usdt_trade_set_temp);
|
||||
tx_task4.send(4).expect("The mpsc channel has been closed.");
|
||||
}
|
||||
Err(E) => {
|
||||
|
|
@ -576,8 +577,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
let interval = String::from("1m");
|
||||
let candle_1m_vec = rx_candle_1m_map.borrow().clone();
|
||||
let dummy_data: HashMap<String, Vec<RealtimePriceData>> = HashMap::new();
|
||||
let mut rt_price_1m_map_write_temp: HashMap<String, Vec<RealtimePriceData>> = HashMap::new();
|
||||
let mut rt_price_1m_map_write_temp_c: HashMap<String, Vec<RealtimePriceData>> = HashMap::new();
|
||||
let mut rt_price_1m_map_write_temp: HashMap<String, Vec<RealtimePriceData>> =
|
||||
HashMap::new();
|
||||
let mut rt_price_1m_map_write_temp_c: HashMap<String, Vec<RealtimePriceData>> =
|
||||
HashMap::new();
|
||||
let result = value_estimation_team::datapoints::price_data::update_realtime_price_data(
|
||||
&interval,
|
||||
&candle_1m_vec,
|
||||
|
|
@ -597,8 +600,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
// 30m
|
||||
let interval = String::from("30m");
|
||||
let candle_30m_map = rx_candle_30m_map.borrow().clone();
|
||||
let mut rt_price_30m_map_write_temp: HashMap<String, Vec<RealtimePriceData>> = HashMap::new();
|
||||
let mut rt_price_30m_map_write_temp_c: HashMap<String, Vec<RealtimePriceData>> = HashMap::new();
|
||||
let mut rt_price_30m_map_write_temp: HashMap<String, Vec<RealtimePriceData>> =
|
||||
HashMap::new();
|
||||
let mut rt_price_30m_map_write_temp_c: HashMap<String, Vec<RealtimePriceData>> =
|
||||
HashMap::new();
|
||||
if !rt_price_1m_map_write_temp_c.is_empty() {
|
||||
let result =
|
||||
value_estimation_team::datapoints::price_data::update_realtime_price_data(
|
||||
|
|
@ -614,15 +619,19 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
if tx_rt_price_30m_map.is_closed() {
|
||||
log::error!("tx_rt_price_30m_vec has been closed!");
|
||||
} else {
|
||||
tx_rt_price_30m_map
|
||||
.send_modify(|map: &mut HashMap<String, Vec<RealtimePriceData>>| *map = rt_price_30m_map_write_temp);
|
||||
tx_rt_price_30m_map.send_modify(
|
||||
|map: &mut HashMap<String, Vec<RealtimePriceData>>| {
|
||||
*map = rt_price_30m_map_write_temp
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 1d
|
||||
let interval = String::from("1d");
|
||||
let candle_1d_vec = rx_candle_1d_map.borrow().clone();
|
||||
let mut rt_price_1d_map_write_temp: HashMap<String, Vec<RealtimePriceData>> = HashMap::new();
|
||||
let mut rt_price_1d_map_write_temp: HashMap<String, Vec<RealtimePriceData>> =
|
||||
HashMap::new();
|
||||
|
||||
if !rt_price_30m_map_write_temp_c.is_empty() {
|
||||
let result =
|
||||
|
|
@ -1055,8 +1064,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
let instant = Instant::now();
|
||||
let exchange_info_map = rx_exchange_info_map.borrow().clone();
|
||||
let trade_fee_map = rx_tradefee_map.borrow().clone();
|
||||
let result =
|
||||
coex::exchange_team::buy_coin(&exchange_info_map, &trade_fee_map).await;
|
||||
let result = coex::exchange_team::buy_coin(&exchange_info_map, &trade_fee_map).await;
|
||||
|
||||
// send Task#0 a message to notify running on
|
||||
match result {
|
||||
|
|
@ -1091,11 +1099,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
.build()
|
||||
.unwrap();
|
||||
let trade_fee_map = rx2_tradefee_map.borrow().clone();
|
||||
let result = coex::order_team::monitoring_open_buy_order(
|
||||
&client,
|
||||
&trade_fee_map,
|
||||
)
|
||||
.await;
|
||||
let result =
|
||||
coex::order_team::monitoring_open_buy_order(&client, &trade_fee_map).await;
|
||||
|
||||
// send Task#0 a message to notify running on
|
||||
match result {
|
||||
|
|
@ -1328,17 +1333,18 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
let local_epoch = *local_epoch_rx2.borrow();
|
||||
let difference_epoch = *epoch_difference_rx2.borrow();
|
||||
|
||||
|
||||
let result = request_others::request_delist_symbols(
|
||||
API_KEY,
|
||||
SECRET_KEY,
|
||||
local_epoch,
|
||||
difference_epoch,
|
||||
&client
|
||||
&client,
|
||||
)
|
||||
.await;
|
||||
|
||||
tx_task27.send(27).expect("The mpsc channel has been closed.");
|
||||
tx_task27
|
||||
.send(27)
|
||||
.expect("The mpsc channel has been closed.");
|
||||
|
||||
// sleep as much as the loop recurs per 300 seconds if all operation finished within 300 seconds.
|
||||
elapsed_time = instant.elapsed().as_secs();
|
||||
|
|
@ -1348,15 +1354,17 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
}
|
||||
});
|
||||
|
||||
loop {
|
||||
}
|
||||
loop {}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn program_setting() {
|
||||
let matches = Command::new("Tradingbot")
|
||||
.arg(arg!(log_level: -l --log <level> "Select log level: trace, debug, info, warn, error").default_value("error"))
|
||||
.arg(
|
||||
arg!(log_level: -l --log <level> "Select log level: trace, debug, info, warn, error")
|
||||
.default_value("error"),
|
||||
)
|
||||
.arg(arg!(mode: -m --mode <mode> "Select mode: real, simul, test").required(true))
|
||||
.get_matches();
|
||||
|
||||
|
|
@ -1374,7 +1382,6 @@ fn program_setting() {
|
|||
log::error!("wrong log level argument.");
|
||||
std::process::exit(0);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1385,15 +1392,15 @@ fn program_setting() {
|
|||
"real" => {
|
||||
RUNNING_MODE = RunningMode::REAL;
|
||||
println!("*** REAL MODE ***");
|
||||
},
|
||||
}
|
||||
"simul" => {
|
||||
RUNNING_MODE = RunningMode::SIMUL;
|
||||
println!("*** SIMULATION MODE ***");
|
||||
},
|
||||
}
|
||||
"test" => {
|
||||
RUNNING_MODE = RunningMode::TEST;
|
||||
println!("*** TEST MODE ***");
|
||||
},
|
||||
}
|
||||
_ => {
|
||||
log::error!("wrong mode argument.");
|
||||
std::process::exit(0);
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@
|
|||
|
||||
use crate::database_control::*;
|
||||
use crate::time_checking_team::UserTime;
|
||||
use log;
|
||||
use rand::*;
|
||||
use reqwest::{Client, ClientBuilder, Response};
|
||||
use tokio::join;
|
||||
use tokio::time::*;
|
||||
use log;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ServerHealth {
|
||||
|
|
|
|||
|
|
@ -9,13 +9,15 @@ pub mod strategy_008;
|
|||
// pub mod strategy_test;
|
||||
pub mod strategy_manager;
|
||||
|
||||
use crate::coex::order_team::{limit_order_sell, select_filled_buy_orders};
|
||||
use crate::coex::exchange_team::get_server_epoch;
|
||||
use crate::coex::order_team::{limit_order_sell, select_filled_buy_orders};
|
||||
use crate::coin_health_check_team::request_others::{ExchangeInfo, TradeFee};
|
||||
use crate::database_control::*;
|
||||
use crate::decimal_funcs::*;
|
||||
use crate::value_estimation_team::datapoints::price_data::{RealtimePriceData, CandleType};
|
||||
use crate::value_estimation_team::datapoints::price_data::{CandleType, RealtimePriceData};
|
||||
use crate::value_estimation_team::indicators::adx::{adx, AdxData};
|
||||
use crate::value_estimation_team::indicators::bollingerband::{bollingerband, BollingerBandData};
|
||||
use crate::value_estimation_team::indicators::dema::{dema, DemaData};
|
||||
use crate::value_estimation_team::indicators::ema::{ema, ema_opclo, EmaData};
|
||||
use crate::value_estimation_team::indicators::heatmap_volume::{
|
||||
heatmap_volume, HeatMapLevel, HeatmapVolumeData,
|
||||
|
|
@ -24,19 +26,19 @@ use crate::value_estimation_team::indicators::macd::{ema_macd, MacdData};
|
|||
use crate::value_estimation_team::indicators::rsi::{rsi, RsiData};
|
||||
use crate::value_estimation_team::indicators::sma::{sma, sma_opclo, SmaData};
|
||||
use crate::value_estimation_team::indicators::stoch_rsi::{stoch_rsi, StochRsiData};
|
||||
use crate::value_estimation_team::indicators::supertrend::{supertrend, SupertrendData, SuperTrendArea, SuperTrendSignal};
|
||||
use crate::value_estimation_team::indicators::adx::{AdxData, adx};
|
||||
use crate::value_estimation_team::indicators::dema::{DemaData, dema};
|
||||
use crate::value_estimation_team::indicators::tema::{TemaData, tema};
|
||||
use crate::value_estimation_team::indicators::supertrend::{
|
||||
supertrend, SuperTrendArea, SuperTrendSignal, SupertrendData,
|
||||
};
|
||||
use crate::value_estimation_team::indicators::tema::{tema, TemaData};
|
||||
use futures::future::try_join_all;
|
||||
use reqwest::{Client, ClientBuilder};
|
||||
use rust_decimal::{prelude::FromPrimitive, prelude::ToPrimitive, Decimal, RoundingStrategy};
|
||||
use rust_decimal_macros::dec;
|
||||
use sqlx::FromRow;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::sync::Arc;
|
||||
use strategy_manager::insert_pre_suggested_coins;
|
||||
use tokio::sync::Mutex;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct AllData {
|
||||
|
|
@ -92,9 +94,10 @@ impl FilteredDataValue {
|
|||
}
|
||||
}
|
||||
|
||||
pub async fn duplicate_filter(registerer: i32, original_filtered_data: &HashMap<String, FilteredDataValue>)
|
||||
-> Result<HashMap<String, FilteredDataValue>, Box<dyn std::error::Error + Send + Sync>>
|
||||
{
|
||||
pub async fn duplicate_filter(
|
||||
registerer: i32,
|
||||
original_filtered_data: &HashMap<String, FilteredDataValue>,
|
||||
) -> Result<HashMap<String, FilteredDataValue>, Box<dyn std::error::Error + Send + Sync>> {
|
||||
let inspect_table_name_1 = String::from("buy_ordered_coin_list");
|
||||
let inspect_table_name_2 = String::from("sell_ordered_coin_list");
|
||||
let inspect_table_name_3 = String::from("pre_suggested_coin_list");
|
||||
|
|
@ -146,7 +149,10 @@ pub async fn duplicate_filter(registerer: i32, original_filtered_data: &HashMap<
|
|||
Ok(filtered_data_c)
|
||||
}
|
||||
|
||||
pub async fn remove_keys(filtered_data: &mut HashMap<String, FilteredDataValue>, keys_to_remove: HashSet<String>) {
|
||||
pub async fn remove_keys(
|
||||
filtered_data: &mut HashMap<String, FilteredDataValue>,
|
||||
keys_to_remove: HashSet<String>,
|
||||
) {
|
||||
let len_prev = filtered_data.len();
|
||||
// remove key-value in filtered_data
|
||||
for symbol in keys_to_remove {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
use crate::value_estimation_team::indicators::bollingerband::bollingerband;
|
||||
|
||||
use super::{
|
||||
dec, decimal_add, decimal_sub, decimal_div, ema, exists_record, insert_pre_suggested_coins,
|
||||
limit_order_sell, rsi, select_filled_buy_orders, stoch_rsi, supertrend, try_join_all, AllData,
|
||||
Arc, Client, ClientBuilder, Decimal, EmaData, ExchangeInfo, FilteredDataValue, Mutex,
|
||||
RealtimePriceData, RoundingStrategy, RsiData, StochRsiData, SupertrendData, TradeFee, update_record3, adx, AdxData, get_server_epoch, MacdData, ema_macd,
|
||||
BollingerBandData, ToPrimitive, duplicate_filter, HashMap, HashSet, remove_keys, SuperTrendArea, SuperTrendSignal
|
||||
adx, dec, decimal_add, decimal_div, decimal_sub, duplicate_filter, ema, ema_macd,
|
||||
exists_record, get_server_epoch, insert_pre_suggested_coins, limit_order_sell, remove_keys,
|
||||
rsi, select_filled_buy_orders, stoch_rsi, supertrend, try_join_all, update_record3, AdxData,
|
||||
AllData, Arc, BollingerBandData, Client, ClientBuilder, Decimal, EmaData, ExchangeInfo,
|
||||
FilteredDataValue, HashMap, HashSet, MacdData, Mutex, RealtimePriceData, RoundingStrategy,
|
||||
RsiData, StochRsiData, SuperTrendArea, SuperTrendSignal, SupertrendData, ToPrimitive, TradeFee,
|
||||
};
|
||||
|
||||
// BB lowerband + SuperTrend + StochRSI
|
||||
|
|
@ -31,12 +32,14 @@ pub async fn list_up_for_buy(
|
|||
let rt_price_30m = alldata.rt_price_30m_vec.get(symbol).unwrap();
|
||||
let vec_len = rt_price_30m.len();
|
||||
|
||||
if let Some(candles) = rt_price_30m.get(vec_len-12..vec_len-1) {
|
||||
if let Some(candles) = rt_price_30m.get(vec_len - 12..vec_len - 1) {
|
||||
let windows = candles.windows(2);
|
||||
let mut average_amplitude = 0.0;
|
||||
|
||||
for window in windows {
|
||||
average_amplitude += (window.last().unwrap().high_price - window.last().unwrap().low_price) / window.first().unwrap().close_price;
|
||||
average_amplitude += (window.last().unwrap().high_price
|
||||
- window.last().unwrap().low_price)
|
||||
/ window.first().unwrap().close_price;
|
||||
}
|
||||
average_amplitude /= 10.0;
|
||||
|
||||
|
|
@ -56,24 +59,39 @@ pub async fn list_up_for_buy(
|
|||
// 2nd filtering: supertrend(ATR period 20, multiplier: 2, 30m close price)
|
||||
let mut keys_to_remove: HashSet<String> = HashSet::new();
|
||||
let server_epoch = get_server_epoch().await;
|
||||
let supertrend_30m_map = supertrend(20, 2.0, true, &alldata.rt_price_30m_vec, &filtered_data).await?;
|
||||
let supertrend_30m_map =
|
||||
supertrend(20, 2.0, true, &alldata.rt_price_30m_vec, &filtered_data).await?;
|
||||
for (symbol, values) in &mut filtered_data {
|
||||
if let (Some(supertrend_vec), Some(rt_price_vec)) = (supertrend_30m_map.get(symbol), alldata.rt_price_30m_vec.get(symbol)) {
|
||||
if supertrend_vec.last().unwrap().close_time == rt_price_vec.last().unwrap().close_time &&
|
||||
rt_price_vec.last().unwrap().close_time > server_epoch {
|
||||
if let (Some(supertrend_vec), Some(rt_price_vec)) = (
|
||||
supertrend_30m_map.get(symbol),
|
||||
alldata.rt_price_30m_vec.get(symbol),
|
||||
) {
|
||||
if supertrend_vec.last().unwrap().close_time == rt_price_vec.last().unwrap().close_time
|
||||
&& rt_price_vec.last().unwrap().close_time > server_epoch
|
||||
{
|
||||
// input closetime, current_price
|
||||
values.closetime = rt_price_vec.last().unwrap().close_time;
|
||||
values.current_price = rust_decimal::prelude::FromPrimitive::from_f64(rt_price_vec.last().unwrap().close_price).unwrap();
|
||||
values.current_price = rust_decimal::prelude::FromPrimitive::from_f64(
|
||||
rt_price_vec.last().unwrap().close_price,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// input stoploss
|
||||
let band_value: Decimal = rust_decimal::prelude::FromPrimitive::from_f64(supertrend_vec.last().unwrap().band_value).unwrap();
|
||||
if supertrend_vec.last().unwrap().area == SuperTrendArea::DOWN &&
|
||||
supertrend_vec.last().unwrap().band_value > values.current_price.to_f64().unwrap()
|
||||
let band_value: Decimal = rust_decimal::prelude::FromPrimitive::from_f64(
|
||||
supertrend_vec.last().unwrap().band_value,
|
||||
)
|
||||
.unwrap();
|
||||
if supertrend_vec.last().unwrap().area == SuperTrendArea::DOWN
|
||||
&& supertrend_vec.last().unwrap().band_value
|
||||
> values.current_price.to_f64().unwrap()
|
||||
{
|
||||
values.stoploss = decimal_sub(values.current_price, decimal_sub(band_value, values.current_price));
|
||||
|
||||
} else if supertrend_vec.last().unwrap().area == SuperTrendArea::UP &&
|
||||
supertrend_vec.last().unwrap().band_value < values.current_price.to_f64().unwrap()
|
||||
values.stoploss = decimal_sub(
|
||||
values.current_price,
|
||||
decimal_sub(band_value, values.current_price),
|
||||
);
|
||||
} else if supertrend_vec.last().unwrap().area == SuperTrendArea::UP
|
||||
&& supertrend_vec.last().unwrap().band_value
|
||||
< values.current_price.to_f64().unwrap()
|
||||
{
|
||||
values.stoploss = band_value;
|
||||
} else {
|
||||
|
|
@ -97,16 +115,34 @@ pub async fn list_up_for_buy(
|
|||
let rt_price_30m = alldata.rt_price_30m_vec.get(symbol).unwrap();
|
||||
let rt_price_30m_len = rt_price_30m.len();
|
||||
let search_result = ema.binary_search_by_key(
|
||||
&alldata.rt_price_30m_vec.get(symbol).unwrap().last().unwrap().close_time,
|
||||
&alldata
|
||||
.rt_price_30m_vec
|
||||
.get(symbol)
|
||||
.unwrap()
|
||||
.last()
|
||||
.unwrap()
|
||||
.close_time,
|
||||
|EmaData {
|
||||
ema_value,
|
||||
close_time,
|
||||
}| *close_time);
|
||||
if search_result.is_ok_and(|x| ema[search_result.unwrap()].ema_value < rt_price_30m[rt_price_30m_len-1].close_price) &&
|
||||
search_result.is_ok_and(|x| ema[search_result.unwrap()-1].ema_value < rt_price_30m[rt_price_30m_len-2].close_price) &&
|
||||
search_result.is_ok_and(|x| ema[search_result.unwrap()-2].ema_value < rt_price_30m[rt_price_30m_len-3].close_price) &&
|
||||
search_result.is_ok_and(|x| ema[search_result.unwrap()-3].ema_value < rt_price_30m[rt_price_30m_len-4].close_price) &&
|
||||
search_result.is_ok_and(|x| ema[search_result.unwrap()-4].ema_value < rt_price_30m[rt_price_30m_len-5].close_price) {
|
||||
}| *close_time,
|
||||
);
|
||||
if search_result.is_ok_and(|x| {
|
||||
ema[search_result.unwrap()].ema_value
|
||||
< rt_price_30m[rt_price_30m_len - 1].close_price
|
||||
}) && search_result.is_ok_and(|x| {
|
||||
ema[search_result.unwrap() - 1].ema_value
|
||||
< rt_price_30m[rt_price_30m_len - 2].close_price
|
||||
}) && search_result.is_ok_and(|x| {
|
||||
ema[search_result.unwrap() - 2].ema_value
|
||||
< rt_price_30m[rt_price_30m_len - 3].close_price
|
||||
}) && search_result.is_ok_and(|x| {
|
||||
ema[search_result.unwrap() - 3].ema_value
|
||||
< rt_price_30m[rt_price_30m_len - 4].close_price
|
||||
}) && search_result.is_ok_and(|x| {
|
||||
ema[search_result.unwrap() - 4].ema_value
|
||||
< rt_price_30m[rt_price_30m_len - 5].close_price
|
||||
}) {
|
||||
} else {
|
||||
keys_to_remove.insert(symbol.clone());
|
||||
}
|
||||
|
|
@ -122,8 +158,12 @@ pub async fn list_up_for_buy(
|
|||
for (symbol, values) in &mut filtered_data {
|
||||
if alldata.rt_price_30m_vec.contains_key(symbol) && stoch_rsis.contains_key(symbol) {
|
||||
let stoch_rsi_vec = stoch_rsis.get(symbol).unwrap();
|
||||
let search_result = stoch_rsi_vec.iter().position(|x| x.close_time == values.closetime);
|
||||
if search_result.is_some_and(|a| stoch_rsi_vec[a-1].k < 5.0 && stoch_rsi_vec[a].k > stoch_rsi_vec[a-1].k) {
|
||||
let search_result = stoch_rsi_vec
|
||||
.iter()
|
||||
.position(|x| x.close_time == values.closetime);
|
||||
if search_result.is_some_and(|a| {
|
||||
stoch_rsi_vec[a - 1].k < 5.0 && stoch_rsi_vec[a].k > stoch_rsi_vec[a - 1].k
|
||||
}) {
|
||||
} else {
|
||||
keys_to_remove.insert(symbol.clone());
|
||||
}
|
||||
|
|
@ -137,12 +177,21 @@ pub async fn list_up_for_buy(
|
|||
let mut keys_to_remove: HashSet<String> = HashSet::new();
|
||||
let macd_1d_map = ema_macd(3, 7, 30, &alldata.rt_price_1d_vec, &filtered_data).await?;
|
||||
for (symbol, values) in &mut filtered_data {
|
||||
if let (Some(macd_vec), Some(rt_price_vec)) = (macd_1d_map.get(symbol), alldata.rt_price_1d_vec.get(symbol)) {
|
||||
if macd_vec.last().unwrap().close_time == rt_price_vec.last().unwrap().close_time &&
|
||||
rt_price_vec.last().unwrap().close_time > server_epoch {
|
||||
if macd_vec[macd_vec.len()-1].macd_value - macd_vec[macd_vec.len()-1].signal_value > macd_vec[macd_vec.len()-2].macd_value - macd_vec[macd_vec.len()-2].signal_value
|
||||
if let (Some(macd_vec), Some(rt_price_vec)) =
|
||||
(macd_1d_map.get(symbol), alldata.rt_price_1d_vec.get(symbol))
|
||||
{
|
||||
values.current_price = rust_decimal::prelude::FromPrimitive::from_f64(rt_price_vec.last().unwrap().close_price).unwrap();
|
||||
if macd_vec.last().unwrap().close_time == rt_price_vec.last().unwrap().close_time
|
||||
&& rt_price_vec.last().unwrap().close_time > server_epoch
|
||||
{
|
||||
if macd_vec[macd_vec.len() - 1].macd_value
|
||||
- macd_vec[macd_vec.len() - 1].signal_value
|
||||
> macd_vec[macd_vec.len() - 2].macd_value
|
||||
- macd_vec[macd_vec.len() - 2].signal_value
|
||||
{
|
||||
values.current_price = rust_decimal::prelude::FromPrimitive::from_f64(
|
||||
rt_price_vec.last().unwrap().close_price,
|
||||
)
|
||||
.unwrap();
|
||||
values.closetime = rt_price_vec.last().unwrap().close_time;
|
||||
} else {
|
||||
keys_to_remove.insert(symbol.clone());
|
||||
|
|
@ -161,10 +210,13 @@ pub async fn list_up_for_buy(
|
|||
let adx_vec = adx(10, 10, &alldata.rt_price_30m_vec, &filtered_data).await?;
|
||||
for (symbol, values) in &mut filtered_data {
|
||||
if let Some(adx_vec) = adx_vec.get(symbol) {
|
||||
if let Some(last_idx) = adx_vec.iter().position(|elem| elem.close_time == values.closetime) {
|
||||
if
|
||||
adx_vec[last_idx].adx < adx_vec[last_idx-1].adx &&
|
||||
adx_vec[last_idx-1].adx < adx_vec[last_idx-2].adx {
|
||||
if let Some(last_idx) = adx_vec
|
||||
.iter()
|
||||
.position(|elem| elem.close_time == values.closetime)
|
||||
{
|
||||
if adx_vec[last_idx].adx < adx_vec[last_idx - 1].adx
|
||||
&& adx_vec[last_idx - 1].adx < adx_vec[last_idx - 2].adx
|
||||
{
|
||||
} else {
|
||||
keys_to_remove.insert(symbol.clone());
|
||||
}
|
||||
|
|
@ -202,20 +254,33 @@ pub async fn list_up_for_sell(
|
|||
for element in &filled_buy_orders {
|
||||
filtered_symbols.insert(element.symbol.clone(), FilteredDataValue::new());
|
||||
}
|
||||
let supertrend_30m = supertrend(20, 2.0, true, &all_data.rt_price_30m_vec, &filtered_symbols).await?;
|
||||
let stoch_rsis = stoch_rsi(10, 10, 3, 3, &all_data.rt_price_30m_vec, &filtered_symbols).await?;
|
||||
let supertrend_30m =
|
||||
supertrend(20, 2.0, true, &all_data.rt_price_30m_vec, &filtered_symbols).await?;
|
||||
let stoch_rsis =
|
||||
stoch_rsi(10, 10, 3, 3, &all_data.rt_price_30m_vec, &filtered_symbols).await?;
|
||||
for element in filled_buy_orders {
|
||||
if element.used_usdt >= dec!(10.0) {
|
||||
if let (Some(exchange_info), Some(tradefee), Some(stoch_rsi), Some(supertrend_vec)) =
|
||||
(exchange_info_map.get(&element.symbol), trade_fee_map.get(&element.symbol), stoch_rsis.get(&element.symbol), supertrend_30m.get(&element.symbol)) {
|
||||
if let (
|
||||
Some(exchange_info),
|
||||
Some(tradefee),
|
||||
Some(stoch_rsi),
|
||||
Some(supertrend_vec),
|
||||
) = (
|
||||
exchange_info_map.get(&element.symbol),
|
||||
trade_fee_map.get(&element.symbol),
|
||||
stoch_rsis.get(&element.symbol),
|
||||
supertrend_30m.get(&element.symbol),
|
||||
) {
|
||||
// update stoploss
|
||||
let band_value: Decimal = rust_decimal::prelude::FromPrimitive::from_f64(supertrend_vec.last().unwrap().band_value).unwrap();
|
||||
let band_value: Decimal = rust_decimal::prelude::FromPrimitive::from_f64(
|
||||
supertrend_vec.last().unwrap().band_value,
|
||||
)
|
||||
.unwrap();
|
||||
if supertrend_vec.last().unwrap().area == SuperTrendArea::UP
|
||||
&& band_value > element.stoploss {
|
||||
&& band_value > element.stoploss
|
||||
{
|
||||
let update_table_name = String::from("buy_ordered_coin_list");
|
||||
let update_value = vec![
|
||||
(String::from("stoploss"), band_value.to_string()),
|
||||
];
|
||||
let update_value = vec![(String::from("stoploss"), band_value.to_string())];
|
||||
let update_condition = vec![(String::from("id"), element.id.to_string())];
|
||||
update_record3(&update_table_name, &update_value, &update_condition)
|
||||
.await
|
||||
|
|
@ -224,15 +289,14 @@ pub async fn list_up_for_sell(
|
|||
|
||||
let lot_step_size = exchange_info.stepsize;
|
||||
let quote_commission_precision = exchange_info.quote_commission_precision;
|
||||
let base_qty_to_be_ordered =
|
||||
element.base_qty_ordered.round_dp_with_strategy(
|
||||
let base_qty_to_be_ordered = element.base_qty_ordered.round_dp_with_strategy(
|
||||
lot_step_size.normalize().scale(),
|
||||
RoundingStrategy::ToZero,
|
||||
);
|
||||
let stoch_rsi_k = stoch_rsi.last().unwrap().k;
|
||||
let stoch_rsi_k_prev = stoch_rsi[stoch_rsi.len()-2].k;
|
||||
let stoch_rsi_k_prev = stoch_rsi[stoch_rsi.len() - 2].k;
|
||||
let stoch_rsi_d = stoch_rsi.last().unwrap().d;
|
||||
let stoch_rsi_d_prev = stoch_rsi[stoch_rsi.len()-2].d;
|
||||
let stoch_rsi_d_prev = stoch_rsi[stoch_rsi.len() - 2].d;
|
||||
if (element.is_long == 0 || element.is_long == 1)
|
||||
&& !element.current_price.is_zero()
|
||||
{
|
||||
|
|
@ -266,9 +330,9 @@ pub async fn list_up_for_sell(
|
|||
&trade_fee_map,
|
||||
)
|
||||
.await;
|
||||
} else if stoch_rsi_k >= 90.0 &&
|
||||
(stoch_rsi_k < stoch_rsi_d &&
|
||||
stoch_rsi_k_prev > stoch_rsi_d_prev) {
|
||||
} else if stoch_rsi_k >= 90.0
|
||||
&& (stoch_rsi_k < stoch_rsi_d && stoch_rsi_k_prev > stoch_rsi_d_prev)
|
||||
{
|
||||
limit_order_sell(
|
||||
&element,
|
||||
element.current_price,
|
||||
|
|
@ -305,7 +369,6 @@ pub async fn list_up_for_sell(
|
|||
// }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
use crate::value_estimation_team::indicators::bollingerband::bollingerband;
|
||||
|
||||
use super::{
|
||||
dec, decimal_add, decimal_sub, decimal_div, ema, exists_record, insert_pre_suggested_coins,
|
||||
limit_order_sell, rsi, select_filled_buy_orders, stoch_rsi, supertrend, try_join_all, AllData,
|
||||
Arc, Client, ClientBuilder, Decimal, EmaData, ExchangeInfo, FilteredDataValue, Mutex,
|
||||
RealtimePriceData, RoundingStrategy, RsiData, StochRsiData, SupertrendData, TradeFee, update_record3, adx, AdxData, get_server_epoch, MacdData, ema_macd,
|
||||
BollingerBandData, ToPrimitive, duplicate_filter, HashMap, HashSet, remove_keys, SuperTrendArea, SuperTrendSignal
|
||||
adx, dec, decimal_add, decimal_div, decimal_sub, duplicate_filter, ema, ema_macd,
|
||||
exists_record, get_server_epoch, insert_pre_suggested_coins, limit_order_sell, remove_keys,
|
||||
rsi, select_filled_buy_orders, stoch_rsi, supertrend, try_join_all, update_record3, AdxData,
|
||||
AllData, Arc, BollingerBandData, Client, ClientBuilder, Decimal, EmaData, ExchangeInfo,
|
||||
FilteredDataValue, HashMap, HashSet, MacdData, Mutex, RealtimePriceData, RoundingStrategy,
|
||||
RsiData, StochRsiData, SuperTrendArea, SuperTrendSignal, SupertrendData, ToPrimitive, TradeFee,
|
||||
};
|
||||
|
||||
// BB 30m lowerband + BB 1m lowerband
|
||||
|
|
@ -29,12 +30,14 @@ pub async fn list_up_for_buy(
|
|||
if let Some(rt_price_30m_vec) = alldata.rt_price_30m_vec.get(symbol) {
|
||||
let vec_len = rt_price_30m_vec.len();
|
||||
if vec_len >= 11 {
|
||||
let candles = rt_price_30m_vec.get(vec_len-12..vec_len-1).unwrap();
|
||||
let candles = rt_price_30m_vec.get(vec_len - 12..vec_len - 1).unwrap();
|
||||
let windows = candles.windows(2);
|
||||
let mut average_amplitude = 0.0;
|
||||
|
||||
for window in windows {
|
||||
average_amplitude += (window.last().unwrap().high_price - window.last().unwrap().low_price) / window.first().unwrap().close_price;
|
||||
average_amplitude += (window.last().unwrap().high_price
|
||||
- window.last().unwrap().low_price)
|
||||
/ window.first().unwrap().close_price;
|
||||
}
|
||||
average_amplitude /= 10.0;
|
||||
|
||||
|
|
@ -53,12 +56,22 @@ pub async fn list_up_for_buy(
|
|||
|
||||
// 2nd filtering: BollingerBand (len:10, multiplier 2.5) previous_30m_price (close or low price) < lower_band
|
||||
let mut keys_to_remove: HashSet<String> = HashSet::new();
|
||||
let bollingerbands_30m_map = bollingerband(10, 2.5, &alldata.rt_price_30m_vec, &filtered_data).await?;
|
||||
let bollingerbands_1m_map = bollingerband(30, 3.0, &alldata.rt_price_1m_vec, &filtered_data).await?;
|
||||
let bollingerbands_30m_map =
|
||||
bollingerband(10, 2.5, &alldata.rt_price_30m_vec, &filtered_data).await?;
|
||||
let bollingerbands_1m_map =
|
||||
bollingerband(30, 3.0, &alldata.rt_price_1m_vec, &filtered_data).await?;
|
||||
let server_epoch = get_server_epoch().await;
|
||||
for (symbol, filtered_data) in &mut filtered_data {
|
||||
if let (Some(bb_30m_vec), Some(bb_1m_vec), Some(rt_30m_vec)) = (bollingerbands_30m_map.get(symbol), bollingerbands_1m_map.get(symbol), alldata.rt_price_30m_vec.get(symbol)) {
|
||||
if rt_30m_vec.len() >= 3 && bb_30m_vec.len() >= 3 && bb_1m_vec.len() >= 3 && rt_30m_vec.last().unwrap().close_time > server_epoch {
|
||||
if let (Some(bb_30m_vec), Some(bb_1m_vec), Some(rt_30m_vec)) = (
|
||||
bollingerbands_30m_map.get(symbol),
|
||||
bollingerbands_1m_map.get(symbol),
|
||||
alldata.rt_price_30m_vec.get(symbol),
|
||||
) {
|
||||
if rt_30m_vec.len() >= 3
|
||||
&& bb_30m_vec.len() >= 3
|
||||
&& bb_1m_vec.len() >= 3
|
||||
&& rt_30m_vec.last().unwrap().close_time > server_epoch
|
||||
{
|
||||
let bb_30m_search_result = bb_30m_vec.binary_search_by_key(
|
||||
&rt_30m_vec.last().unwrap().close_time,
|
||||
|BollingerBandData {
|
||||
|
|
@ -69,11 +82,17 @@ pub async fn list_up_for_buy(
|
|||
}| *close_time,
|
||||
);
|
||||
if bb_30m_search_result.is_ok() {
|
||||
if bb_30m_vec[bb_30m_search_result.unwrap()].lowerband > rt_30m_vec[rt_30m_vec.len()-1].close_price &&
|
||||
bb_1m_vec.last().unwrap().lowerband > rt_30m_vec[rt_30m_vec.len()-1].close_price
|
||||
if bb_30m_vec[bb_30m_search_result.unwrap()].lowerband
|
||||
> rt_30m_vec[rt_30m_vec.len() - 1].close_price
|
||||
&& bb_1m_vec.last().unwrap().lowerband
|
||||
> rt_30m_vec[rt_30m_vec.len() - 1].close_price
|
||||
{
|
||||
filtered_data.closetime = rt_30m_vec.last().unwrap().close_time;
|
||||
filtered_data.current_price = rust_decimal::prelude::FromPrimitive::from_f64(rt_30m_vec.last().unwrap().close_price).unwrap();
|
||||
filtered_data.current_price =
|
||||
rust_decimal::prelude::FromPrimitive::from_f64(
|
||||
rt_30m_vec.last().unwrap().close_price,
|
||||
)
|
||||
.unwrap();
|
||||
} else {
|
||||
keys_to_remove.insert(symbol.clone());
|
||||
}
|
||||
|
|
@ -91,11 +110,18 @@ pub async fn list_up_for_buy(
|
|||
|
||||
// 3rd filtering: supertrend(ATR period 7, multiplier: 1.5, 30m close price), area should be DOWN
|
||||
let mut keys_to_remove: HashSet<String> = HashSet::new();
|
||||
let supertrend_30m_map = supertrend( 7, 1.5, true, &alldata.rt_price_30m_vec, &filtered_data).await?;
|
||||
let supertrend_30m_map =
|
||||
supertrend(7, 1.5, true, &alldata.rt_price_30m_vec, &filtered_data).await?;
|
||||
let server_epoch = get_server_epoch().await;
|
||||
for (symbol, filtered_data) in &mut filtered_data {
|
||||
if let (Some(rt_30m_vec), Some(supertrend_vec)) = (alldata.rt_price_30m_vec.get(symbol), supertrend_30m_map.get(symbol)) {
|
||||
if rt_30m_vec.len() >= 3 && supertrend_vec.len() >= 3 && rt_30m_vec.last().unwrap().close_time > server_epoch {
|
||||
if let (Some(rt_30m_vec), Some(supertrend_vec)) = (
|
||||
alldata.rt_price_30m_vec.get(symbol),
|
||||
supertrend_30m_map.get(symbol),
|
||||
) {
|
||||
if rt_30m_vec.len() >= 3
|
||||
&& supertrend_vec.len() >= 3
|
||||
&& rt_30m_vec.last().unwrap().close_time > server_epoch
|
||||
{
|
||||
let supertrend_search_result = supertrend_vec.binary_search_by_key(
|
||||
&rt_30m_vec.last().unwrap().close_time,
|
||||
|SupertrendData {
|
||||
|
|
@ -106,11 +132,26 @@ pub async fn list_up_for_buy(
|
|||
}| *close_time,
|
||||
);
|
||||
if supertrend_search_result.is_ok() {
|
||||
if supertrend_vec[supertrend_search_result.unwrap()].area == SuperTrendArea::DOWN
|
||||
&& supertrend_vec[supertrend_search_result.unwrap()].band_value > filtered_data.current_price.to_f64().unwrap()
|
||||
if supertrend_vec[supertrend_search_result.unwrap()].area
|
||||
== SuperTrendArea::DOWN
|
||||
&& supertrend_vec[supertrend_search_result.unwrap()].band_value
|
||||
> filtered_data.current_price.to_f64().unwrap()
|
||||
{
|
||||
filtered_data.target_price = rust_decimal::prelude::FromPrimitive::from_f64(supertrend_vec[supertrend_search_result.unwrap()].band_value).unwrap();
|
||||
let stop_loss = decimal_sub(filtered_data.current_price, decimal_div(decimal_sub(filtered_data.target_price, filtered_data.current_price), dec!(2)));
|
||||
filtered_data.target_price =
|
||||
rust_decimal::prelude::FromPrimitive::from_f64(
|
||||
supertrend_vec[supertrend_search_result.unwrap()].band_value,
|
||||
)
|
||||
.unwrap();
|
||||
let stop_loss = decimal_sub(
|
||||
filtered_data.current_price,
|
||||
decimal_div(
|
||||
decimal_sub(
|
||||
filtered_data.target_price,
|
||||
filtered_data.current_price,
|
||||
),
|
||||
dec!(2),
|
||||
),
|
||||
);
|
||||
filtered_data.stoploss = stop_loss;
|
||||
} else {
|
||||
keys_to_remove.insert(symbol.clone());
|
||||
|
|
@ -131,18 +172,31 @@ pub async fn list_up_for_buy(
|
|||
let mut keys_to_remove: HashSet<String> = HashSet::new();
|
||||
let ema_map = ema(200, &alldata.rt_price_30m_vec, &filtered_data).await?;
|
||||
for (symbol, filtered_data) in &mut filtered_data {
|
||||
if let (Some(ema_vec), Some(rt_30m_vec)) = (ema_map.get(symbol), alldata.rt_price_30m_vec.get(symbol)) {
|
||||
if let (Some(ema_vec), Some(rt_30m_vec)) =
|
||||
(ema_map.get(symbol), alldata.rt_price_30m_vec.get(symbol))
|
||||
{
|
||||
let search_result = ema_vec.binary_search_by_key(
|
||||
&rt_30m_vec.last().unwrap().close_time,
|
||||
|EmaData {
|
||||
ema_value,
|
||||
close_time,
|
||||
}| *close_time);
|
||||
if search_result.is_ok_and(|x| ema_vec[x].ema_value < rt_30m_vec[rt_30m_vec.len()-1].close_price) &&
|
||||
search_result.is_ok_and(|x| ema_vec[x-1].ema_value < rt_30m_vec[rt_30m_vec.len()-2].close_price) &&
|
||||
search_result.is_ok_and(|x| ema_vec[x-2].ema_value < rt_30m_vec[rt_30m_vec.len()-3].close_price) &&
|
||||
search_result.is_ok_and(|x| ema_vec[x-3].ema_value < rt_30m_vec[rt_30m_vec.len()-4].close_price) &&
|
||||
search_result.is_ok_and(|x| ema_vec[x-4].ema_value < rt_30m_vec[rt_30m_vec.len()-5].close_price) {
|
||||
}| *close_time,
|
||||
);
|
||||
if search_result
|
||||
.is_ok_and(|x| ema_vec[x].ema_value < rt_30m_vec[rt_30m_vec.len() - 1].close_price)
|
||||
&& search_result.is_ok_and(|x| {
|
||||
ema_vec[x - 1].ema_value < rt_30m_vec[rt_30m_vec.len() - 2].close_price
|
||||
})
|
||||
&& search_result.is_ok_and(|x| {
|
||||
ema_vec[x - 2].ema_value < rt_30m_vec[rt_30m_vec.len() - 3].close_price
|
||||
})
|
||||
&& search_result.is_ok_and(|x| {
|
||||
ema_vec[x - 3].ema_value < rt_30m_vec[rt_30m_vec.len() - 4].close_price
|
||||
})
|
||||
&& search_result.is_ok_and(|x| {
|
||||
ema_vec[x - 4].ema_value < rt_30m_vec[rt_30m_vec.len() - 5].close_price
|
||||
})
|
||||
{
|
||||
} else {
|
||||
keys_to_remove.insert(symbol.clone());
|
||||
}
|
||||
|
|
@ -156,12 +210,21 @@ pub async fn list_up_for_buy(
|
|||
let mut keys_to_remove: HashSet<String> = HashSet::new();
|
||||
let macd_1d_map = ema_macd(3, 7, 30, &alldata.rt_price_1d_vec, &filtered_data).await?;
|
||||
for (symbol, values) in &mut filtered_data {
|
||||
if let (Some(macd_vec), Some(rt_price_vec)) = (macd_1d_map.get(symbol), alldata.rt_price_1d_vec.get(symbol)) {
|
||||
if macd_vec.last().unwrap().close_time == rt_price_vec.last().unwrap().close_time &&
|
||||
rt_price_vec.last().unwrap().close_time > server_epoch {
|
||||
if macd_vec[macd_vec.len()-1].macd_value - macd_vec[macd_vec.len()-1].signal_value > macd_vec[macd_vec.len()-2].macd_value - macd_vec[macd_vec.len()-2].signal_value
|
||||
if let (Some(macd_vec), Some(rt_price_vec)) =
|
||||
(macd_1d_map.get(symbol), alldata.rt_price_1d_vec.get(symbol))
|
||||
{
|
||||
values.current_price = rust_decimal::prelude::FromPrimitive::from_f64(rt_price_vec.last().unwrap().close_price).unwrap();
|
||||
if macd_vec.last().unwrap().close_time == rt_price_vec.last().unwrap().close_time
|
||||
&& rt_price_vec.last().unwrap().close_time > server_epoch
|
||||
{
|
||||
if macd_vec[macd_vec.len() - 1].macd_value
|
||||
- macd_vec[macd_vec.len() - 1].signal_value
|
||||
> macd_vec[macd_vec.len() - 2].macd_value
|
||||
- macd_vec[macd_vec.len() - 2].signal_value
|
||||
{
|
||||
values.current_price = rust_decimal::prelude::FromPrimitive::from_f64(
|
||||
rt_price_vec.last().unwrap().close_price,
|
||||
)
|
||||
.unwrap();
|
||||
values.closetime = rt_price_vec.last().unwrap().close_time;
|
||||
} else {
|
||||
keys_to_remove.insert(symbol.clone());
|
||||
|
|
@ -199,8 +262,7 @@ pub async fn list_up_for_sell(
|
|||
if let Some(exchange_info) = exchange_info_map.get(&element.symbol) {
|
||||
let lot_step_size = exchange_info.stepsize;
|
||||
let quote_commission_precision = exchange_info.quote_commission_precision;
|
||||
let base_qty_to_be_ordered =
|
||||
element.base_qty_ordered.round_dp_with_strategy(
|
||||
let base_qty_to_be_ordered = element.base_qty_ordered.round_dp_with_strategy(
|
||||
lot_step_size.normalize().scale(),
|
||||
RoundingStrategy::ToZero,
|
||||
);
|
||||
|
|
@ -208,8 +270,7 @@ pub async fn list_up_for_sell(
|
|||
if (element.is_long == 0 || element.is_long == 1)
|
||||
&& !element.current_price.is_zero()
|
||||
{
|
||||
if element.current_price >= element.target_price
|
||||
{
|
||||
if element.current_price >= element.target_price {
|
||||
limit_order_sell(
|
||||
&element,
|
||||
element.current_price,
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
use crate::value_estimation_team::indicators::bollingerband::bollingerband;
|
||||
|
||||
use super::{
|
||||
dec, decimal_add, decimal_sub, decimal_div, ema, ema_opclo, sma, sma_opclo, exists_record, insert_pre_suggested_coins,
|
||||
limit_order_sell, rsi, select_filled_buy_orders, stoch_rsi, supertrend, try_join_all, AllData,
|
||||
Arc, Client, ClientBuilder, Decimal, EmaData, ExchangeInfo, FilteredDataValue, Mutex, SmaData,
|
||||
RealtimePriceData, RoundingStrategy, RsiData, StochRsiData, SupertrendData, TradeFee, update_record3, adx, AdxData, get_server_epoch, MacdData, ema_macd,
|
||||
BollingerBandData, ToPrimitive, duplicate_filter, HashMap, HashSet, remove_keys, SuperTrendArea, SuperTrendSignal
|
||||
adx, dec, decimal_add, decimal_div, decimal_sub, duplicate_filter, ema, ema_macd, ema_opclo,
|
||||
exists_record, get_server_epoch, insert_pre_suggested_coins, limit_order_sell, remove_keys,
|
||||
rsi, select_filled_buy_orders, sma, sma_opclo, stoch_rsi, supertrend, try_join_all,
|
||||
update_record3, AdxData, AllData, Arc, BollingerBandData, Client, ClientBuilder, Decimal,
|
||||
EmaData, ExchangeInfo, FilteredDataValue, HashMap, HashSet, MacdData, Mutex, RealtimePriceData,
|
||||
RoundingStrategy, RsiData, SmaData, StochRsiData, SuperTrendArea, SuperTrendSignal,
|
||||
SupertrendData, ToPrimitive, TradeFee,
|
||||
};
|
||||
|
||||
// BUY: 30m SMA5 (opclo_price) < 30m EMA3 (opclo_price)
|
||||
|
|
@ -25,11 +27,18 @@ pub async fn list_up_for_buy(
|
|||
|
||||
// 3rd filtering: supertrend(ATR period 20, multiplier: 4.0, 30m close price), area should be UP
|
||||
let mut keys_to_remove: HashSet<String> = HashSet::new();
|
||||
let supertrend_30m_map = supertrend(20, 4.0, true, &alldata.rt_price_30m_vec, &filtered_data).await?;
|
||||
let supertrend_30m_map =
|
||||
supertrend(20, 4.0, true, &alldata.rt_price_30m_vec, &filtered_data).await?;
|
||||
let server_epoch = get_server_epoch().await;
|
||||
for (symbol, filtered_data) in &mut filtered_data {
|
||||
if let (Some(rt_30m_vec), Some(supertrend_vec)) = (alldata.rt_price_30m_vec.get(symbol), supertrend_30m_map.get(symbol)) {
|
||||
if rt_30m_vec.len() >= 3 && supertrend_vec.len() >= 3 && rt_30m_vec.last().unwrap().close_time > server_epoch {
|
||||
if let (Some(rt_30m_vec), Some(supertrend_vec)) = (
|
||||
alldata.rt_price_30m_vec.get(symbol),
|
||||
supertrend_30m_map.get(symbol),
|
||||
) {
|
||||
if rt_30m_vec.len() >= 3
|
||||
&& supertrend_vec.len() >= 3
|
||||
&& rt_30m_vec.last().unwrap().close_time > server_epoch
|
||||
{
|
||||
let supertrend_search_result = supertrend_vec.binary_search_by_key(
|
||||
&rt_30m_vec.last().unwrap().close_time,
|
||||
|SupertrendData {
|
||||
|
|
@ -41,7 +50,8 @@ pub async fn list_up_for_buy(
|
|||
);
|
||||
if supertrend_search_result.is_ok() {
|
||||
if supertrend_vec[supertrend_search_result.unwrap()].area == SuperTrendArea::UP
|
||||
&& supertrend_vec[supertrend_search_result.unwrap()].band_value < filtered_data.current_price.to_f64().unwrap()
|
||||
&& supertrend_vec[supertrend_search_result.unwrap()].band_value
|
||||
< filtered_data.current_price.to_f64().unwrap()
|
||||
{
|
||||
} else {
|
||||
keys_to_remove.insert(symbol.clone());
|
||||
|
|
@ -64,10 +74,17 @@ pub async fn list_up_for_buy(
|
|||
for (symbol, values) in &mut filtered_data {
|
||||
if alldata.rt_price_30m_vec.contains_key(symbol) && stoch_rsis.contains_key(symbol) {
|
||||
let stoch_rsi_vec = stoch_rsis.get(symbol).unwrap();
|
||||
let search_result = stoch_rsi_vec.iter().position(|x| x.close_time == values.closetime);
|
||||
if search_result.is_some_and(|a| stoch_rsi_vec[a-1].k < 10.0 && stoch_rsi_vec[a].k < 10.0
|
||||
&& stoch_rsi_vec[a-1].d < 10.0 && stoch_rsi_vec[a].d< 10.0 &&
|
||||
stoch_rsi_vec[a-1].k <= stoch_rsi_vec[a-1].d && stoch_rsi_vec[a].k > stoch_rsi_vec[a].d) {
|
||||
let search_result = stoch_rsi_vec
|
||||
.iter()
|
||||
.position(|x| x.close_time == values.closetime);
|
||||
if search_result.is_some_and(|a| {
|
||||
stoch_rsi_vec[a - 1].k < 10.0
|
||||
&& stoch_rsi_vec[a].k < 10.0
|
||||
&& stoch_rsi_vec[a - 1].d < 10.0
|
||||
&& stoch_rsi_vec[a].d < 10.0
|
||||
&& stoch_rsi_vec[a - 1].k <= stoch_rsi_vec[a - 1].d
|
||||
&& stoch_rsi_vec[a].k > stoch_rsi_vec[a].d
|
||||
}) {
|
||||
} else {
|
||||
keys_to_remove.insert(symbol.clone());
|
||||
}
|
||||
|
|
@ -86,13 +103,25 @@ pub async fn list_up_for_buy(
|
|||
let rt_price_30m = alldata.rt_price_30m_vec.get(symbol).unwrap();
|
||||
let rt_price_30m_len = rt_price_30m.len();
|
||||
let search_result = ema.binary_search_by_key(
|
||||
&alldata.rt_price_30m_vec.get(symbol).unwrap().last().unwrap().close_time,
|
||||
&alldata
|
||||
.rt_price_30m_vec
|
||||
.get(symbol)
|
||||
.unwrap()
|
||||
.last()
|
||||
.unwrap()
|
||||
.close_time,
|
||||
|EmaData {
|
||||
ema_value,
|
||||
close_time,
|
||||
}| *close_time);
|
||||
if search_result.is_ok_and(|x| ema[search_result.unwrap()].ema_value < rt_price_30m[rt_price_30m_len-1].close_price) &&
|
||||
search_result.is_ok_and(|x| ema[search_result.unwrap()-1].ema_value < rt_price_30m[rt_price_30m_len-2].close_price) {
|
||||
}| *close_time,
|
||||
);
|
||||
if search_result.is_ok_and(|x| {
|
||||
ema[search_result.unwrap()].ema_value
|
||||
< rt_price_30m[rt_price_30m_len - 1].close_price
|
||||
}) && search_result.is_ok_and(|x| {
|
||||
ema[search_result.unwrap() - 1].ema_value
|
||||
< rt_price_30m[rt_price_30m_len - 2].close_price
|
||||
}) {
|
||||
} else {
|
||||
keys_to_remove.insert(symbol.clone());
|
||||
}
|
||||
|
|
@ -106,12 +135,21 @@ pub async fn list_up_for_buy(
|
|||
let mut keys_to_remove: HashSet<String> = HashSet::new();
|
||||
let macd_1d_map = ema_macd(3, 7, 30, &alldata.rt_price_1d_vec, &filtered_data).await?;
|
||||
for (symbol, values) in &mut filtered_data {
|
||||
if let (Some(macd_vec), Some(rt_price_vec)) = (macd_1d_map.get(symbol), alldata.rt_price_1d_vec.get(symbol)) {
|
||||
if macd_vec.last().unwrap().close_time == rt_price_vec.last().unwrap().close_time &&
|
||||
rt_price_vec.last().unwrap().close_time > server_epoch {
|
||||
if macd_vec[macd_vec.len()-1].macd_value - macd_vec[macd_vec.len()-1].signal_value > macd_vec[macd_vec.len()-2].macd_value - macd_vec[macd_vec.len()-2].signal_value
|
||||
if let (Some(macd_vec), Some(rt_price_vec)) =
|
||||
(macd_1d_map.get(symbol), alldata.rt_price_1d_vec.get(symbol))
|
||||
{
|
||||
values.current_price = rust_decimal::prelude::FromPrimitive::from_f64(rt_price_vec.last().unwrap().close_price).unwrap();
|
||||
if macd_vec.last().unwrap().close_time == rt_price_vec.last().unwrap().close_time
|
||||
&& rt_price_vec.last().unwrap().close_time > server_epoch
|
||||
{
|
||||
if macd_vec[macd_vec.len() - 1].macd_value
|
||||
- macd_vec[macd_vec.len() - 1].signal_value
|
||||
> macd_vec[macd_vec.len() - 2].macd_value
|
||||
- macd_vec[macd_vec.len() - 2].signal_value
|
||||
{
|
||||
values.current_price = rust_decimal::prelude::FromPrimitive::from_f64(
|
||||
rt_price_vec.last().unwrap().close_price,
|
||||
)
|
||||
.unwrap();
|
||||
values.closetime = rt_price_vec.last().unwrap().close_time;
|
||||
} else {
|
||||
keys_to_remove.insert(symbol.clone());
|
||||
|
|
@ -148,27 +186,29 @@ pub async fn list_up_for_sell(
|
|||
filtered_symbols.insert(element.symbol.clone(), FilteredDataValue::new());
|
||||
}
|
||||
let server_epoch = get_server_epoch().await;
|
||||
let stoch_rsis = stoch_rsi(30, 30, 3, 3, &all_data.rt_price_30m_vec, &filtered_symbols).await?;
|
||||
let stoch_rsis =
|
||||
stoch_rsi(30, 30, 3, 3, &all_data.rt_price_30m_vec, &filtered_symbols).await?;
|
||||
for element in filled_buy_orders {
|
||||
if element.used_usdt >= dec!(10.0) {
|
||||
if let (Some(exchange_info), Some(stoch_rsi)) = (exchange_info_map.get(&element.symbol), stoch_rsis.get(&element.symbol)) {
|
||||
if let (Some(exchange_info), Some(stoch_rsi)) = (
|
||||
exchange_info_map.get(&element.symbol),
|
||||
stoch_rsis.get(&element.symbol),
|
||||
) {
|
||||
let lot_step_size = exchange_info.stepsize;
|
||||
let quote_commission_precision = exchange_info.quote_commission_precision;
|
||||
let base_qty_to_be_ordered =
|
||||
element.base_qty_ordered.round_dp_with_strategy(
|
||||
let base_qty_to_be_ordered = element.base_qty_ordered.round_dp_with_strategy(
|
||||
lot_step_size.normalize().scale(),
|
||||
RoundingStrategy::ToZero,
|
||||
);
|
||||
let stoch_rsi_k = stoch_rsi.last().unwrap().k;
|
||||
let stoch_rsi_k_prev = stoch_rsi[stoch_rsi.len()-2].k;
|
||||
let stoch_rsi_k_prev = stoch_rsi[stoch_rsi.len() - 2].k;
|
||||
let stoch_rsi_d = stoch_rsi.last().unwrap().d;
|
||||
let stoch_rsi_d_prev = stoch_rsi[stoch_rsi.len()-2].d;
|
||||
let stoch_rsi_d_prev = stoch_rsi[stoch_rsi.len() - 2].d;
|
||||
|
||||
if (element.is_long == 0 || element.is_long == 1)
|
||||
&& !element.current_price.is_zero()
|
||||
{
|
||||
if element.current_price >= element.target_price
|
||||
{
|
||||
if element.current_price >= element.target_price {
|
||||
limit_order_sell(
|
||||
&element,
|
||||
element.current_price,
|
||||
|
|
@ -208,10 +248,12 @@ pub async fn list_up_for_sell(
|
|||
&trade_fee_map,
|
||||
)
|
||||
.await;
|
||||
} else if stoch_rsi_k >= 20.0 && stoch_rsi_k >= 20.0 &&
|
||||
stoch_rsi_k_prev >= 20.0 && stoch_rsi_k_prev >= 20.0 &&
|
||||
stoch_rsi_k < stoch_rsi_d &&
|
||||
stoch_rsi_k_prev >= stoch_rsi_d_prev
|
||||
} else if stoch_rsi_k >= 20.0
|
||||
&& stoch_rsi_k >= 20.0
|
||||
&& stoch_rsi_k_prev >= 20.0
|
||||
&& stoch_rsi_k_prev >= 20.0
|
||||
&& stoch_rsi_k < stoch_rsi_d
|
||||
&& stoch_rsi_k_prev >= stoch_rsi_d_prev
|
||||
{
|
||||
limit_order_sell(
|
||||
&element,
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
use crate::value_estimation_team::indicators::bollingerband::bollingerband;
|
||||
|
||||
use super::{
|
||||
dec, decimal_add, decimal_sub, decimal_div, ema, exists_record, insert_pre_suggested_coins,
|
||||
limit_order_sell, rsi, select_filled_buy_orders, stoch_rsi, supertrend, try_join_all, AllData,
|
||||
Arc, Client, ClientBuilder, Decimal, EmaData, ExchangeInfo, FilteredDataValue, Mutex,
|
||||
RealtimePriceData, RoundingStrategy, RsiData, StochRsiData, SupertrendData, TradeFee, update_record3, adx, AdxData, get_server_epoch, MacdData, ema_macd,
|
||||
BollingerBandData, ToPrimitive, duplicate_filter, HashMap, HashSet, remove_keys, SuperTrendArea, SuperTrendSignal, CandleType
|
||||
adx, dec, decimal_add, decimal_div, decimal_sub, duplicate_filter, ema, ema_macd,
|
||||
exists_record, get_server_epoch, insert_pre_suggested_coins, limit_order_sell, remove_keys,
|
||||
rsi, select_filled_buy_orders, stoch_rsi, supertrend, try_join_all, update_record3, AdxData,
|
||||
AllData, Arc, BollingerBandData, CandleType, Client, ClientBuilder, Decimal, EmaData,
|
||||
ExchangeInfo, FilteredDataValue, HashMap, HashSet, MacdData, Mutex, RealtimePriceData,
|
||||
RoundingStrategy, RsiData, StochRsiData, SuperTrendArea, SuperTrendSignal, SupertrendData,
|
||||
ToPrimitive, TradeFee,
|
||||
};
|
||||
|
||||
// BB lowerband + SuperTrend + StochRSI
|
||||
|
|
@ -30,12 +32,14 @@ pub async fn list_up_for_buy(
|
|||
if let Some(rt_price_30m_vec) = alldata.rt_price_30m_vec.get(symbol) {
|
||||
let vec_len = rt_price_30m_vec.len();
|
||||
if vec_len >= 11 {
|
||||
let candles = rt_price_30m_vec.get(vec_len-12..vec_len-1).unwrap();
|
||||
let candles = rt_price_30m_vec.get(vec_len - 12..vec_len - 1).unwrap();
|
||||
let windows = candles.windows(2);
|
||||
let mut average_amplitude = 0.0;
|
||||
|
||||
for window in windows {
|
||||
average_amplitude += (window.last().unwrap().high_price - window.last().unwrap().low_price) / window.first().unwrap().close_price;
|
||||
average_amplitude += (window.last().unwrap().high_price
|
||||
- window.last().unwrap().low_price)
|
||||
/ window.first().unwrap().close_price;
|
||||
}
|
||||
average_amplitude /= 10.0;
|
||||
|
||||
|
|
@ -54,11 +58,18 @@ pub async fn list_up_for_buy(
|
|||
|
||||
// 2nd filtering: BollingerBand (len:30, multiplier 3) previous_30m_price (close or low price) < lower_band
|
||||
let mut keys_to_remove: HashSet<String> = HashSet::new();
|
||||
let bollingerband_map = bollingerband(30, 3.0, &alldata.rt_price_30m_vec, &filtered_data).await?;
|
||||
let bollingerband_map =
|
||||
bollingerband(30, 3.0, &alldata.rt_price_30m_vec, &filtered_data).await?;
|
||||
let server_epoch = get_server_epoch().await;
|
||||
for (symbol, filtered_data) in &mut filtered_data {
|
||||
if let (Some(bb_vec), Some(rt_30m_vec)) = (bollingerband_map.get(symbol), alldata.rt_price_30m_vec.get(symbol)) {
|
||||
if rt_30m_vec.len() >= 3 && bb_vec.len() >= 3 && rt_30m_vec.last().unwrap().close_time > server_epoch {
|
||||
if let (Some(bb_vec), Some(rt_30m_vec)) = (
|
||||
bollingerband_map.get(symbol),
|
||||
alldata.rt_price_30m_vec.get(symbol),
|
||||
) {
|
||||
if rt_30m_vec.len() >= 3
|
||||
&& bb_vec.len() >= 3
|
||||
&& rt_30m_vec.last().unwrap().close_time > server_epoch
|
||||
{
|
||||
let bb_search_result = bb_vec.binary_search_by_key(
|
||||
&rt_30m_vec.last().unwrap().close_time,
|
||||
|BollingerBandData {
|
||||
|
|
@ -69,13 +80,20 @@ pub async fn list_up_for_buy(
|
|||
}| *close_time,
|
||||
);
|
||||
if bb_search_result.is_ok() {
|
||||
if bb_vec[bb_search_result.unwrap()-1].lowerband > rt_30m_vec[rt_30m_vec.len()-2].low_price &&
|
||||
rt_30m_vec[rt_30m_vec.len()-2].opclo_price > rt_30m_vec.last().unwrap().close_price &&
|
||||
rt_30m_vec[rt_30m_vec.len()-2].candle_type == CandleType::DOWN &&
|
||||
rt_30m_vec[rt_30m_vec.len()-2].high_price < bb_vec[bb_search_result.unwrap()-1].sma
|
||||
if bb_vec[bb_search_result.unwrap() - 1].lowerband
|
||||
> rt_30m_vec[rt_30m_vec.len() - 2].low_price
|
||||
&& rt_30m_vec[rt_30m_vec.len() - 2].opclo_price
|
||||
> rt_30m_vec.last().unwrap().close_price
|
||||
&& rt_30m_vec[rt_30m_vec.len() - 2].candle_type == CandleType::DOWN
|
||||
&& rt_30m_vec[rt_30m_vec.len() - 2].high_price
|
||||
< bb_vec[bb_search_result.unwrap() - 1].sma
|
||||
{
|
||||
filtered_data.closetime = rt_30m_vec.last().unwrap().close_time;
|
||||
filtered_data.current_price = rust_decimal::prelude::FromPrimitive::from_f64(rt_30m_vec.last().unwrap().close_price).unwrap();
|
||||
filtered_data.current_price =
|
||||
rust_decimal::prelude::FromPrimitive::from_f64(
|
||||
rt_30m_vec.last().unwrap().close_price,
|
||||
)
|
||||
.unwrap();
|
||||
} else {
|
||||
keys_to_remove.insert(symbol.clone());
|
||||
}
|
||||
|
|
@ -94,10 +112,17 @@ pub async fn list_up_for_buy(
|
|||
// 3rd filtering: supertrend(ATR period 10, multiplier: 2, 30m close price), area should be DOWN
|
||||
let mut keys_to_remove: HashSet<String> = HashSet::new();
|
||||
let server_epoch = get_server_epoch().await;
|
||||
let supertrend_30m_map = supertrend( 10, 2.0, true, &alldata.rt_price_30m_vec, &filtered_data).await?;
|
||||
let supertrend_30m_map =
|
||||
supertrend(10, 2.0, true, &alldata.rt_price_30m_vec, &filtered_data).await?;
|
||||
for (symbol, filtered_data) in &mut filtered_data {
|
||||
if let (Some(supertrend_vec), Some(rt_30m_vec)) = (supertrend_30m_map.get(symbol), alldata.rt_price_30m_vec.get(symbol)) {
|
||||
if rt_30m_vec.len() >= 3 && supertrend_vec.len() >= 3 && rt_30m_vec.last().unwrap().close_time > server_epoch {
|
||||
if let (Some(supertrend_vec), Some(rt_30m_vec)) = (
|
||||
supertrend_30m_map.get(symbol),
|
||||
alldata.rt_price_30m_vec.get(symbol),
|
||||
) {
|
||||
if rt_30m_vec.len() >= 3
|
||||
&& supertrend_vec.len() >= 3
|
||||
&& rt_30m_vec.last().unwrap().close_time > server_epoch
|
||||
{
|
||||
let supertrend_search_result = supertrend_vec.binary_search_by_key(
|
||||
&rt_30m_vec.last().unwrap().close_time,
|
||||
|SupertrendData {
|
||||
|
|
@ -107,10 +132,22 @@ pub async fn list_up_for_buy(
|
|||
close_time,
|
||||
}| *close_time,
|
||||
);
|
||||
if supertrend_search_result.is_ok_and(|x|
|
||||
supertrend_vec[x].area == SuperTrendArea::DOWN && supertrend_vec[x].band_value > filtered_data.current_price.to_f64().unwrap()) {
|
||||
filtered_data.target_price = rust_decimal::prelude::FromPrimitive::from_f64(supertrend_vec[supertrend_search_result.unwrap()].band_value).unwrap();
|
||||
let stop_loss = decimal_sub(filtered_data.current_price, decimal_div(decimal_sub(filtered_data.target_price, filtered_data.current_price), dec!(2)));
|
||||
if supertrend_search_result.is_ok_and(|x| {
|
||||
supertrend_vec[x].area == SuperTrendArea::DOWN
|
||||
&& supertrend_vec[x].band_value
|
||||
> filtered_data.current_price.to_f64().unwrap()
|
||||
}) {
|
||||
filtered_data.target_price = rust_decimal::prelude::FromPrimitive::from_f64(
|
||||
supertrend_vec[supertrend_search_result.unwrap()].band_value,
|
||||
)
|
||||
.unwrap();
|
||||
let stop_loss = decimal_sub(
|
||||
filtered_data.current_price,
|
||||
decimal_div(
|
||||
decimal_sub(filtered_data.target_price, filtered_data.current_price),
|
||||
dec!(2),
|
||||
),
|
||||
);
|
||||
filtered_data.stoploss = stop_loss;
|
||||
} else {
|
||||
keys_to_remove.insert(symbol.clone());
|
||||
|
|
@ -128,18 +165,32 @@ pub async fn list_up_for_buy(
|
|||
let mut keys_to_remove: HashSet<String> = HashSet::new();
|
||||
let ema_map = ema(200, &alldata.rt_price_30m_vec, &filtered_data).await?;
|
||||
for (symbol, filtered_data) in &mut filtered_data {
|
||||
if let (Some(ema_vec), Some(rt_30m_vec)) = (ema_map.get(symbol), alldata.rt_price_30m_vec.get(symbol)) {
|
||||
if let (Some(ema_vec), Some(rt_30m_vec)) =
|
||||
(ema_map.get(symbol), alldata.rt_price_30m_vec.get(symbol))
|
||||
{
|
||||
let search_result = ema_vec.binary_search_by_key(
|
||||
&rt_30m_vec.last().unwrap().close_time,
|
||||
|EmaData {
|
||||
ema_value,
|
||||
close_time,
|
||||
}| *close_time);
|
||||
if search_result.is_ok_and(|x| ema_vec[search_result.unwrap()].ema_value < rt_30m_vec[rt_30m_vec.len()-1].close_price) &&
|
||||
search_result.is_ok_and(|x| ema_vec[search_result.unwrap()-1].ema_value < rt_30m_vec[rt_30m_vec.len()-2].close_price) &&
|
||||
search_result.is_ok_and(|x| ema_vec[search_result.unwrap()-2].ema_value < rt_30m_vec[rt_30m_vec.len()-3].close_price) &&
|
||||
search_result.is_ok_and(|x| ema_vec[search_result.unwrap()-3].ema_value < rt_30m_vec[rt_30m_vec.len()-4].close_price) &&
|
||||
search_result.is_ok_and(|x| ema_vec[search_result.unwrap()-4].ema_value < rt_30m_vec[rt_30m_vec.len()-5].close_price) {
|
||||
}| *close_time,
|
||||
);
|
||||
if search_result.is_ok_and(|x| {
|
||||
ema_vec[search_result.unwrap()].ema_value
|
||||
< rt_30m_vec[rt_30m_vec.len() - 1].close_price
|
||||
}) && search_result.is_ok_and(|x| {
|
||||
ema_vec[search_result.unwrap() - 1].ema_value
|
||||
< rt_30m_vec[rt_30m_vec.len() - 2].close_price
|
||||
}) && search_result.is_ok_and(|x| {
|
||||
ema_vec[search_result.unwrap() - 2].ema_value
|
||||
< rt_30m_vec[rt_30m_vec.len() - 3].close_price
|
||||
}) && search_result.is_ok_and(|x| {
|
||||
ema_vec[search_result.unwrap() - 3].ema_value
|
||||
< rt_30m_vec[rt_30m_vec.len() - 4].close_price
|
||||
}) && search_result.is_ok_and(|x| {
|
||||
ema_vec[search_result.unwrap() - 4].ema_value
|
||||
< rt_30m_vec[rt_30m_vec.len() - 5].close_price
|
||||
}) {
|
||||
} else {
|
||||
keys_to_remove.insert(symbol.clone());
|
||||
}
|
||||
|
|
@ -154,8 +205,11 @@ pub async fn list_up_for_buy(
|
|||
let stoch_rsi_map = stoch_rsi(10, 10, 3, 3, &alldata.rt_price_30m_vec, &filtered_data).await?;
|
||||
for (symbol, filtered_data) in &mut filtered_data {
|
||||
if let Some(stoch_rsi_vec) = stoch_rsi_map.get(symbol) {
|
||||
let search_result = stoch_rsi_vec.iter().position(|x| x.close_time == filtered_data.closetime);
|
||||
if search_result.is_some_and(|a| stoch_rsi_vec[a].k < 15.0 && stoch_rsi_vec[a].d < 15.0) {
|
||||
let search_result = stoch_rsi_vec
|
||||
.iter()
|
||||
.position(|x| x.close_time == filtered_data.closetime);
|
||||
if search_result.is_some_and(|a| stoch_rsi_vec[a].k < 15.0 && stoch_rsi_vec[a].d < 15.0)
|
||||
{
|
||||
} else {
|
||||
keys_to_remove.insert(symbol.clone());
|
||||
}
|
||||
|
|
@ -169,12 +223,21 @@ pub async fn list_up_for_buy(
|
|||
let mut keys_to_remove: HashSet<String> = HashSet::new();
|
||||
let macd_1d_map = ema_macd(3, 7, 30, &alldata.rt_price_1d_vec, &filtered_data).await?;
|
||||
for (symbol, values) in &mut filtered_data {
|
||||
if let (Some(macd_vec), Some(rt_price_vec)) = (macd_1d_map.get(symbol), alldata.rt_price_1d_vec.get(symbol)) {
|
||||
if macd_vec.last().unwrap().close_time == rt_price_vec.last().unwrap().close_time &&
|
||||
rt_price_vec.last().unwrap().close_time > server_epoch {
|
||||
if macd_vec[macd_vec.len()-1].macd_value - macd_vec[macd_vec.len()-1].signal_value > macd_vec[macd_vec.len()-2].macd_value - macd_vec[macd_vec.len()-2].signal_value
|
||||
if let (Some(macd_vec), Some(rt_price_vec)) =
|
||||
(macd_1d_map.get(symbol), alldata.rt_price_1d_vec.get(symbol))
|
||||
{
|
||||
values.current_price = rust_decimal::prelude::FromPrimitive::from_f64(rt_price_vec.last().unwrap().close_price).unwrap();
|
||||
if macd_vec.last().unwrap().close_time == rt_price_vec.last().unwrap().close_time
|
||||
&& rt_price_vec.last().unwrap().close_time > server_epoch
|
||||
{
|
||||
if macd_vec[macd_vec.len() - 1].macd_value
|
||||
- macd_vec[macd_vec.len() - 1].signal_value
|
||||
> macd_vec[macd_vec.len() - 2].macd_value
|
||||
- macd_vec[macd_vec.len() - 2].signal_value
|
||||
{
|
||||
values.current_price = rust_decimal::prelude::FromPrimitive::from_f64(
|
||||
rt_price_vec.last().unwrap().close_price,
|
||||
)
|
||||
.unwrap();
|
||||
values.closetime = rt_price_vec.last().unwrap().close_time;
|
||||
} else {
|
||||
keys_to_remove.insert(symbol.clone());
|
||||
|
|
@ -213,8 +276,7 @@ pub async fn list_up_for_sell(
|
|||
if let Some(exchange_info) = exchange_info_map.get(&element.symbol) {
|
||||
let lot_step_size = exchange_info.stepsize;
|
||||
let quote_commission_precision = exchange_info.quote_commission_precision;
|
||||
let base_qty_to_be_ordered =
|
||||
element.base_qty_ordered.round_dp_with_strategy(
|
||||
let base_qty_to_be_ordered = element.base_qty_ordered.round_dp_with_strategy(
|
||||
lot_step_size.normalize().scale(),
|
||||
RoundingStrategy::ToZero,
|
||||
);
|
||||
|
|
@ -222,8 +284,7 @@ pub async fn list_up_for_sell(
|
|||
if (element.is_long == 0 || element.is_long == 1)
|
||||
&& !element.current_price.is_zero()
|
||||
{
|
||||
if element.current_price >= element.target_price
|
||||
{
|
||||
if element.current_price >= element.target_price {
|
||||
limit_order_sell(
|
||||
&element,
|
||||
element.current_price,
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
use super::{
|
||||
dec, decimal_add, decimal_sub, decimal_div, decimal_mul, ema, exists_record, insert_pre_suggested_coins,
|
||||
limit_order_sell, rsi, select_filled_buy_orders, stoch_rsi, supertrend, try_join_all, AllData,
|
||||
Arc, Client, ClientBuilder, Decimal, EmaData, ExchangeInfo, FilteredDataValue, Mutex,
|
||||
RealtimePriceData, RoundingStrategy, RsiData, StochRsiData, SupertrendData, TradeFee, update_record3, adx, AdxData, get_server_epoch, MacdData, ema_macd,
|
||||
BollingerBandData, ToPrimitive, duplicate_filter, HashMap, HashSet, remove_keys, SuperTrendArea, SuperTrendSignal, get_current_price
|
||||
adx, dec, decimal_add, decimal_div, decimal_mul, decimal_sub, duplicate_filter, ema, ema_macd,
|
||||
exists_record, get_current_price, get_server_epoch, insert_pre_suggested_coins,
|
||||
limit_order_sell, remove_keys, rsi, select_filled_buy_orders, stoch_rsi, supertrend,
|
||||
try_join_all, update_record3, AdxData, AllData, Arc, BollingerBandData, Client, ClientBuilder,
|
||||
Decimal, EmaData, ExchangeInfo, FilteredDataValue, HashMap, HashSet, MacdData, Mutex,
|
||||
RealtimePriceData, RoundingStrategy, RsiData, StochRsiData, SuperTrendArea, SuperTrendSignal,
|
||||
SupertrendData, ToPrimitive, TradeFee,
|
||||
};
|
||||
|
||||
// BUY conditions
|
||||
|
|
@ -27,12 +29,17 @@ pub async fn list_up_for_buy(
|
|||
// 2nd filtering: supertrend(ATR period 14, multiplier: 1.2, 1d close price)
|
||||
let mut keys_to_remove: HashSet<String> = HashSet::new();
|
||||
let server_epoch = get_server_epoch().await;
|
||||
let supertrend_1d_map = supertrend(14, 1.2, true, &alldata.rt_price_1d_vec, &filtered_data).await?;
|
||||
let supertrend_1d_map =
|
||||
supertrend(14, 1.2, true, &alldata.rt_price_1d_vec, &filtered_data).await?;
|
||||
for (symbol, values) in &mut filtered_data {
|
||||
if let (Some(supertrend_vec), Some(rt_price_vec)) = (supertrend_1d_map.get(symbol), alldata.rt_price_1d_vec.get(symbol)) {
|
||||
if supertrend_vec.last().unwrap().close_time == rt_price_vec.last().unwrap().close_time &&
|
||||
rt_price_vec.last().unwrap().close_time > server_epoch {
|
||||
if supertrend_vec.last().unwrap().area == SuperTrendArea::UP{
|
||||
if let (Some(supertrend_vec), Some(rt_price_vec)) = (
|
||||
supertrend_1d_map.get(symbol),
|
||||
alldata.rt_price_1d_vec.get(symbol),
|
||||
) {
|
||||
if supertrend_vec.last().unwrap().close_time == rt_price_vec.last().unwrap().close_time
|
||||
&& rt_price_vec.last().unwrap().close_time > server_epoch
|
||||
{
|
||||
if supertrend_vec.last().unwrap().area == SuperTrendArea::UP {
|
||||
} else {
|
||||
keys_to_remove.insert(symbol.clone());
|
||||
}
|
||||
|
|
@ -49,12 +56,21 @@ pub async fn list_up_for_buy(
|
|||
let mut keys_to_remove: HashSet<String> = HashSet::new();
|
||||
let macd_1d_map = ema_macd(3, 5, 30, &alldata.rt_price_1d_vec, &filtered_data).await?;
|
||||
for (symbol, values) in &mut filtered_data {
|
||||
if let (Some(macd_vec), Some(rt_price_vec)) = (macd_1d_map.get(symbol), alldata.rt_price_1d_vec.get(symbol)) {
|
||||
if macd_vec.last().unwrap().close_time == rt_price_vec.last().unwrap().close_time &&
|
||||
rt_price_vec.last().unwrap().close_time > server_epoch {
|
||||
if macd_vec[macd_vec.len()-1].macd_value > macd_vec[macd_vec.len()-1].signal_value &&
|
||||
macd_vec[macd_vec.len()-2].macd_value < macd_vec[macd_vec.len()-2].signal_value {
|
||||
values.current_price = rust_decimal::prelude::FromPrimitive::from_f64(rt_price_vec.last().unwrap().close_price).unwrap();
|
||||
if let (Some(macd_vec), Some(rt_price_vec)) =
|
||||
(macd_1d_map.get(symbol), alldata.rt_price_1d_vec.get(symbol))
|
||||
{
|
||||
if macd_vec.last().unwrap().close_time == rt_price_vec.last().unwrap().close_time
|
||||
&& rt_price_vec.last().unwrap().close_time > server_epoch
|
||||
{
|
||||
if macd_vec[macd_vec.len() - 1].macd_value
|
||||
> macd_vec[macd_vec.len() - 1].signal_value
|
||||
&& macd_vec[macd_vec.len() - 2].macd_value
|
||||
< macd_vec[macd_vec.len() - 2].signal_value
|
||||
{
|
||||
values.current_price = rust_decimal::prelude::FromPrimitive::from_f64(
|
||||
rt_price_vec.last().unwrap().close_price,
|
||||
)
|
||||
.unwrap();
|
||||
values.closetime = rt_price_vec.last().unwrap().close_time;
|
||||
} else {
|
||||
keys_to_remove.insert(symbol.clone());
|
||||
|
|
@ -71,24 +87,48 @@ pub async fn list_up_for_buy(
|
|||
// 2nd filtering: supertrend(ATR period 14, multiplier: 1.2, 1d close price)
|
||||
let mut keys_to_remove: HashSet<String> = HashSet::new();
|
||||
let server_epoch = get_server_epoch().await;
|
||||
let supertrend_1d_map = supertrend(14, 1.2, true, &alldata.rt_price_1d_vec, &filtered_data).await?;
|
||||
let supertrend_1d_map =
|
||||
supertrend(14, 1.2, true, &alldata.rt_price_1d_vec, &filtered_data).await?;
|
||||
for (symbol, values) in &mut filtered_data {
|
||||
if let (Some(supertrend_vec), Some(rt_price_vec)) = (supertrend_1d_map.get(symbol), alldata.rt_price_1d_vec.get(symbol)) {
|
||||
if supertrend_vec.last().unwrap().close_time == rt_price_vec.last().unwrap().close_time &&
|
||||
rt_price_vec.last().unwrap().close_time > server_epoch {
|
||||
// input stoploss, target_price
|
||||
let band_value: Decimal = rust_decimal::prelude::FromPrimitive::from_f64(supertrend_vec.last().unwrap().band_value).unwrap();
|
||||
if supertrend_vec.last().unwrap().area == SuperTrendArea::DOWN &&
|
||||
supertrend_vec.last().unwrap().band_value > values.current_price.to_f64().unwrap()
|
||||
if let (Some(supertrend_vec), Some(rt_price_vec)) = (
|
||||
supertrend_1d_map.get(symbol),
|
||||
alldata.rt_price_1d_vec.get(symbol),
|
||||
) {
|
||||
if supertrend_vec.last().unwrap().close_time == rt_price_vec.last().unwrap().close_time
|
||||
&& rt_price_vec.last().unwrap().close_time > server_epoch
|
||||
{
|
||||
values.stoploss = decimal_sub(values.current_price, decimal_sub(band_value, values.current_price));
|
||||
values.target_price = decimal_add(decimal_mul(decimal_sub(values.current_price, values.stoploss), dec!(2.0)), values.current_price);
|
||||
|
||||
} else if supertrend_vec.last().unwrap().area == SuperTrendArea::UP &&
|
||||
supertrend_vec.last().unwrap().band_value < values.current_price.to_f64().unwrap()
|
||||
// input stoploss, target_price
|
||||
let band_value: Decimal = rust_decimal::prelude::FromPrimitive::from_f64(
|
||||
supertrend_vec.last().unwrap().band_value,
|
||||
)
|
||||
.unwrap();
|
||||
if supertrend_vec.last().unwrap().area == SuperTrendArea::DOWN
|
||||
&& supertrend_vec.last().unwrap().band_value
|
||||
> values.current_price.to_f64().unwrap()
|
||||
{
|
||||
values.stoploss = decimal_sub(
|
||||
values.current_price,
|
||||
decimal_sub(band_value, values.current_price),
|
||||
);
|
||||
values.target_price = decimal_add(
|
||||
decimal_mul(
|
||||
decimal_sub(values.current_price, values.stoploss),
|
||||
dec!(2.0),
|
||||
),
|
||||
values.current_price,
|
||||
);
|
||||
} else if supertrend_vec.last().unwrap().area == SuperTrendArea::UP
|
||||
&& supertrend_vec.last().unwrap().band_value
|
||||
< values.current_price.to_f64().unwrap()
|
||||
{
|
||||
values.stoploss = band_value;
|
||||
values.target_price = decimal_add(decimal_mul(decimal_sub(values.current_price, values.stoploss), dec!(2.0)), values.current_price);
|
||||
values.target_price = decimal_add(
|
||||
decimal_mul(
|
||||
decimal_sub(values.current_price, values.stoploss),
|
||||
dec!(2.0),
|
||||
),
|
||||
values.current_price,
|
||||
);
|
||||
} else {
|
||||
keys_to_remove.insert(symbol.clone());
|
||||
}
|
||||
|
|
@ -106,9 +146,11 @@ pub async fn list_up_for_buy(
|
|||
let adx_vec = adx(3, 5, &alldata.rt_price_1d_vec, &filtered_data).await?;
|
||||
for (symbol, values) in &mut filtered_data {
|
||||
if let Some(adx_vec) = adx_vec.get(symbol) {
|
||||
if let Some(last_idx) = adx_vec.iter().position(|elem| elem.close_time == values.closetime) {
|
||||
if
|
||||
adx_vec[last_idx].adx > adx_vec[last_idx-1].adx {
|
||||
if let Some(last_idx) = adx_vec
|
||||
.iter()
|
||||
.position(|elem| elem.close_time == values.closetime)
|
||||
{
|
||||
if adx_vec[last_idx].adx > adx_vec[last_idx - 1].adx {
|
||||
} else {
|
||||
keys_to_remove.insert(symbol.clone());
|
||||
}
|
||||
|
|
@ -128,12 +170,17 @@ pub async fn list_up_for_buy(
|
|||
if let Some(rt_price_vec) = alldata.rt_price_1d_vec.get(symbol) {
|
||||
if rt_price_vec.last().unwrap().close_time > server_epoch && rt_price_vec.len() >= 6 {
|
||||
let mut opclo_vec: Vec<f64> = Vec::new();
|
||||
opclo_vec.push(rt_price_vec[rt_price_vec.len()-2].opclo_price);
|
||||
opclo_vec.push(rt_price_vec[rt_price_vec.len()-3].opclo_price);
|
||||
opclo_vec.push(rt_price_vec[rt_price_vec.len()-4].opclo_price);
|
||||
opclo_vec.push(rt_price_vec[rt_price_vec.len()-5].opclo_price);
|
||||
opclo_vec.push(rt_price_vec[rt_price_vec.len()-6].opclo_price);
|
||||
let max_idx = opclo_vec.iter().position(|&x| x == *opclo_vec.iter().max_by(|&a, &b| a.partial_cmp(b).unwrap()).unwrap());
|
||||
opclo_vec.push(rt_price_vec[rt_price_vec.len() - 2].opclo_price);
|
||||
opclo_vec.push(rt_price_vec[rt_price_vec.len() - 3].opclo_price);
|
||||
opclo_vec.push(rt_price_vec[rt_price_vec.len() - 4].opclo_price);
|
||||
opclo_vec.push(rt_price_vec[rt_price_vec.len() - 5].opclo_price);
|
||||
opclo_vec.push(rt_price_vec[rt_price_vec.len() - 6].opclo_price);
|
||||
let max_idx = opclo_vec.iter().position(|&x| {
|
||||
x == *opclo_vec
|
||||
.iter()
|
||||
.max_by(|&a, &b| a.partial_cmp(b).unwrap())
|
||||
.unwrap()
|
||||
});
|
||||
opclo_vec.remove(max_idx.unwrap());
|
||||
|
||||
let mut mean = 0.0;
|
||||
|
|
@ -181,19 +228,25 @@ pub async fn list_up_for_sell(
|
|||
for element in &filled_buy_orders {
|
||||
filtered_symbols.insert(element.symbol.clone(), FilteredDataValue::new());
|
||||
}
|
||||
let supertrend_1d = supertrend(14, 1.2, true, &all_data.rt_price_1d_vec, &filtered_symbols).await?;
|
||||
let supertrend_1d =
|
||||
supertrend(14, 1.2, true, &all_data.rt_price_1d_vec, &filtered_symbols).await?;
|
||||
for element in filled_buy_orders {
|
||||
if element.used_usdt >= dec!(10.0) {
|
||||
if let (Some(exchange_info), Some(tradefee), Some(supertrend_vec)) =
|
||||
(exchange_info_map.get(&element.symbol), trade_fee_map.get(&element.symbol), supertrend_1d.get(&element.symbol)) {
|
||||
if let (Some(exchange_info), Some(tradefee), Some(supertrend_vec)) = (
|
||||
exchange_info_map.get(&element.symbol),
|
||||
trade_fee_map.get(&element.symbol),
|
||||
supertrend_1d.get(&element.symbol),
|
||||
) {
|
||||
// update stoploss
|
||||
let band_value: Decimal = rust_decimal::prelude::FromPrimitive::from_f64(supertrend_vec.last().unwrap().band_value).unwrap();
|
||||
let band_value: Decimal = rust_decimal::prelude::FromPrimitive::from_f64(
|
||||
supertrend_vec.last().unwrap().band_value,
|
||||
)
|
||||
.unwrap();
|
||||
if supertrend_vec.last().unwrap().area == SuperTrendArea::UP
|
||||
&& band_value > element.stoploss {
|
||||
&& band_value > element.stoploss
|
||||
{
|
||||
let update_table_name = String::from("buy_ordered_coin_list");
|
||||
let update_value = vec![
|
||||
(String::from("stoploss"), band_value.to_string()),
|
||||
];
|
||||
let update_value = vec![(String::from("stoploss"), band_value.to_string())];
|
||||
let update_condition = vec![(String::from("id"), element.id.to_string())];
|
||||
update_record3(&update_table_name, &update_value, &update_condition)
|
||||
.await
|
||||
|
|
@ -202,8 +255,7 @@ pub async fn list_up_for_sell(
|
|||
|
||||
let lot_step_size = exchange_info.stepsize;
|
||||
let quote_commission_precision = exchange_info.quote_commission_precision;
|
||||
let base_qty_to_be_ordered =
|
||||
element.base_qty_ordered.round_dp_with_strategy(
|
||||
let base_qty_to_be_ordered = element.base_qty_ordered.round_dp_with_strategy(
|
||||
lot_step_size.normalize().scale(),
|
||||
RoundingStrategy::ToZero,
|
||||
);
|
||||
|
|
@ -231,7 +283,8 @@ pub async fn list_up_for_sell(
|
|||
&trade_fee_map,
|
||||
)
|
||||
.await;
|
||||
} else if server_epoch - element.transact_time > (86_400_000) * 7 { // 7 days timeout selling
|
||||
} else if server_epoch - element.transact_time > (86_400_000) * 7 {
|
||||
// 7 days timeout selling
|
||||
limit_order_sell(
|
||||
&element,
|
||||
element.current_price,
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
use super::{
|
||||
dec, decimal_add, decimal_sub, decimal_div, decimal_mul, ema, exists_record, insert_pre_suggested_coins,
|
||||
limit_order_sell, rsi, select_filled_buy_orders, stoch_rsi, supertrend, try_join_all, AllData,
|
||||
Arc, Client, ClientBuilder, Decimal, EmaData, ExchangeInfo, FilteredDataValue, Mutex,
|
||||
RealtimePriceData, RoundingStrategy, RsiData, StochRsiData, SupertrendData, TradeFee, update_record3, adx, AdxData, get_server_epoch, MacdData, ema_macd,
|
||||
BollingerBandData, ToPrimitive, duplicate_filter, HashMap, HashSet, remove_keys, SuperTrendArea, SuperTrendSignal, get_current_price, dema, DemaData, tema, TemaData
|
||||
adx, dec, decimal_add, decimal_div, decimal_mul, decimal_sub, dema, duplicate_filter, ema,
|
||||
ema_macd, exists_record, get_current_price, get_server_epoch, insert_pre_suggested_coins,
|
||||
limit_order_sell, remove_keys, rsi, select_filled_buy_orders, stoch_rsi, supertrend, tema,
|
||||
try_join_all, update_record3, AdxData, AllData, Arc, BollingerBandData, Client, ClientBuilder,
|
||||
Decimal, DemaData, EmaData, ExchangeInfo, FilteredDataValue, HashMap, HashSet, MacdData, Mutex,
|
||||
RealtimePriceData, RoundingStrategy, RsiData, StochRsiData, SuperTrendArea, SuperTrendSignal,
|
||||
SupertrendData, TemaData, ToPrimitive, TradeFee,
|
||||
};
|
||||
|
||||
// BUY conditions
|
||||
|
|
@ -29,15 +31,28 @@ pub async fn list_up_for_buy(
|
|||
let macd_1d_map = ema_macd(3, 7, 30, &alldata.rt_price_1d_vec, &filtered_data).await?;
|
||||
let server_epoch = get_server_epoch().await;
|
||||
for (symbol, values) in &mut filtered_data {
|
||||
if let (Some(macd_vec), Some(rt_price_vec)) = (macd_1d_map.get(symbol), alldata.rt_price_1d_vec.get(symbol)) {
|
||||
if macd_vec.last().unwrap().close_time == rt_price_vec.last().unwrap().close_time &&
|
||||
rt_price_vec.last().unwrap().close_time > server_epoch {
|
||||
if macd_vec.len() >= 30 &&
|
||||
(macd_vec[macd_vec.len()-1].macd_value - macd_vec[macd_vec.len()-1].signal_value).is_sign_negative() &&
|
||||
(macd_vec[macd_vec.len()-2].macd_value - macd_vec[macd_vec.len()-2].signal_value).is_sign_negative() &&
|
||||
(macd_vec[macd_vec.len()-1].macd_value - macd_vec[macd_vec.len()-1].signal_value >
|
||||
macd_vec[macd_vec.len()-2].macd_value - macd_vec[macd_vec.len()-2].signal_value) {
|
||||
values.current_price = rust_decimal::prelude::FromPrimitive::from_f64(rt_price_vec.last().unwrap().close_price).unwrap();
|
||||
if let (Some(macd_vec), Some(rt_price_vec)) =
|
||||
(macd_1d_map.get(symbol), alldata.rt_price_1d_vec.get(symbol))
|
||||
{
|
||||
if macd_vec.last().unwrap().close_time == rt_price_vec.last().unwrap().close_time
|
||||
&& rt_price_vec.last().unwrap().close_time > server_epoch
|
||||
{
|
||||
if macd_vec.len() >= 30
|
||||
&& (macd_vec[macd_vec.len() - 1].macd_value
|
||||
- macd_vec[macd_vec.len() - 1].signal_value)
|
||||
.is_sign_negative()
|
||||
&& (macd_vec[macd_vec.len() - 2].macd_value
|
||||
- macd_vec[macd_vec.len() - 2].signal_value)
|
||||
.is_sign_negative()
|
||||
&& (macd_vec[macd_vec.len() - 1].macd_value
|
||||
- macd_vec[macd_vec.len() - 1].signal_value
|
||||
> macd_vec[macd_vec.len() - 2].macd_value
|
||||
- macd_vec[macd_vec.len() - 2].signal_value)
|
||||
{
|
||||
values.current_price = rust_decimal::prelude::FromPrimitive::from_f64(
|
||||
rt_price_vec.last().unwrap().close_price,
|
||||
)
|
||||
.unwrap();
|
||||
values.closetime = rt_price_vec.last().unwrap().close_time;
|
||||
} else {
|
||||
keys_to_remove.insert(symbol.clone());
|
||||
|
|
@ -57,14 +72,20 @@ pub async fn list_up_for_buy(
|
|||
for (symbol, values) in &mut filtered_data {
|
||||
if stoch_rsis.contains_key(symbol) {
|
||||
let stoch_rsi_vec = stoch_rsis.get(symbol).unwrap();
|
||||
let search_result = stoch_rsi_vec.iter().position(|x| x.close_time == values.closetime);
|
||||
if stoch_rsi_vec.len() > 10 && search_result.is_some_and(|a| stoch_rsi_vec[a-3].k < 20.0 &&
|
||||
stoch_rsi_vec[a-2].k < 15.0 &&
|
||||
stoch_rsi_vec[a-1].k < 10.0 &&
|
||||
stoch_rsi_vec[a-1].k < stoch_rsi_vec[a].k &&
|
||||
stoch_rsi_vec[a].k < stoch_rsi_vec[a].d &&
|
||||
!stoch_rsi_vec[a].d.is_subnormal() &&
|
||||
stoch_rsi_vec[a].d > 0.00000001) {
|
||||
let search_result = stoch_rsi_vec
|
||||
.iter()
|
||||
.position(|x| x.close_time == values.closetime);
|
||||
if stoch_rsi_vec.len() > 10
|
||||
&& search_result.is_some_and(|a| {
|
||||
stoch_rsi_vec[a - 3].k < 20.0
|
||||
&& stoch_rsi_vec[a - 2].k < 15.0
|
||||
&& stoch_rsi_vec[a - 1].k < 10.0
|
||||
&& stoch_rsi_vec[a - 1].k < stoch_rsi_vec[a].k
|
||||
&& stoch_rsi_vec[a].k < stoch_rsi_vec[a].d
|
||||
&& !stoch_rsi_vec[a].d.is_subnormal()
|
||||
&& stoch_rsi_vec[a].d > 0.00000001
|
||||
})
|
||||
{
|
||||
} else {
|
||||
keys_to_remove.insert(symbol.clone());
|
||||
}
|
||||
|
|
@ -77,11 +98,16 @@ pub async fn list_up_for_buy(
|
|||
// 2nd filtering: supertrend(ATR period 30, multiplier: 2.0, 1d close price) UP area
|
||||
let mut keys_to_remove: HashSet<String> = HashSet::new();
|
||||
let server_epoch = get_server_epoch().await;
|
||||
let supertrend_1d_map = supertrend(30, 2.0, true, &alldata.rt_price_1d_vec, &filtered_data).await?;
|
||||
let supertrend_1d_map =
|
||||
supertrend(30, 2.0, true, &alldata.rt_price_1d_vec, &filtered_data).await?;
|
||||
for (symbol, values) in &mut filtered_data {
|
||||
if let (Some(supertrend_vec), Some(rt_price_vec)) = (supertrend_1d_map.get(symbol), alldata.rt_price_1d_vec.get(symbol)) {
|
||||
if supertrend_vec.last().unwrap().close_time == rt_price_vec.last().unwrap().close_time &&
|
||||
rt_price_vec.last().unwrap().close_time > server_epoch {
|
||||
if let (Some(supertrend_vec), Some(rt_price_vec)) = (
|
||||
supertrend_1d_map.get(symbol),
|
||||
alldata.rt_price_1d_vec.get(symbol),
|
||||
) {
|
||||
if supertrend_vec.last().unwrap().close_time == rt_price_vec.last().unwrap().close_time
|
||||
&& rt_price_vec.last().unwrap().close_time > server_epoch
|
||||
{
|
||||
if supertrend_vec.last().unwrap().area == SuperTrendArea::UP {
|
||||
} else {
|
||||
keys_to_remove.insert(symbol.clone());
|
||||
|
|
@ -98,24 +124,48 @@ pub async fn list_up_for_buy(
|
|||
// 2nd filtering: supertrend(ATR period 14, multiplier: 1.2, 1d close price)
|
||||
let mut keys_to_remove: HashSet<String> = HashSet::new();
|
||||
let server_epoch = get_server_epoch().await;
|
||||
let supertrend_1d_map = supertrend(14, 1.2, true, &alldata.rt_price_1d_vec, &filtered_data).await?;
|
||||
let supertrend_1d_map =
|
||||
supertrend(14, 1.2, true, &alldata.rt_price_1d_vec, &filtered_data).await?;
|
||||
for (symbol, values) in &mut filtered_data {
|
||||
if let (Some(supertrend_vec), Some(rt_price_vec)) = (supertrend_1d_map.get(symbol), alldata.rt_price_1d_vec.get(symbol)) {
|
||||
if supertrend_vec.last().unwrap().close_time == rt_price_vec.last().unwrap().close_time &&
|
||||
rt_price_vec.last().unwrap().close_time > server_epoch {
|
||||
// input stoploss, target_price
|
||||
let band_value: Decimal = rust_decimal::prelude::FromPrimitive::from_f64(supertrend_vec.last().unwrap().band_value).unwrap();
|
||||
if supertrend_vec.last().unwrap().area == SuperTrendArea::DOWN &&
|
||||
supertrend_vec.last().unwrap().band_value > values.current_price.to_f64().unwrap()
|
||||
if let (Some(supertrend_vec), Some(rt_price_vec)) = (
|
||||
supertrend_1d_map.get(symbol),
|
||||
alldata.rt_price_1d_vec.get(symbol),
|
||||
) {
|
||||
if supertrend_vec.last().unwrap().close_time == rt_price_vec.last().unwrap().close_time
|
||||
&& rt_price_vec.last().unwrap().close_time > server_epoch
|
||||
{
|
||||
values.stoploss = decimal_sub(values.current_price, decimal_sub(band_value, values.current_price));
|
||||
values.target_price = decimal_add(decimal_mul(decimal_sub(values.current_price, values.stoploss), dec!(2.0)), values.current_price);
|
||||
|
||||
} else if supertrend_vec.last().unwrap().area == SuperTrendArea::UP &&
|
||||
supertrend_vec.last().unwrap().band_value < values.current_price.to_f64().unwrap()
|
||||
// input stoploss, target_price
|
||||
let band_value: Decimal = rust_decimal::prelude::FromPrimitive::from_f64(
|
||||
supertrend_vec.last().unwrap().band_value,
|
||||
)
|
||||
.unwrap();
|
||||
if supertrend_vec.last().unwrap().area == SuperTrendArea::DOWN
|
||||
&& supertrend_vec.last().unwrap().band_value
|
||||
> values.current_price.to_f64().unwrap()
|
||||
{
|
||||
values.stoploss = decimal_sub(
|
||||
values.current_price,
|
||||
decimal_sub(band_value, values.current_price),
|
||||
);
|
||||
values.target_price = decimal_add(
|
||||
decimal_mul(
|
||||
decimal_sub(values.current_price, values.stoploss),
|
||||
dec!(2.0),
|
||||
),
|
||||
values.current_price,
|
||||
);
|
||||
} else if supertrend_vec.last().unwrap().area == SuperTrendArea::UP
|
||||
&& supertrend_vec.last().unwrap().band_value
|
||||
< values.current_price.to_f64().unwrap()
|
||||
{
|
||||
values.stoploss = band_value;
|
||||
values.target_price = decimal_add(decimal_mul(decimal_sub(values.current_price, values.stoploss), dec!(2.0)), values.current_price);
|
||||
values.target_price = decimal_add(
|
||||
decimal_mul(
|
||||
decimal_sub(values.current_price, values.stoploss),
|
||||
dec!(2.0),
|
||||
),
|
||||
values.current_price,
|
||||
);
|
||||
} else {
|
||||
keys_to_remove.insert(symbol.clone());
|
||||
}
|
||||
|
|
@ -135,12 +185,17 @@ pub async fn list_up_for_buy(
|
|||
if let Some(rt_price_vec) = alldata.rt_price_1d_vec.get(symbol) {
|
||||
if rt_price_vec.last().unwrap().close_time > server_epoch && rt_price_vec.len() >= 6 {
|
||||
let mut opclo_vec: Vec<f64> = Vec::new();
|
||||
opclo_vec.push(rt_price_vec[rt_price_vec.len()-2].opclo_price);
|
||||
opclo_vec.push(rt_price_vec[rt_price_vec.len()-3].opclo_price);
|
||||
opclo_vec.push(rt_price_vec[rt_price_vec.len()-4].opclo_price);
|
||||
opclo_vec.push(rt_price_vec[rt_price_vec.len()-5].opclo_price);
|
||||
opclo_vec.push(rt_price_vec[rt_price_vec.len()-6].opclo_price);
|
||||
let max_idx = opclo_vec.iter().position(|&x| x == *opclo_vec.iter().max_by(|&a, &b| a.partial_cmp(b).unwrap()).unwrap());
|
||||
opclo_vec.push(rt_price_vec[rt_price_vec.len() - 2].opclo_price);
|
||||
opclo_vec.push(rt_price_vec[rt_price_vec.len() - 3].opclo_price);
|
||||
opclo_vec.push(rt_price_vec[rt_price_vec.len() - 4].opclo_price);
|
||||
opclo_vec.push(rt_price_vec[rt_price_vec.len() - 5].opclo_price);
|
||||
opclo_vec.push(rt_price_vec[rt_price_vec.len() - 6].opclo_price);
|
||||
let max_idx = opclo_vec.iter().position(|&x| {
|
||||
x == *opclo_vec
|
||||
.iter()
|
||||
.max_by(|&a, &b| a.partial_cmp(b).unwrap())
|
||||
.unwrap()
|
||||
});
|
||||
opclo_vec.remove(max_idx.unwrap());
|
||||
|
||||
let mut mean = 0.0;
|
||||
|
|
@ -188,49 +243,63 @@ pub async fn list_up_for_sell(
|
|||
for element in &filled_buy_orders {
|
||||
filtered_symbols.insert(element.symbol.clone(), FilteredDataValue::new());
|
||||
}
|
||||
let supertrend_1d = supertrend(14, 1.2, true, &all_data.rt_price_1d_vec, &filtered_symbols).await?;
|
||||
let supertrend_1d =
|
||||
supertrend(14, 1.2, true, &all_data.rt_price_1d_vec, &filtered_symbols).await?;
|
||||
for element in filled_buy_orders {
|
||||
let mut is_sell = false;
|
||||
let opclo_sample_length: usize = 15; // 15 candle samsples
|
||||
let mut target_profit_percent = 0.0;
|
||||
if let Some(price_1d_vec) = all_data
|
||||
.rt_price_1d_vec
|
||||
.get(&element.symbol)
|
||||
{
|
||||
if let Some(price_1d_vec) = all_data.rt_price_1d_vec.get(&element.symbol) {
|
||||
let vec_len = price_1d_vec.len();
|
||||
if let Some(candles) = price_1d_vec.get(vec_len-opclo_sample_length-2..vec_len-1) {
|
||||
if let Some(candles) =
|
||||
price_1d_vec.get(vec_len - opclo_sample_length - 2..vec_len - 1)
|
||||
{
|
||||
let windows = candles.windows(2);
|
||||
let mut sum_amplitude_candles = 0.0;
|
||||
let mut sum_ratio_amp_body = 0.0;
|
||||
let mut average_amplitude = 0.0;
|
||||
|
||||
for window in windows {
|
||||
sum_amplitude_candles += ((window.last().unwrap().high_price - window.last().unwrap().low_price) * 100.0) / window.first().unwrap().close_price;
|
||||
sum_amplitude_candles += ((window.last().unwrap().high_price
|
||||
- window.last().unwrap().low_price)
|
||||
* 100.0)
|
||||
/ window.first().unwrap().close_price;
|
||||
}
|
||||
let average_amplitude = sum_amplitude_candles / opclo_sample_length as f64; // percent unit
|
||||
let mut amplitude_variance = 0.0;
|
||||
|
||||
let windows = candles.windows(2);
|
||||
for window in windows {
|
||||
amplitude_variance += ((((window.last().unwrap().high_price - window.last().unwrap().low_price) * 100.0) / window.first().unwrap().close_price) - average_amplitude).powi(2);
|
||||
amplitude_variance += ((((window.last().unwrap().high_price
|
||||
- window.last().unwrap().low_price)
|
||||
* 100.0)
|
||||
/ window.first().unwrap().close_price)
|
||||
- average_amplitude)
|
||||
.powi(2);
|
||||
}
|
||||
amplitude_variance = amplitude_variance / (opclo_sample_length - 1) as f64;
|
||||
let standard_deviation_amplitude = amplitude_variance.sqrt();
|
||||
target_profit_percent = average_amplitude + (standard_deviation_amplitude * 0.5);
|
||||
target_profit_percent =
|
||||
average_amplitude + (standard_deviation_amplitude * 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
if element.used_usdt >= dec!(10.0) {
|
||||
if let (Some(exchange_info), Some(tradefee), Some(supertrend_vec)) =
|
||||
(exchange_info_map.get(&element.symbol), trade_fee_map.get(&element.symbol), supertrend_1d.get(&element.symbol)) {
|
||||
if let (Some(exchange_info), Some(tradefee), Some(supertrend_vec)) = (
|
||||
exchange_info_map.get(&element.symbol),
|
||||
trade_fee_map.get(&element.symbol),
|
||||
supertrend_1d.get(&element.symbol),
|
||||
) {
|
||||
// update stoploss
|
||||
let band_value: Decimal = rust_decimal::prelude::FromPrimitive::from_f64(supertrend_vec.last().unwrap().band_value).unwrap();
|
||||
let band_value: Decimal = rust_decimal::prelude::FromPrimitive::from_f64(
|
||||
supertrend_vec.last().unwrap().band_value,
|
||||
)
|
||||
.unwrap();
|
||||
if supertrend_vec.last().unwrap().area == SuperTrendArea::UP
|
||||
&& band_value > element.stoploss {
|
||||
&& band_value > element.stoploss
|
||||
{
|
||||
let update_table_name = String::from("buy_ordered_coin_list");
|
||||
let update_value = vec![
|
||||
(String::from("stoploss"), band_value.to_string()),
|
||||
];
|
||||
let update_value = vec![(String::from("stoploss"), band_value.to_string())];
|
||||
let update_condition = vec![(String::from("id"), element.id.to_string())];
|
||||
update_record3(&update_table_name, &update_value, &update_condition)
|
||||
.await
|
||||
|
|
@ -239,8 +308,7 @@ pub async fn list_up_for_sell(
|
|||
|
||||
let lot_step_size = exchange_info.stepsize;
|
||||
let quote_commission_precision = exchange_info.quote_commission_precision;
|
||||
let base_qty_to_be_ordered =
|
||||
element.base_qty_ordered.round_dp_with_strategy(
|
||||
let base_qty_to_be_ordered = element.base_qty_ordered.round_dp_with_strategy(
|
||||
lot_step_size.normalize().scale(),
|
||||
RoundingStrategy::ToZero,
|
||||
);
|
||||
|
|
@ -252,15 +320,28 @@ pub async fn list_up_for_sell(
|
|||
is_sell = true;
|
||||
} else if element.current_price >= element.target_price {
|
||||
is_sell = true;
|
||||
} else if (element.pure_profit_percent >= target_profit_percent * 2.5) && (target_profit_percent != 0.0 && target_profit_percent.is_sign_positive()) { // absolute sell profit percent
|
||||
} else if (element.pure_profit_percent >= target_profit_percent * 2.5)
|
||||
&& (target_profit_percent != 0.0
|
||||
&& target_profit_percent.is_sign_positive())
|
||||
{
|
||||
// absolute sell profit percent
|
||||
is_sell = true;
|
||||
} else if server_epoch - element.transact_time > (86_400_000) * 5 &&
|
||||
(target_profit_percent != 0.0 && target_profit_percent.is_sign_positive() && target_profit_percent * 2.0 <= element.pure_profit_percent){ // scaled selling with time up selling (5 days)
|
||||
} else if server_epoch - element.transact_time > (86_400_000) * 5
|
||||
&& (target_profit_percent != 0.0
|
||||
&& target_profit_percent.is_sign_positive()
|
||||
&& target_profit_percent * 2.0 <= element.pure_profit_percent)
|
||||
{
|
||||
// scaled selling with time up selling (5 days)
|
||||
is_sell = true;
|
||||
} else if server_epoch - element.transact_time > (86_400_000) * 6 &&
|
||||
(target_profit_percent != 0.0 && target_profit_percent.is_sign_positive() && target_profit_percent * 1.5 <= element.pure_profit_percent){ // scaled selling with time up selling (6 days)
|
||||
} else if server_epoch - element.transact_time > (86_400_000) * 6
|
||||
&& (target_profit_percent != 0.0
|
||||
&& target_profit_percent.is_sign_positive()
|
||||
&& target_profit_percent * 1.5 <= element.pure_profit_percent)
|
||||
{
|
||||
// scaled selling with time up selling (6 days)
|
||||
is_sell = true;
|
||||
} else if server_epoch - element.transact_time > (86_400_000) * 7 { // time up selling
|
||||
} else if server_epoch - element.transact_time > (86_400_000) * 7 {
|
||||
// time up selling
|
||||
is_sell = true;
|
||||
}
|
||||
// TODO: sell_count가 1일 때 적용하기
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
use super::{
|
||||
dec, decimal_add, decimal_sub, decimal_div, decimal_mul, ema, exists_record, insert_pre_suggested_coins,
|
||||
limit_order_sell, rsi, select_filled_buy_orders, stoch_rsi, supertrend, try_join_all, AllData,
|
||||
Arc, Client, ClientBuilder, Decimal, EmaData, ExchangeInfo, FilteredDataValue, Mutex,
|
||||
RealtimePriceData, RoundingStrategy, RsiData, StochRsiData, SupertrendData, TradeFee, update_record3, adx, AdxData, get_server_epoch, MacdData, ema_macd,
|
||||
BollingerBandData, ToPrimitive, duplicate_filter, HashMap, HashSet, remove_keys, SuperTrendArea, SuperTrendSignal, get_current_price
|
||||
adx, dec, decimal_add, decimal_div, decimal_mul, decimal_sub, duplicate_filter, ema, ema_macd,
|
||||
exists_record, get_current_price, get_server_epoch, insert_pre_suggested_coins,
|
||||
limit_order_sell, remove_keys, rsi, select_filled_buy_orders, stoch_rsi, supertrend,
|
||||
try_join_all, update_record3, AdxData, AllData, Arc, BollingerBandData, Client, ClientBuilder,
|
||||
Decimal, EmaData, ExchangeInfo, FilteredDataValue, HashMap, HashSet, MacdData, Mutex,
|
||||
RealtimePriceData, RoundingStrategy, RsiData, StochRsiData, SuperTrendArea, SuperTrendSignal,
|
||||
SupertrendData, ToPrimitive, TradeFee,
|
||||
};
|
||||
|
||||
// BUY conditions
|
||||
|
|
@ -31,11 +33,15 @@ pub async fn list_up_for_buy(
|
|||
let adx_vec = adx(10, 10, &alldata.rt_price_1d_vec, &filtered_data).await?;
|
||||
for (symbol, values) in &mut filtered_data {
|
||||
if let Some(adx_vec) = adx_vec.get(symbol) {
|
||||
if let Some(last_idx) = adx_vec.iter().position(|elem| elem.close_time == values.closetime) {
|
||||
if
|
||||
adx_vec[last_idx].adx > adx_vec[last_idx-1].adx &&
|
||||
adx_vec[last_idx-1].adx > adx_vec[last_idx-2].adx &&
|
||||
adx_vec[last_idx].adx < 25.0 {
|
||||
if let Some(last_idx) = adx_vec
|
||||
.iter()
|
||||
.position(|elem| elem.close_time == values.closetime)
|
||||
{
|
||||
if adx_vec.len() > 10
|
||||
&& adx_vec[last_idx].adx > adx_vec[last_idx - 1].adx
|
||||
&& adx_vec[last_idx - 1].adx > adx_vec[last_idx - 2].adx
|
||||
&& adx_vec[last_idx].adx < 25.0
|
||||
{
|
||||
} else {
|
||||
keys_to_remove.insert(symbol.clone());
|
||||
}
|
||||
|
|
@ -47,17 +53,21 @@ pub async fn list_up_for_buy(
|
|||
}
|
||||
}
|
||||
remove_keys(&mut filtered_data, keys_to_remove).await;
|
||||
|
||||
println!("{}", filtered_data.keys().len());
|
||||
// 2nd filtering: the 2 previous ADX(5, 5)s increase, ADX < 40
|
||||
let mut keys_to_remove: HashSet<String> = HashSet::new();
|
||||
let adx_vec = adx(10, 10, &alldata.rt_price_1d_vec, &filtered_data).await?;
|
||||
for (symbol, values) in &mut filtered_data {
|
||||
if let Some(adx_vec) = adx_vec.get(symbol) {
|
||||
if let Some(last_idx) = adx_vec.iter().position(|elem| elem.close_time == values.closetime) {
|
||||
if
|
||||
adx_vec[last_idx].adx > adx_vec[last_idx-1].adx &&
|
||||
adx_vec[last_idx-1].adx > adx_vec[last_idx-2].adx &&
|
||||
adx_vec[last_idx].adx < 40.0 {
|
||||
if let Some(last_idx) = adx_vec
|
||||
.iter()
|
||||
.position(|elem| elem.close_time == values.closetime)
|
||||
{
|
||||
if adx_vec.len() > 10
|
||||
&& adx_vec[last_idx].adx > adx_vec[last_idx - 1].adx
|
||||
&& adx_vec[last_idx - 1].adx > adx_vec[last_idx - 2].adx
|
||||
&& adx_vec[last_idx].adx < 40.0
|
||||
{
|
||||
} else {
|
||||
keys_to_remove.insert(symbol.clone());
|
||||
}
|
||||
|
|
@ -75,7 +85,10 @@ pub async fn list_up_for_buy(
|
|||
let rsi_map = rsi(5, &alldata.rt_price_1d_vec, &filtered_data).await?;
|
||||
for (symbol, values) in &mut filtered_data {
|
||||
if let Some(rsi_vec) = rsi_map.get(symbol) {
|
||||
if let Some(last_idx) = rsi_vec.iter().position(|elem| elem.close_time == values.closetime) {
|
||||
if let Some(last_idx) = rsi_vec
|
||||
.iter()
|
||||
.position(|elem| elem.close_time == values.closetime)
|
||||
{
|
||||
if rsi_vec[last_idx].rsi_value > 75.0 {
|
||||
keys_to_remove.insert(symbol.clone());
|
||||
}
|
||||
|
|
@ -91,20 +104,38 @@ pub async fn list_up_for_buy(
|
|||
// 4th filtering: supertrend(ATR period 14, multiplier: 1.2, 1d close price)
|
||||
let mut keys_to_remove: HashSet<String> = HashSet::new();
|
||||
let server_epoch = get_server_epoch().await;
|
||||
let supertrend_1d_map = supertrend(14, 1.2, true, &alldata.rt_price_1d_vec, &filtered_data).await?;
|
||||
let supertrend_1d_map =
|
||||
supertrend(14, 1.2, true, &alldata.rt_price_1d_vec, &filtered_data).await?;
|
||||
for (symbol, values) in &mut filtered_data {
|
||||
if let (Some(supertrend_vec), Some(rt_price_vec)) = (supertrend_1d_map.get(symbol), alldata.rt_price_1d_vec.get(symbol)) {
|
||||
if supertrend_vec.last().unwrap().close_time == rt_price_vec.last().unwrap().close_time &&
|
||||
rt_price_vec.last().unwrap().close_time > server_epoch {
|
||||
// input stoploss, target_price
|
||||
let band_value: Decimal = rust_decimal::prelude::FromPrimitive::from_f64(supertrend_vec.last().unwrap().band_value).unwrap();
|
||||
if supertrend_vec.last().unwrap().area == SuperTrendArea::UP &&
|
||||
supertrend_vec.last().unwrap().band_value < values.current_price.to_f64().unwrap()
|
||||
if let (Some(supertrend_vec), Some(rt_price_vec)) = (
|
||||
supertrend_1d_map.get(symbol),
|
||||
alldata.rt_price_1d_vec.get(symbol),
|
||||
) {
|
||||
if supertrend_vec.last().unwrap().close_time == rt_price_vec.last().unwrap().close_time
|
||||
&& rt_price_vec.last().unwrap().close_time > server_epoch
|
||||
{
|
||||
values.current_price = rust_decimal::prelude::FromPrimitive::from_f64(rt_price_vec.last().unwrap().close_price).unwrap();
|
||||
// input stoploss, target_price
|
||||
let band_value: Decimal = rust_decimal::prelude::FromPrimitive::from_f64(
|
||||
supertrend_vec.last().unwrap().band_value,
|
||||
)
|
||||
.unwrap();
|
||||
if supertrend_vec.last().unwrap().area == SuperTrendArea::UP
|
||||
&& supertrend_vec.last().unwrap().band_value
|
||||
< values.current_price.to_f64().unwrap()
|
||||
{
|
||||
values.current_price = rust_decimal::prelude::FromPrimitive::from_f64(
|
||||
rt_price_vec.last().unwrap().close_price,
|
||||
)
|
||||
.unwrap();
|
||||
values.closetime = rt_price_vec.last().unwrap().close_time;
|
||||
values.stoploss = band_value;
|
||||
values.target_price = decimal_add(decimal_mul(decimal_sub(values.current_price, values.stoploss), dec!(3.0)), values.current_price);
|
||||
values.target_price = decimal_add(
|
||||
decimal_mul(
|
||||
decimal_sub(values.current_price, values.stoploss),
|
||||
dec!(3.0),
|
||||
),
|
||||
values.current_price,
|
||||
);
|
||||
} else {
|
||||
keys_to_remove.insert(symbol.clone());
|
||||
}
|
||||
|
|
@ -124,12 +155,17 @@ pub async fn list_up_for_buy(
|
|||
if let Some(rt_price_vec) = alldata.rt_price_1d_vec.get(symbol) {
|
||||
if rt_price_vec.last().unwrap().close_time > server_epoch && rt_price_vec.len() >= 6 {
|
||||
let mut opclo_vec: Vec<f64> = Vec::new();
|
||||
opclo_vec.push(rt_price_vec[rt_price_vec.len()-2].opclo_price);
|
||||
opclo_vec.push(rt_price_vec[rt_price_vec.len()-3].opclo_price);
|
||||
opclo_vec.push(rt_price_vec[rt_price_vec.len()-4].opclo_price);
|
||||
opclo_vec.push(rt_price_vec[rt_price_vec.len()-5].opclo_price);
|
||||
opclo_vec.push(rt_price_vec[rt_price_vec.len()-6].opclo_price);
|
||||
let max_idx = opclo_vec.iter().position(|&x| x == *opclo_vec.iter().max_by(|&a, &b| a.partial_cmp(b).unwrap()).unwrap());
|
||||
opclo_vec.push(rt_price_vec[rt_price_vec.len() - 2].opclo_price);
|
||||
opclo_vec.push(rt_price_vec[rt_price_vec.len() - 3].opclo_price);
|
||||
opclo_vec.push(rt_price_vec[rt_price_vec.len() - 4].opclo_price);
|
||||
opclo_vec.push(rt_price_vec[rt_price_vec.len() - 5].opclo_price);
|
||||
opclo_vec.push(rt_price_vec[rt_price_vec.len() - 6].opclo_price);
|
||||
let max_idx = opclo_vec.iter().position(|&x| {
|
||||
x == *opclo_vec
|
||||
.iter()
|
||||
.max_by(|&a, &b| a.partial_cmp(b).unwrap())
|
||||
.unwrap()
|
||||
});
|
||||
opclo_vec.remove(max_idx.unwrap());
|
||||
|
||||
let mut mean = 0.0;
|
||||
|
|
@ -180,22 +216,27 @@ pub async fn list_up_for_sell(
|
|||
for element in &filled_buy_orders {
|
||||
filtered_symbols.insert(element.symbol.clone(), FilteredDataValue::new());
|
||||
}
|
||||
let supertrend_1d = supertrend(14, 1.2, true, &all_data.rt_price_1d_vec, &filtered_symbols).await?;
|
||||
let supertrend_1d =
|
||||
supertrend(14, 1.2, true, &all_data.rt_price_1d_vec, &filtered_symbols).await?;
|
||||
for element in filled_buy_orders {
|
||||
let mut is_sell = false;
|
||||
|
||||
|
||||
if element.used_usdt >= dec!(10.0) {
|
||||
if let (Some(exchange_info), Some(tradefee), Some(supertrend_vec)) =
|
||||
(exchange_info_map.get(&element.symbol), trade_fee_map.get(&element.symbol), supertrend_1d.get(&element.symbol)) {
|
||||
if let (Some(exchange_info), Some(tradefee), Some(supertrend_vec)) = (
|
||||
exchange_info_map.get(&element.symbol),
|
||||
trade_fee_map.get(&element.symbol),
|
||||
supertrend_1d.get(&element.symbol),
|
||||
) {
|
||||
// update stoploss
|
||||
let band_value: Decimal = rust_decimal::prelude::FromPrimitive::from_f64(supertrend_vec.last().unwrap().band_value).unwrap();
|
||||
let band_value: Decimal = rust_decimal::prelude::FromPrimitive::from_f64(
|
||||
supertrend_vec.last().unwrap().band_value,
|
||||
)
|
||||
.unwrap();
|
||||
if supertrend_vec.last().unwrap().area == SuperTrendArea::UP
|
||||
&& band_value > element.stoploss {
|
||||
&& band_value > element.stoploss
|
||||
{
|
||||
let update_table_name = String::from("buy_ordered_coin_list");
|
||||
let update_value = vec![
|
||||
(String::from("stoploss"), band_value.to_string()),
|
||||
];
|
||||
let update_value = vec![(String::from("stoploss"), band_value.to_string())];
|
||||
let update_condition = vec![(String::from("id"), element.id.to_string())];
|
||||
update_record3(&update_table_name, &update_value, &update_condition)
|
||||
.await
|
||||
|
|
@ -204,12 +245,16 @@ pub async fn list_up_for_sell(
|
|||
|
||||
let lot_step_size = exchange_info.stepsize;
|
||||
let quote_commission_precision = exchange_info.quote_commission_precision;
|
||||
let base_qty_to_be_ordered =
|
||||
element.base_qty_ordered.round_dp_with_strategy(
|
||||
let base_qty_to_be_ordered = element.base_qty_ordered.round_dp_with_strategy(
|
||||
lot_step_size.normalize().scale(),
|
||||
RoundingStrategy::ToZero,
|
||||
);
|
||||
let target_profit_percent = decimal_div(decimal_sub(element.stoploss, element.buy_price), element.buy_price).to_f64().unwrap();
|
||||
let target_profit_percent = decimal_div(
|
||||
decimal_sub(element.target_price, element.buy_price),
|
||||
element.buy_price,
|
||||
)
|
||||
.to_f64()
|
||||
.unwrap();
|
||||
if (element.is_long == 0 || element.is_long == 1)
|
||||
&& !element.current_price.is_zero()
|
||||
{
|
||||
|
|
@ -217,28 +262,58 @@ pub async fn list_up_for_sell(
|
|||
is_sell = true;
|
||||
} else if element.current_price >= element.target_price {
|
||||
is_sell = true;
|
||||
} else if server_epoch - element.transact_time > (86_400_000) * 8 &&
|
||||
(target_profit_percent != 0.0 && target_profit_percent.is_sign_positive() && target_profit_percent * (13.0/14.0) <= element.pure_profit_percent) {
|
||||
} else if server_epoch - element.transact_time > (86_400_000) * 8
|
||||
&& (target_profit_percent != 0.0
|
||||
&& target_profit_percent.is_sign_positive()
|
||||
&& target_profit_percent * (13.0 / 14.0)
|
||||
<= element.pure_profit_percent)
|
||||
{
|
||||
is_sell = true;
|
||||
} else if server_epoch - element.transact_time > (86_400_000) * 9 &&
|
||||
(target_profit_percent != 0.0 && target_profit_percent.is_sign_positive() && target_profit_percent * (12.0/14.0) <= element.pure_profit_percent) {
|
||||
} else if server_epoch - element.transact_time > (86_400_000) * 9
|
||||
&& (target_profit_percent != 0.0
|
||||
&& target_profit_percent.is_sign_positive()
|
||||
&& target_profit_percent * (12.0 / 14.0)
|
||||
<= element.pure_profit_percent)
|
||||
{
|
||||
is_sell = true;
|
||||
} else if server_epoch - element.transact_time > (86_400_000) * 10 &&
|
||||
(target_profit_percent != 0.0 && target_profit_percent.is_sign_positive() && target_profit_percent * (11.0/14.0) <= element.pure_profit_percent) {
|
||||
} else if server_epoch - element.transact_time > (86_400_000) * 10
|
||||
&& (target_profit_percent != 0.0
|
||||
&& target_profit_percent.is_sign_positive()
|
||||
&& target_profit_percent * (11.0 / 14.0)
|
||||
<= element.pure_profit_percent)
|
||||
{
|
||||
is_sell = true;
|
||||
} else if server_epoch - element.transact_time > (86_400_000) * 11 &&
|
||||
(target_profit_percent != 0.0 && target_profit_percent.is_sign_positive() && target_profit_percent * (10.0/14.0) <= element.pure_profit_percent) {
|
||||
} else if server_epoch - element.transact_time > (86_400_000) * 11
|
||||
&& (target_profit_percent != 0.0
|
||||
&& target_profit_percent.is_sign_positive()
|
||||
&& target_profit_percent * (10.0 / 14.0)
|
||||
<= element.pure_profit_percent)
|
||||
{
|
||||
is_sell = true;
|
||||
} else if server_epoch - element.transact_time > (86_400_000) * 12 &&
|
||||
(target_profit_percent != 0.0 && target_profit_percent.is_sign_positive() && target_profit_percent * (9.0/14.0) <= element.pure_profit_percent) {
|
||||
} else if server_epoch - element.transact_time > (86_400_000) * 12
|
||||
&& (target_profit_percent != 0.0
|
||||
&& target_profit_percent.is_sign_positive()
|
||||
&& target_profit_percent * (9.0 / 14.0)
|
||||
<= element.pure_profit_percent)
|
||||
{
|
||||
is_sell = true;
|
||||
} else if server_epoch - element.transact_time > (86_400_000) * 13 &&
|
||||
(target_profit_percent != 0.0 && target_profit_percent.is_sign_positive() && target_profit_percent * (8.0/14.0) <= element.pure_profit_percent) {
|
||||
} else if server_epoch - element.transact_time > (86_400_000) * 13
|
||||
&& (target_profit_percent != 0.0
|
||||
&& target_profit_percent.is_sign_positive()
|
||||
&& target_profit_percent * (8.0 / 14.0)
|
||||
<= element.pure_profit_percent)
|
||||
{
|
||||
is_sell = true;
|
||||
} else if server_epoch - element.transact_time > (86_400_000) * 14 &&
|
||||
(target_profit_percent != 0.0 && target_profit_percent.is_sign_positive() && target_profit_percent * (1.0/2.0) <= element.pure_profit_percent) { // scaled selling with time up selling (6 days){
|
||||
} else if server_epoch - element.transact_time > (86_400_000) * 14
|
||||
&& (target_profit_percent != 0.0
|
||||
&& target_profit_percent.is_sign_positive()
|
||||
&& target_profit_percent * (1.0 / 2.0)
|
||||
<= element.pure_profit_percent)
|
||||
{
|
||||
// scaled selling with time up selling (6 days){
|
||||
is_sell = true;
|
||||
} else if server_epoch - element.transact_time > (86_400_000) * 15 { // time up selling
|
||||
} else if server_epoch - element.transact_time > (86_400_000) * 15 {
|
||||
// time up selling
|
||||
is_sell = true;
|
||||
}
|
||||
// TODO: sell_count가 1일 때 적용하기
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
use super::{
|
||||
dec, decimal_add, decimal_sub, decimal_div, decimal_mul, ema, exists_record, insert_pre_suggested_coins,
|
||||
limit_order_sell, rsi, select_filled_buy_orders, stoch_rsi, supertrend, try_join_all, AllData,
|
||||
Arc, Client, ClientBuilder, Decimal, EmaData, ExchangeInfo, FilteredDataValue, Mutex,
|
||||
RealtimePriceData, RoundingStrategy, RsiData, StochRsiData, SupertrendData, TradeFee, update_record3, adx, AdxData, get_server_epoch, MacdData, ema_macd,
|
||||
BollingerBandData, ToPrimitive, duplicate_filter, HashMap, HashSet, remove_keys, SuperTrendArea, SuperTrendSignal, get_current_price, dema, DemaData, tema, TemaData,
|
||||
heatmap_volume, HeatMapLevel, HeatmapVolumeData
|
||||
adx, dec, decimal_add, decimal_div, decimal_mul, decimal_sub, dema, duplicate_filter, ema,
|
||||
ema_macd, exists_record, get_current_price, get_server_epoch, heatmap_volume,
|
||||
insert_pre_suggested_coins, limit_order_sell, remove_keys, rsi, select_filled_buy_orders,
|
||||
stoch_rsi, supertrend, tema, try_join_all, update_record3, AdxData, AllData, Arc,
|
||||
BollingerBandData, Client, ClientBuilder, Decimal, DemaData, EmaData, ExchangeInfo,
|
||||
FilteredDataValue, HashMap, HashSet, HeatMapLevel, HeatmapVolumeData, MacdData, Mutex,
|
||||
RealtimePriceData, RoundingStrategy, RsiData, StochRsiData, SuperTrendArea, SuperTrendSignal,
|
||||
SupertrendData, TemaData, ToPrimitive, TradeFee,
|
||||
};
|
||||
|
||||
// BUY conditions
|
||||
|
|
@ -28,10 +30,12 @@ pub async fn list_up_for_buy(
|
|||
let server_epoch = get_server_epoch().await;
|
||||
for (symbol, values) in &mut filtered_data {
|
||||
if let (Some(tema5_vec), Some(tema10_vec)) = (tema_3.get(symbol), tema_10.get(symbol)) {
|
||||
if tema5_vec.len() > 2 && tema10_vec.len() > 2 &&
|
||||
tema5_vec.last().unwrap().close_time == tema10_vec.last().unwrap().close_time &&
|
||||
tema5_vec.last().unwrap().close_time > server_epoch &&
|
||||
tema10_vec.last().unwrap().close_time > server_epoch {
|
||||
if tema5_vec.len() > 2
|
||||
&& tema10_vec.len() > 2
|
||||
&& tema5_vec.last().unwrap().close_time == tema10_vec.last().unwrap().close_time
|
||||
&& tema5_vec.last().unwrap().close_time > server_epoch
|
||||
&& tema10_vec.last().unwrap().close_time > server_epoch
|
||||
{
|
||||
if tema5_vec.last().unwrap().tema_value > tema10_vec.last().unwrap().tema_value {
|
||||
} else {
|
||||
keys_to_remove.insert(symbol.clone());
|
||||
|
|
@ -53,17 +57,30 @@ pub async fn list_up_for_buy(
|
|||
let tema_200 = tema(200, &alldata.rt_price_30m_vec, &filtered_data).await?;
|
||||
let server_epoch = get_server_epoch().await;
|
||||
for (symbol, values) in &mut filtered_data {
|
||||
if let (Some(tema30_vec), Some(tema5_vec), Some(tema_200_vec), Some(rt_price_vec)) =
|
||||
(tema_30.get(symbol), tema_5.get(symbol), tema_200.get(symbol), alldata.rt_price_30m_vec.get(symbol)) {
|
||||
if (tema30_vec.len() > 10 && tema5_vec.len() > 10 && tema_200_vec.len() > 10 && rt_price_vec.len() > 10) &&
|
||||
tema30_vec.last().unwrap().close_time == tema5_vec.last().unwrap().close_time &&
|
||||
tema_200_vec.last().unwrap().close_time == tema5_vec.last().unwrap().close_time &&
|
||||
tema5_vec.last().unwrap().close_time > server_epoch {
|
||||
if tema30_vec.last().unwrap().tema_value < tema5_vec.last().unwrap().tema_value &&
|
||||
tema30_vec[tema30_vec.len()-2].tema_value > tema5_vec[tema5_vec.len()-2].tema_value &&
|
||||
tema30_vec[tema30_vec.len()-3].tema_value > tema5_vec[tema5_vec.len()-3].tema_value &&
|
||||
tema_200_vec.last().unwrap().tema_value < rt_price_vec.last().unwrap().opclo_price &&
|
||||
tema_200_vec[tema_200_vec.len()-2].tema_value < rt_price_vec[rt_price_vec.len()-2].opclo_price{
|
||||
if let (Some(tema30_vec), Some(tema5_vec), Some(tema_200_vec), Some(rt_price_vec)) = (
|
||||
tema_30.get(symbol),
|
||||
tema_5.get(symbol),
|
||||
tema_200.get(symbol),
|
||||
alldata.rt_price_30m_vec.get(symbol),
|
||||
) {
|
||||
if (tema30_vec.len() > 10
|
||||
&& tema5_vec.len() > 10
|
||||
&& tema_200_vec.len() > 10
|
||||
&& rt_price_vec.len() > 10)
|
||||
&& tema30_vec.last().unwrap().close_time == tema5_vec.last().unwrap().close_time
|
||||
&& tema_200_vec.last().unwrap().close_time == tema5_vec.last().unwrap().close_time
|
||||
&& tema5_vec.last().unwrap().close_time > server_epoch
|
||||
{
|
||||
if tema30_vec.last().unwrap().tema_value < tema5_vec.last().unwrap().tema_value
|
||||
&& tema30_vec[tema30_vec.len() - 2].tema_value
|
||||
> tema5_vec[tema5_vec.len() - 2].tema_value
|
||||
&& tema30_vec[tema30_vec.len() - 3].tema_value
|
||||
> tema5_vec[tema5_vec.len() - 3].tema_value
|
||||
&& tema_200_vec.last().unwrap().tema_value
|
||||
< rt_price_vec.last().unwrap().opclo_price
|
||||
&& tema_200_vec[tema_200_vec.len() - 2].tema_value
|
||||
< rt_price_vec[rt_price_vec.len() - 2].opclo_price
|
||||
{
|
||||
} else {
|
||||
keys_to_remove.insert(symbol.clone());
|
||||
}
|
||||
|
|
@ -79,32 +96,51 @@ pub async fn list_up_for_buy(
|
|||
// supertrend(ATR period 10, multiplier: 2.0, 30m close price)
|
||||
let mut keys_to_remove: HashSet<String> = HashSet::new();
|
||||
let server_epoch = get_server_epoch().await;
|
||||
let supertrend_30m_map = supertrend(10, 2.0, true, &alldata.rt_price_30m_vec, &filtered_data).await?;
|
||||
let supertrend_30m_map =
|
||||
supertrend(10, 2.0, true, &alldata.rt_price_30m_vec, &filtered_data).await?;
|
||||
for (symbol, values) in &mut filtered_data {
|
||||
if let (Some(supertrend_vec), Some(rt_price_vec)) = (supertrend_30m_map.get(symbol), alldata.rt_price_30m_vec.get(symbol)) {
|
||||
if supertrend_vec.last().unwrap().close_time == rt_price_vec.last().unwrap().close_time &&
|
||||
rt_price_vec.last().unwrap().close_time > server_epoch {
|
||||
if let (Some(supertrend_vec), Some(rt_price_vec)) = (
|
||||
supertrend_30m_map.get(symbol),
|
||||
alldata.rt_price_30m_vec.get(symbol),
|
||||
) {
|
||||
if supertrend_vec.last().unwrap().close_time == rt_price_vec.last().unwrap().close_time
|
||||
&& rt_price_vec.last().unwrap().close_time > server_epoch
|
||||
{
|
||||
// input stoploss, target_price
|
||||
let band_value: Decimal = rust_decimal::prelude::FromPrimitive::from_f64(supertrend_vec.last().unwrap().band_value).unwrap();
|
||||
let open_price: Decimal = rust_decimal::prelude::FromPrimitive::from_f64(rt_price_vec.last().unwrap().open_price).unwrap();
|
||||
let current_price: Decimal = rust_decimal::prelude::FromPrimitive::from_f64(rt_price_vec.last().unwrap().close_price).unwrap();
|
||||
if supertrend_vec.last().unwrap().area == SuperTrendArea::UP &&
|
||||
band_value < current_price &&
|
||||
band_value < open_price
|
||||
let band_value: Decimal = rust_decimal::prelude::FromPrimitive::from_f64(
|
||||
supertrend_vec.last().unwrap().band_value,
|
||||
)
|
||||
.unwrap();
|
||||
let open_price: Decimal = rust_decimal::prelude::FromPrimitive::from_f64(
|
||||
rt_price_vec.last().unwrap().open_price,
|
||||
)
|
||||
.unwrap();
|
||||
let current_price: Decimal = rust_decimal::prelude::FromPrimitive::from_f64(
|
||||
rt_price_vec.last().unwrap().close_price,
|
||||
)
|
||||
.unwrap();
|
||||
if supertrend_vec.last().unwrap().area == SuperTrendArea::UP
|
||||
&& band_value < current_price
|
||||
&& band_value < open_price
|
||||
{
|
||||
values.current_price = current_price;
|
||||
values.closetime = rt_price_vec.last().unwrap().close_time;
|
||||
values.stoploss = band_value;
|
||||
values.target_price = decimal_add(decimal_mul(decimal_sub(current_price, values.stoploss), dec!(3.0)), current_price);
|
||||
} else if supertrend_vec.last().unwrap().area == SuperTrendArea::DOWN &&
|
||||
band_value > current_price &&
|
||||
band_value > open_price
|
||||
values.target_price = decimal_add(
|
||||
decimal_mul(decimal_sub(current_price, values.stoploss), dec!(3.0)),
|
||||
current_price,
|
||||
);
|
||||
} else if supertrend_vec.last().unwrap().area == SuperTrendArea::DOWN
|
||||
&& band_value > current_price
|
||||
&& band_value > open_price
|
||||
{
|
||||
values.current_price = current_price;
|
||||
values.closetime = rt_price_vec.last().unwrap().close_time;
|
||||
values.stoploss = decimal_sub(open_price, decimal_sub(band_value, open_price));
|
||||
values.target_price = decimal_add(decimal_mul(decimal_sub(open_price, values.stoploss), dec!(3.0)), current_price);
|
||||
|
||||
values.target_price = decimal_add(
|
||||
decimal_mul(decimal_sub(open_price, values.stoploss), dec!(3.0)),
|
||||
current_price,
|
||||
);
|
||||
} else {
|
||||
keys_to_remove.insert(symbol.clone());
|
||||
}
|
||||
|
|
@ -143,11 +179,17 @@ pub async fn list_up_for_buy(
|
|||
for (symbol, values) in &mut filtered_data {
|
||||
if stoch_rsis.contains_key(symbol) {
|
||||
let stoch_rsi_vec = stoch_rsis.get(symbol).unwrap();
|
||||
let search_result = stoch_rsi_vec.iter().position(|x| x.close_time == values.closetime);
|
||||
if stoch_rsi_vec.len() > 10 && search_result.is_some_and(|a| stoch_rsi_vec[a].k > stoch_rsi_vec[a].d &&
|
||||
stoch_rsi_vec[a].k < 70.0 &&
|
||||
stoch_rsi_vec[a-1].k < 60.0 &&
|
||||
stoch_rsi_vec[a-2].k < 50.0) {
|
||||
let search_result = stoch_rsi_vec
|
||||
.iter()
|
||||
.position(|x| x.close_time == values.closetime);
|
||||
if stoch_rsi_vec.len() > 10
|
||||
&& search_result.is_some_and(|a| {
|
||||
stoch_rsi_vec[a].k > stoch_rsi_vec[a].d
|
||||
&& stoch_rsi_vec[a].k < 70.0
|
||||
&& stoch_rsi_vec[a - 1].k < 60.0
|
||||
&& stoch_rsi_vec[a - 2].k < 50.0
|
||||
})
|
||||
{
|
||||
} else {
|
||||
keys_to_remove.insert(symbol.clone());
|
||||
}
|
||||
|
|
@ -159,25 +201,52 @@ pub async fn list_up_for_buy(
|
|||
|
||||
// Heatmap volume: filtering close price with Extra High is over the previous candle from 30 previous candles
|
||||
let mut keys_to_remove: HashSet<String> = HashSet::new();
|
||||
let heatmap_volumes = heatmap_volume(30, 30, 4.0, 2.5, 1.0, -0.5, &filtered_data, &alldata.rt_price_30m_vec).await?;
|
||||
let heatmap_volumes = heatmap_volume(
|
||||
30,
|
||||
30,
|
||||
4.0,
|
||||
2.5,
|
||||
1.0,
|
||||
-0.5,
|
||||
&filtered_data,
|
||||
&alldata.rt_price_30m_vec,
|
||||
)
|
||||
.await?;
|
||||
for (symbol, values) in &mut filtered_data {
|
||||
if stoch_rsis.contains_key(symbol) {
|
||||
let heatmap_volume_vec = heatmap_volumes.get(symbol).unwrap();
|
||||
if heatmap_volume_vec.len() > 50 {
|
||||
let heatmap_volume_trunc = heatmap_volume_vec.get(heatmap_volume_vec.len()-31..heatmap_volume_vec.len()-1).unwrap();
|
||||
let heatmap_volume_trunc = heatmap_volume_vec
|
||||
.get(heatmap_volume_vec.len() - 31..heatmap_volume_vec.len() - 1)
|
||||
.unwrap();
|
||||
let windows = heatmap_volume_trunc.windows(2);
|
||||
for slice in windows {
|
||||
if slice[1].heatmap_level == HeatMapLevel::ExtraHigh {
|
||||
if let (prev_candle_idx, current_candle_idx) = (
|
||||
(&alldata.rt_price_30m_vec.get(symbol).unwrap().iter().position(|x| x.close_time == slice[0].close_time)).unwrap(),
|
||||
(&alldata.rt_price_30m_vec.get(symbol).unwrap().iter().position(|x| x.close_time == slice[1].close_time)).unwrap()
|
||||
(&alldata
|
||||
.rt_price_30m_vec
|
||||
.get(symbol)
|
||||
.unwrap()
|
||||
.iter()
|
||||
.position(|x| x.close_time == slice[0].close_time))
|
||||
.unwrap(),
|
||||
(&alldata
|
||||
.rt_price_30m_vec
|
||||
.get(symbol)
|
||||
.unwrap()
|
||||
.iter()
|
||||
.position(|x| x.close_time == slice[1].close_time))
|
||||
.unwrap(),
|
||||
) {
|
||||
let prev_candle = &alldata.rt_price_30m_vec.get(symbol).unwrap()[prev_candle_idx];
|
||||
let current_candle = &alldata.rt_price_30m_vec.get(symbol).unwrap()[current_candle_idx];
|
||||
if current_candle.close_price > prev_candle.close_price ||
|
||||
current_candle.close_price > prev_candle.open_price ||
|
||||
current_candle.close_price > prev_candle.high_price ||
|
||||
current_candle.close_price > prev_candle.low_price {
|
||||
let prev_candle =
|
||||
&alldata.rt_price_30m_vec.get(symbol).unwrap()[prev_candle_idx];
|
||||
let current_candle =
|
||||
&alldata.rt_price_30m_vec.get(symbol).unwrap()[current_candle_idx];
|
||||
if current_candle.close_price > prev_candle.close_price
|
||||
|| current_candle.close_price > prev_candle.open_price
|
||||
|| current_candle.close_price > prev_candle.high_price
|
||||
|| current_candle.close_price > prev_candle.low_price
|
||||
{
|
||||
keys_to_remove.insert(symbol.clone());
|
||||
}
|
||||
}
|
||||
|
|
@ -195,12 +264,17 @@ pub async fn list_up_for_buy(
|
|||
if let Some(rt_price_vec) = alldata.rt_price_30m_vec.get(symbol) {
|
||||
if rt_price_vec.last().unwrap().close_time > server_epoch && rt_price_vec.len() >= 6 {
|
||||
let mut opclo_vec: Vec<f64> = Vec::new();
|
||||
opclo_vec.push(rt_price_vec[rt_price_vec.len()-2].opclo_price);
|
||||
opclo_vec.push(rt_price_vec[rt_price_vec.len()-3].opclo_price);
|
||||
opclo_vec.push(rt_price_vec[rt_price_vec.len()-4].opclo_price);
|
||||
opclo_vec.push(rt_price_vec[rt_price_vec.len()-5].opclo_price);
|
||||
opclo_vec.push(rt_price_vec[rt_price_vec.len()-6].opclo_price);
|
||||
let max_idx = opclo_vec.iter().position(|&x| x == *opclo_vec.iter().max_by(|&a, &b| a.partial_cmp(b).unwrap()).unwrap());
|
||||
opclo_vec.push(rt_price_vec[rt_price_vec.len() - 2].opclo_price);
|
||||
opclo_vec.push(rt_price_vec[rt_price_vec.len() - 3].opclo_price);
|
||||
opclo_vec.push(rt_price_vec[rt_price_vec.len() - 4].opclo_price);
|
||||
opclo_vec.push(rt_price_vec[rt_price_vec.len() - 5].opclo_price);
|
||||
opclo_vec.push(rt_price_vec[rt_price_vec.len() - 6].opclo_price);
|
||||
let max_idx = opclo_vec.iter().position(|&x| {
|
||||
x == *opclo_vec
|
||||
.iter()
|
||||
.max_by(|&a, &b| a.partial_cmp(b).unwrap())
|
||||
.unwrap()
|
||||
});
|
||||
opclo_vec.remove(max_idx.unwrap());
|
||||
|
||||
let mut mean = 0.0;
|
||||
|
|
@ -248,34 +322,47 @@ pub async fn list_up_for_sell(
|
|||
for element in &filled_buy_orders {
|
||||
filtered_symbols.insert(element.symbol.clone(), FilteredDataValue::new());
|
||||
}
|
||||
let supertrend_30m = supertrend(10, 2.0, true, &all_data.rt_price_30m_vec, &filtered_symbols).await?;
|
||||
let supertrend_30m =
|
||||
supertrend(10, 2.0, true, &all_data.rt_price_30m_vec, &filtered_symbols).await?;
|
||||
let tema_30 = tema(30, &all_data.rt_price_30m_vec, &filtered_symbols).await?;
|
||||
let tema_5 = tema(5, &all_data.rt_price_30m_vec, &filtered_symbols).await?;
|
||||
for element in filled_buy_orders {
|
||||
let mut is_sell = false;
|
||||
let mut is_overturned = false;
|
||||
if element.used_usdt >= dec!(10.0) {
|
||||
if let (Some(tema30_vec), Some(tema5_vec)) = (tema_30.get(&element.symbol), tema_5.get(&element.symbol)) {
|
||||
if tema30_vec.len() > 2 && tema5_vec.len() > 2 &&
|
||||
tema30_vec.last().unwrap().close_time == tema5_vec.last().unwrap().close_time &&
|
||||
tema30_vec.last().unwrap().close_time > server_epoch &&
|
||||
tema5_vec.last().unwrap().close_time > server_epoch &&
|
||||
tema30_vec.last().unwrap().tema_value > tema5_vec.last().unwrap().tema_value &&
|
||||
tema30_vec[tema30_vec.len()-2].tema_value < tema5_vec[tema5_vec.len()-2].tema_value {
|
||||
if let (Some(tema30_vec), Some(tema5_vec)) =
|
||||
(tema_30.get(&element.symbol), tema_5.get(&element.symbol))
|
||||
{
|
||||
if tema30_vec.len() > 2
|
||||
&& tema5_vec.len() > 2
|
||||
&& tema30_vec.last().unwrap().close_time
|
||||
== tema5_vec.last().unwrap().close_time
|
||||
&& tema30_vec.last().unwrap().close_time > server_epoch
|
||||
&& tema5_vec.last().unwrap().close_time > server_epoch
|
||||
&& tema30_vec.last().unwrap().tema_value
|
||||
> tema5_vec.last().unwrap().tema_value
|
||||
&& tema30_vec[tema30_vec.len() - 2].tema_value
|
||||
< tema5_vec[tema5_vec.len() - 2].tema_value
|
||||
{
|
||||
is_overturned = true;
|
||||
}
|
||||
}
|
||||
|
||||
if let (Some(exchange_info), Some(tradefee), Some(supertrend_vec)) =
|
||||
(exchange_info_map.get(&element.symbol), trade_fee_map.get(&element.symbol), supertrend_30m.get(&element.symbol)) {
|
||||
if let (Some(exchange_info), Some(tradefee), Some(supertrend_vec)) = (
|
||||
exchange_info_map.get(&element.symbol),
|
||||
trade_fee_map.get(&element.symbol),
|
||||
supertrend_30m.get(&element.symbol),
|
||||
) {
|
||||
// update stoploss
|
||||
let band_value: Decimal = rust_decimal::prelude::FromPrimitive::from_f64(supertrend_vec.last().unwrap().band_value).unwrap();
|
||||
let band_value: Decimal = rust_decimal::prelude::FromPrimitive::from_f64(
|
||||
supertrend_vec.last().unwrap().band_value,
|
||||
)
|
||||
.unwrap();
|
||||
if supertrend_vec.last().unwrap().area == SuperTrendArea::UP
|
||||
&& band_value > element.stoploss {
|
||||
&& band_value > element.stoploss
|
||||
{
|
||||
let update_table_name = String::from("buy_ordered_coin_list");
|
||||
let update_value = vec![
|
||||
(String::from("stoploss"), band_value.to_string()),
|
||||
];
|
||||
let update_value = vec![(String::from("stoploss"), band_value.to_string())];
|
||||
let update_condition = vec![(String::from("id"), element.id.to_string())];
|
||||
update_record3(&update_table_name, &update_value, &update_condition)
|
||||
.await
|
||||
|
|
@ -297,27 +384,40 @@ pub async fn list_up_for_sell(
|
|||
lot_step_size.normalize().scale(),
|
||||
RoundingStrategy::ToZero,
|
||||
);
|
||||
let target_profit_percent = decimal_div(decimal_sub(element.target_price, element.buy_price), element.buy_price).to_f64().unwrap();
|
||||
if !element.current_price.is_zero()
|
||||
{
|
||||
let target_profit_percent = decimal_div(
|
||||
decimal_sub(element.target_price, element.buy_price),
|
||||
element.buy_price,
|
||||
)
|
||||
.to_f64()
|
||||
.unwrap();
|
||||
if !element.current_price.is_zero() {
|
||||
if element.current_price <= element.stoploss {
|
||||
is_sell = true;
|
||||
} else if element.current_price >= element.target_price {
|
||||
is_sell = true;
|
||||
} else if server_epoch - element.transact_time > (1_800_000) * 1 && is_overturned == true {
|
||||
} else if server_epoch - element.transact_time > (1_800_000) * 1
|
||||
&& is_overturned == true
|
||||
{
|
||||
is_sell = true;
|
||||
}
|
||||
|
||||
let minimum_candles = 5;
|
||||
let maximum_candles = 30;
|
||||
for count_candles in minimum_candles..=maximum_candles {
|
||||
if count_candles < maximum_candles &&
|
||||
server_epoch - element.transact_time > (1_800_000) * count_candles &&
|
||||
(target_profit_percent != 0.0 && target_profit_percent.is_sign_positive() &&
|
||||
target_profit_percent * ((maximum_candles - count_candles) as f64 / (maximum_candles - minimum_candles + 1) as f64) <= element.pure_profit_percent) {
|
||||
if count_candles < maximum_candles
|
||||
&& server_epoch - element.transact_time
|
||||
> (1_800_000) * count_candles
|
||||
&& (target_profit_percent != 0.0
|
||||
&& target_profit_percent.is_sign_positive()
|
||||
&& target_profit_percent
|
||||
* ((maximum_candles - count_candles) as f64
|
||||
/ (maximum_candles - minimum_candles + 1) as f64)
|
||||
<= element.pure_profit_percent)
|
||||
{
|
||||
is_sell = true;
|
||||
break;
|
||||
} else if count_candles == maximum_candles { // time up selling
|
||||
} else if count_candles == maximum_candles {
|
||||
// time up selling
|
||||
is_sell = true;
|
||||
break;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use serde::Deserialize;
|
|||
// use super::strategy_test;
|
||||
use super::{
|
||||
exists_record, insert_one_record, try_join_all, try_select_record, AllData, ExchangeInfo,
|
||||
FilteredDataValue, FromRow, RealtimePriceData, TradeFee, HashMap
|
||||
FilteredDataValue, FromRow, HashMap, RealtimePriceData, TradeFee,
|
||||
};
|
||||
use crate::signal_association::signal_decision::*;
|
||||
use tokio::time::{sleep, Duration, Instant};
|
||||
|
|
@ -53,9 +53,24 @@ pub async fn execute_list_up_for_sell(
|
|||
// crate::strategy_team::strategy_003::list_up_for_sell(&all_data, &exchange_info_map, &trade_fee_map).await;
|
||||
// crate::strategy_team::strategy_004::list_up_for_sell(&all_data, &exchange_info_map, &trade_fee_map).await;
|
||||
// crate::strategy_team::strategy_005::list_up_for_sell(&all_data, &exchange_info_map, &trade_fee_map).await;
|
||||
crate::strategy_team::strategy_006::list_up_for_sell(&all_data, &exchange_info_map, &trade_fee_map).await;
|
||||
crate::strategy_team::strategy_007::list_up_for_sell(&all_data, &exchange_info_map, &trade_fee_map).await;
|
||||
crate::strategy_team::strategy_008::list_up_for_sell(&all_data, &exchange_info_map, &trade_fee_map).await;
|
||||
crate::strategy_team::strategy_006::list_up_for_sell(
|
||||
&all_data,
|
||||
&exchange_info_map,
|
||||
&trade_fee_map,
|
||||
)
|
||||
.await;
|
||||
crate::strategy_team::strategy_007::list_up_for_sell(
|
||||
&all_data,
|
||||
&exchange_info_map,
|
||||
&trade_fee_map,
|
||||
)
|
||||
.await;
|
||||
crate::strategy_team::strategy_008::list_up_for_sell(
|
||||
&all_data,
|
||||
&exchange_info_map,
|
||||
&trade_fee_map,
|
||||
)
|
||||
.await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use super::{
|
||||
dec, decimal_add, decimal_sub, ema, exists_record, insert_pre_suggested_coins,
|
||||
limit_order_sell, rsi, select_filled_buy_orders, stoch_rsi, supertrend, try_join_all, AllData,
|
||||
Arc, Client, ClientBuilder, Decimal, EmaData, ExchangeInfo, FilteredData, Mutex,
|
||||
Arc, Client, ClientBuilder, Decimal, EmaData, ExchangeInfo, FilteredDataValue, Mutex,
|
||||
RealtimePriceData, RoundingStrategy, RsiData, StochRsiData, SupertrendData, TradeFee, update_record3, adx, AdxData, MacdData, ema_macd
|
||||
};
|
||||
|
||||
|
|
@ -14,13 +14,13 @@ pub async fn strategist_test(
|
|||
// println!("BTCUSDT: {:?}", alldata.rt_price_30m_vec[a.unwrap()].1.last().unwrap());
|
||||
|
||||
// 1st filtering: lookup tables if the tradepair is already there
|
||||
let mut symbol_1 = FilteredData::new();
|
||||
let mut symbol_1 = FilteredDataValue::new();
|
||||
// let mut symbol_2 = FilteredData::new();
|
||||
// let mut symbol_3 = FilteredData::new();
|
||||
symbol_1.symbol = String::from("BTCUSDT");
|
||||
// symbol_2.symbol = String::from("XRPUSDT");
|
||||
// symbol_3.symbol = String::from("ETHUSDT");
|
||||
let mut test_symbols: Vec<FilteredData> = Vec::new();
|
||||
let mut test_symbols: Vec<FilteredDataValue> = Vec::new();
|
||||
test_symbols.push(symbol_1);
|
||||
// test_symbols.push(symbol_2);
|
||||
// test_symbols.push(symbol_3);
|
||||
|
|
|
|||
|
|
@ -7,12 +7,15 @@ use csv::{DeserializeRecordsIter, StringRecord};
|
|||
use rust_decimal::{prelude::ToPrimitive, Decimal};
|
||||
use serde::Deserialize;
|
||||
use sqlx::FromRow;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::sync::Arc;
|
||||
use tokio::{fs::*, sync::Mutex, time::*};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum CandleType { UP, DOWN }
|
||||
pub enum CandleType {
|
||||
UP,
|
||||
DOWN,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct RealtimePriceData {
|
||||
|
|
@ -93,15 +96,11 @@ pub async fn update_realtime_price_data(
|
|||
rt_price_vec.last_mut().unwrap().candle_type = CandleType::DOWN;
|
||||
}
|
||||
// update high_price
|
||||
if rt_price_vec.last_mut().unwrap().high_price
|
||||
< *current_price
|
||||
{
|
||||
if rt_price_vec.last_mut().unwrap().high_price < *current_price {
|
||||
rt_price_vec.last_mut().unwrap().high_price = *current_price;
|
||||
}
|
||||
// update low_price
|
||||
if rt_price_vec.last_mut().unwrap().low_price
|
||||
> *current_price
|
||||
{
|
||||
if rt_price_vec.last_mut().unwrap().low_price > *current_price {
|
||||
rt_price_vec.last_mut().unwrap().low_price = *current_price;
|
||||
}
|
||||
}
|
||||
|
|
@ -112,7 +111,7 @@ pub async fn update_realtime_price_data(
|
|||
// for 1mon, uses 1w candle
|
||||
if let Some(rt_vec) = read_candle_for_rt.get(element) {
|
||||
if rt_vec.len() >= 2 && rt_price_vec.len() >= 2 {
|
||||
let previous_close_time = rt_price_vec[rt_price_vec.len()-2].close_time;
|
||||
let previous_close_time = rt_price_vec[rt_price_vec.len() - 2].close_time;
|
||||
// update realtime information for the latest candle
|
||||
let mut update_closeprice = 0.0;
|
||||
let mut update_highprice = 0.0;
|
||||
|
|
@ -134,25 +133,22 @@ pub async fn update_realtime_price_data(
|
|||
}| *close_time,
|
||||
);
|
||||
if prev_closetime_result.is_ok() {
|
||||
let result =
|
||||
rt_vec.get(prev_closetime_result.unwrap() + 1..);
|
||||
let result = rt_vec.get(prev_closetime_result.unwrap() + 1..);
|
||||
if result.is_some() {
|
||||
let update_highprice_result =
|
||||
result.unwrap().iter().max_by(|x, y| {
|
||||
x.high_price.partial_cmp(&y.high_price).unwrap()
|
||||
});
|
||||
if update_highprice_result.is_some() {
|
||||
update_highprice =
|
||||
update_highprice_result.unwrap().high_price;
|
||||
update_highprice = update_highprice_result.unwrap().high_price;
|
||||
}
|
||||
|
||||
let update_lowprice_result =
|
||||
result.unwrap().iter().min_by(|x, y| {
|
||||
x.low_price.partial_cmp(&y.low_price).unwrap()
|
||||
});
|
||||
let update_lowprice_result = result
|
||||
.unwrap()
|
||||
.iter()
|
||||
.min_by(|x, y| x.low_price.partial_cmp(&y.low_price).unwrap());
|
||||
if update_lowprice_result.is_some() {
|
||||
update_lowprice =
|
||||
update_lowprice_result.unwrap().low_price;
|
||||
update_lowprice = update_lowprice_result.unwrap().low_price;
|
||||
}
|
||||
|
||||
for element in result.unwrap() {
|
||||
|
|
@ -189,10 +185,8 @@ pub async fn update_realtime_price_data(
|
|||
&& !update_closeprice.is_nan()
|
||||
&& update_closeprice.is_finite()
|
||||
{
|
||||
rt_price_vec.last_mut().unwrap().close_price =
|
||||
update_closeprice;
|
||||
rt_price_vec.last_mut().unwrap().opclo_price =
|
||||
(update_closeprice
|
||||
rt_price_vec.last_mut().unwrap().close_price = update_closeprice;
|
||||
rt_price_vec.last_mut().unwrap().opclo_price = (update_closeprice
|
||||
+ rt_price_vec.last_mut().unwrap().open_price)
|
||||
/ 2.0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
use super::{FilteredDataValue, RealtimePriceData, try_join_all, Arc, Mutex, HashMap};
|
||||
use super::{try_join_all, Arc, FilteredDataValue, HashMap, Mutex, RealtimePriceData};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct AdxData {
|
||||
pub adx: f64,
|
||||
pub close_time: i64
|
||||
pub close_time: i64,
|
||||
}
|
||||
|
||||
struct BasicData {
|
||||
|
|
@ -19,8 +19,12 @@ struct DiData {
|
|||
close_time: i64,
|
||||
}
|
||||
|
||||
pub async fn adx(adx_len: usize, di_len: usize, input_rt_data: &HashMap<String, Vec<RealtimePriceData>>,
|
||||
filtered_symbols: &HashMap<String, FilteredDataValue>,) -> Result<HashMap<String, Vec<AdxData>>, Box<dyn std::error::Error + Send + Sync>> {
|
||||
pub async fn adx(
|
||||
adx_len: usize,
|
||||
di_len: usize,
|
||||
input_rt_data: &HashMap<String, Vec<RealtimePriceData>>,
|
||||
filtered_symbols: &HashMap<String, FilteredDataValue>,
|
||||
) -> Result<HashMap<String, Vec<AdxData>>, Box<dyn std::error::Error + Send + Sync>> {
|
||||
if filtered_symbols.is_empty() {
|
||||
Err(("Err"))?;
|
||||
}
|
||||
|
|
@ -34,7 +38,7 @@ filtered_symbols: &HashMap<String, FilteredDataValue>,) -> Result<HashMap<String
|
|||
let symbol = filtered_symbol.clone();
|
||||
task_vec.push(tokio::spawn(async move {
|
||||
if let Some(rt_price_data) = rt_data_map.get(&symbol) {
|
||||
if rt_price_data.len()-1 > adx_len && rt_price_data.len() > di_len {
|
||||
if rt_price_data.len() - 1 > adx_len && rt_price_data.len() > di_len {
|
||||
// step 1: calculate +DM, -DM, TR
|
||||
let windows = rt_price_data.windows(2);
|
||||
let mut basic_data_vec: Vec<BasicData> = Vec::new();
|
||||
|
|
@ -46,15 +50,19 @@ filtered_symbols: &HashMap<String, FilteredDataValue>,) -> Result<HashMap<String
|
|||
let basic_data = BasicData {
|
||||
dm_plus: if up > down && up > 0.0 { up } else { 0.0 },
|
||||
dm_minus: if down > up && down > 0.0 { down } else { 0.0 },
|
||||
true_range: f64::max(f64::max(current_rt_data.high_price - current_rt_data.low_price,
|
||||
current_rt_data.high_price - prev_rt_data.close_price),
|
||||
current_rt_data.low_price - prev_rt_data.close_price),
|
||||
true_range: f64::max(
|
||||
f64::max(
|
||||
current_rt_data.high_price - current_rt_data.low_price,
|
||||
current_rt_data.high_price - prev_rt_data.close_price,
|
||||
),
|
||||
current_rt_data.low_price - prev_rt_data.close_price,
|
||||
),
|
||||
close_time: current_rt_data.close_time,
|
||||
};
|
||||
basic_data_vec.push(basic_data);
|
||||
}
|
||||
// step 2: smoothing +DM, -DM, TR
|
||||
let alpha: f64 = 1.0/(di_len as f64);
|
||||
let alpha: f64 = 1.0 / (di_len as f64);
|
||||
let mut smoothed_basic_data_vec: Vec<BasicData> = Vec::new();
|
||||
|
||||
let partial_vec1 = basic_data_vec.get(..di_len).unwrap(); // for calculation of initial value
|
||||
|
|
@ -72,21 +80,37 @@ filtered_symbols: &HashMap<String, FilteredDataValue>,) -> Result<HashMap<String
|
|||
dm_minus_calculated /= di_len as f64;
|
||||
tr_calculated /= di_len as f64;
|
||||
|
||||
let basic_data = BasicData { dm_plus: dm_plus_calculated, dm_minus: dm_minus_calculated, true_range: tr_calculated, close_time: partial_vec1.last().unwrap().close_time };
|
||||
let basic_data = BasicData {
|
||||
dm_plus: dm_plus_calculated,
|
||||
dm_minus: dm_minus_calculated,
|
||||
true_range: tr_calculated,
|
||||
close_time: partial_vec1.last().unwrap().close_time,
|
||||
};
|
||||
smoothed_basic_data_vec.push(basic_data);
|
||||
|
||||
for element in partial_vec2 {
|
||||
dm_plus_calculated = alpha * element.dm_plus + (1.0 - alpha) * dm_plus_calculated;
|
||||
dm_minus_calculated = alpha * element.dm_minus + (1.0 - alpha) * dm_minus_calculated;
|
||||
dm_plus_calculated =
|
||||
alpha * element.dm_plus + (1.0 - alpha) * dm_plus_calculated;
|
||||
dm_minus_calculated =
|
||||
alpha * element.dm_minus + (1.0 - alpha) * dm_minus_calculated;
|
||||
tr_calculated = alpha * element.true_range + (1.0 - alpha) * tr_calculated;
|
||||
let basic_data = BasicData { dm_plus: dm_plus_calculated, dm_minus: dm_minus_calculated, true_range: tr_calculated, close_time: element.close_time };
|
||||
let basic_data = BasicData {
|
||||
dm_plus: dm_plus_calculated,
|
||||
dm_minus: dm_minus_calculated,
|
||||
true_range: tr_calculated,
|
||||
close_time: element.close_time,
|
||||
};
|
||||
smoothed_basic_data_vec.push(basic_data);
|
||||
}
|
||||
|
||||
// step 3: calculate DI
|
||||
let mut di_data_vec: Vec<DiData> = Vec::new();
|
||||
for basic_data in smoothed_basic_data_vec {
|
||||
let di_data = DiData { di_plus: (100.0 * basic_data.dm_plus) / basic_data.true_range, di_minus: (100.0 * basic_data.dm_minus) / basic_data.true_range, close_time: basic_data.close_time};
|
||||
let di_data = DiData {
|
||||
di_plus: (100.0 * basic_data.dm_plus) / basic_data.true_range,
|
||||
di_minus: (100.0 * basic_data.dm_minus) / basic_data.true_range,
|
||||
close_time: basic_data.close_time,
|
||||
};
|
||||
di_data_vec.push(di_data);
|
||||
}
|
||||
|
||||
|
|
@ -96,11 +120,17 @@ filtered_symbols: &HashMap<String, FilteredDataValue>,) -> Result<HashMap<String
|
|||
let sum = di_data.di_plus + di_data.di_minus;
|
||||
let difference = (di_data.di_plus - di_data.di_minus).abs();
|
||||
let divisor = if sum <= 0.00000001 { 1.0 } else { sum };
|
||||
let adx_data = AdxData { adx: difference.abs()/divisor, close_time: di_data.close_time };
|
||||
let adx_data = AdxData {
|
||||
adx: difference.abs() / divisor,
|
||||
close_time: di_data.close_time,
|
||||
};
|
||||
initial_adx_vec.push(adx_data);
|
||||
}
|
||||
|
||||
if let (Some(partial_vec1), Some(partial_vec2)) = (initial_adx_vec.get(..adx_len), initial_adx_vec.get(adx_len..)) {
|
||||
if let (Some(partial_vec1), Some(partial_vec2)) = (
|
||||
initial_adx_vec.get(..adx_len),
|
||||
initial_adx_vec.get(adx_len..),
|
||||
) {
|
||||
// partial_vec1 is for calculation of initial value
|
||||
// partial_vec2 is for calculation of the rest
|
||||
let mut smoothed_adx_vec: Vec<AdxData> = Vec::new();
|
||||
|
|
@ -110,13 +140,19 @@ filtered_symbols: &HashMap<String, FilteredDataValue>,) -> Result<HashMap<String
|
|||
}
|
||||
adx_calculated /= adx_len as f64;
|
||||
|
||||
let adx_data = AdxData { adx: adx_calculated, close_time: partial_vec1.last().unwrap().close_time };
|
||||
let adx_data = AdxData {
|
||||
adx: adx_calculated,
|
||||
close_time: partial_vec1.last().unwrap().close_time,
|
||||
};
|
||||
smoothed_adx_vec.push(adx_data);
|
||||
|
||||
let alpha: f64 = 1.0 /(adx_len as f64);
|
||||
let alpha: f64 = 1.0 / (adx_len as f64);
|
||||
for element in partial_vec2 {
|
||||
adx_calculated = alpha * element.adx + (1.0 - alpha) * adx_calculated;
|
||||
let adx_data = AdxData { adx: 100.0 * adx_calculated, close_time: element.close_time };
|
||||
let adx_data = AdxData {
|
||||
adx: 100.0 * adx_calculated,
|
||||
close_time: element.close_time,
|
||||
};
|
||||
smoothed_adx_vec.push(adx_data);
|
||||
}
|
||||
|
||||
|
|
@ -131,5 +167,4 @@ filtered_symbols: &HashMap<String, FilteredDataValue>,) -> Result<HashMap<String
|
|||
|
||||
let a = adx_vec_arc.lock().await.to_owned();
|
||||
Ok(a)
|
||||
|
||||
}
|
||||
|
|
@ -1,16 +1,16 @@
|
|||
#![allow(unused)]
|
||||
#![allow(warnings)]
|
||||
|
||||
use super::HashMap;
|
||||
use crate::database_control::*;
|
||||
use crate::value_estimation_team::datapoints::price_data::RealtimePriceData;
|
||||
use crate::value_estimation_team::indicators::sma::{SmaData, sma};
|
||||
use crate::strategy_team::FilteredDataValue;
|
||||
use crate::value_estimation_team::datapoints::price_data::RealtimePriceData;
|
||||
use crate::value_estimation_team::indicators::sma::{sma, SmaData};
|
||||
use futures::future::try_join_all;
|
||||
use serde::Deserialize;
|
||||
use sqlx::FromRow;
|
||||
use std::sync::Arc;
|
||||
use tokio::{fs::*, io::AsyncWriteExt, sync::Mutex, time::*};
|
||||
use super::{HashMap};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct BollingerBandData {
|
||||
|
|
@ -43,7 +43,8 @@ pub async fn bollingerband(
|
|||
Err(("Err"))?;
|
||||
}
|
||||
|
||||
let mut sma_data_map: HashMap<String, Vec<SmaData>> = sma(period, input_rt_data, filtered_symbols).await?;
|
||||
let mut sma_data_map: HashMap<String, Vec<SmaData>> =
|
||||
sma(period, input_rt_data, filtered_symbols).await?;
|
||||
let mut bb_data_wrapper: HashMap<String, Vec<BollingerBandData>> = HashMap::new();
|
||||
let mut bb_data_wrapper_arc = Arc::new(Mutex::new(bb_data_wrapper));
|
||||
let mut task_vec = Vec::new();
|
||||
|
|
@ -76,13 +77,11 @@ pub async fn bollingerband(
|
|||
match result {
|
||||
Ok(T) => {
|
||||
if T <= period - 1 {
|
||||
let mut read_data_iter =
|
||||
sma_data_vec_c.iter();
|
||||
let mut read_data_iter = sma_data_vec_c.iter();
|
||||
for _ in T..period - 1 {
|
||||
read_data_iter.next();
|
||||
}
|
||||
let window_iter =
|
||||
rt_data_vec_c.windows(period);
|
||||
let window_iter = rt_data_vec_c.windows(period);
|
||||
for buffer in window_iter {
|
||||
let mut sd_mean = 0.0;
|
||||
let mut standard_deviation = 0.0;
|
||||
|
|
@ -94,16 +93,14 @@ pub async fn bollingerband(
|
|||
standard_deviation +=
|
||||
(element.close_price - sd_mean).powi(2);
|
||||
}
|
||||
standard_deviation = sd_factor
|
||||
* ((standard_deviation / period as f64).sqrt());
|
||||
standard_deviation =
|
||||
sd_factor * ((standard_deviation / period as f64).sqrt());
|
||||
|
||||
match read_data_iter.next() {
|
||||
Some(T) => {
|
||||
bb_data.sma = T.sma_value;
|
||||
bb_data.upperband =
|
||||
T.sma_value + standard_deviation;
|
||||
bb_data.lowerband =
|
||||
T.sma_value - standard_deviation;
|
||||
bb_data.upperband = T.sma_value + standard_deviation;
|
||||
bb_data.lowerband = T.sma_value - standard_deviation;
|
||||
bb_data.close_time = T.close_time;
|
||||
bb_data_vec.push(bb_data.clone());
|
||||
}
|
||||
|
|
@ -115,8 +112,7 @@ pub async fn bollingerband(
|
|||
Err(E) => {}
|
||||
}
|
||||
let mut bb_data_wrapper_lock = bb_data_wrapper_arc_c.lock().await;
|
||||
bb_data_wrapper_lock
|
||||
.insert(symbol_c, bb_data_vec.clone());
|
||||
bb_data_wrapper_lock.insert(symbol_c, bb_data_vec.clone());
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
#![allow(unused)]
|
||||
#![allow(warnings)]
|
||||
use super::ema::{ema, EmaData};
|
||||
use super::FilteredDataValue;
|
||||
use crate::database_control::*;
|
||||
use crate::value_estimation_team::datapoints::price_data::RealtimePriceData;
|
||||
use futures::future::try_join_all;
|
||||
use serde::Deserialize;
|
||||
use sqlx::FromRow;
|
||||
use std::collections::HashMap;
|
||||
use std::{iter::zip, sync::Arc};
|
||||
use tokio::{fs::*, io::AsyncWriteExt, sync::Mutex, time::*};
|
||||
use super::FilteredDataValue;
|
||||
use std::collections::HashMap;
|
||||
use super::ema::{ema, EmaData};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct DemaData {
|
||||
|
|
@ -81,7 +81,6 @@ pub async fn dema(
|
|||
ema_data_wrapper_lock.insert(symbol_c, ema_data_vec.clone());
|
||||
}
|
||||
}));
|
||||
|
||||
}
|
||||
try_join_all(task_vec).await?;
|
||||
let e2 = ema_data_wrapper_arc.lock().await.to_owned();
|
||||
|
|
@ -91,14 +90,16 @@ pub async fn dema(
|
|||
let mut task_vec = Vec::new();
|
||||
for (symbol, e2_vec) in e2 {
|
||||
if let Some(e1_vec) = e1.get(&symbol) {
|
||||
let dema_data_wrapper_arc_c: Arc<Mutex<HashMap<String, Vec<DemaData>>>> = Arc::clone(&dema_data_wrapper_arc);
|
||||
let dema_data_wrapper_arc_c: Arc<Mutex<HashMap<String, Vec<DemaData>>>> =
|
||||
Arc::clone(&dema_data_wrapper_arc);
|
||||
let symbol_c = symbol.clone();
|
||||
let e1_vec_c = e1_vec.clone();
|
||||
task_vec.push(tokio::spawn(async move {
|
||||
if e2_vec.last().unwrap().close_time == e1_vec_c.last().unwrap().close_time &&
|
||||
e2_vec.len() < e1_vec_c.len() {
|
||||
if e2_vec.last().unwrap().close_time == e1_vec_c.last().unwrap().close_time
|
||||
&& e2_vec.len() < e1_vec_c.len()
|
||||
{
|
||||
let mut dema_data_vec: Vec<DemaData> = Vec::new();
|
||||
let e1_vec_part = e1_vec_c.get(e1_vec_c.len()-e2_vec.len()..).unwrap();
|
||||
let e1_vec_part = e1_vec_c.get(e1_vec_c.len() - e2_vec.len()..).unwrap();
|
||||
let zipped = e1_vec_part.iter().zip(e2_vec.iter());
|
||||
for element in zipped {
|
||||
let mut dema_data = DemaData::new();
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
#![allow(unused)]
|
||||
#![allow(warnings)]
|
||||
use super::FilteredDataValue;
|
||||
use crate::database_control::*;
|
||||
use crate::value_estimation_team::datapoints::price_data::RealtimePriceData;
|
||||
use futures::future::try_join_all;
|
||||
use serde::Deserialize;
|
||||
use sqlx::FromRow;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use tokio::{fs::*, io::AsyncWriteExt, sync::Mutex, time::*};
|
||||
use super::FilteredDataValue;
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct EmaData {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
use crate::value_estimation_team::datapoints::price_data::RealtimePriceData;
|
||||
use super::FilteredDataValue;
|
||||
use super::HashMap;
|
||||
use crate::value_estimation_team::datapoints::price_data::RealtimePriceData;
|
||||
use futures::future::try_join_all;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::Mutex;
|
||||
use futures::future::try_join_all;
|
||||
use super::HashMap;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum HeatMapLevel {
|
||||
|
|
@ -172,7 +172,6 @@ pub async fn heatmap_volume(
|
|||
}
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
||||
try_join_all(task_vec).await?;
|
||||
let a = heatmap_data_wrapper_arc.lock().await.to_owned();
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
use crate::value_estimation_team::indicators::ema::{EmaData, ema};
|
||||
use crate::value_estimation_team::datapoints::price_data::RealtimePriceData;
|
||||
use super::{FilteredDataValue, HashMap};
|
||||
use crate::value_estimation_team::datapoints::price_data::RealtimePriceData;
|
||||
use crate::value_estimation_team::indicators::ema::{ema, EmaData};
|
||||
use futures::future::try_join_all;
|
||||
use std::sync::Arc;
|
||||
use tokio::{fs::*, io::AsyncWriteExt, sync::Mutex, time::*};
|
||||
use futures::future::try_join_all;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MacdData {
|
||||
|
|
@ -44,7 +44,7 @@ pub async fn ema_macd(
|
|||
slow_len: usize,
|
||||
signal_smoothing: usize,
|
||||
input_rt_data: &HashMap<String, Vec<RealtimePriceData>>,
|
||||
filtered_symbols: &HashMap<String, FilteredDataValue>
|
||||
filtered_symbols: &HashMap<String, FilteredDataValue>,
|
||||
) -> Result<HashMap<String, Vec<MacdData>>, Box<dyn std::error::Error + Send + Sync>> {
|
||||
let mut macd_oscil_vec: HashMap<String, Vec<MacdData>> = HashMap::new();
|
||||
|
||||
|
|
@ -56,13 +56,17 @@ pub async fn ema_macd(
|
|||
for (symbol, filtered_data) in filtered_symbols {
|
||||
let fast_emas_c = fast_emas.clone();
|
||||
let slow_emas_c = slow_emas.clone();
|
||||
if let (Some(fast_ema_vec), Some(slow_ema_vec)) = (fast_emas.get(symbol), slow_emas_c.get(symbol)) {
|
||||
if let (Some(fast_ema_vec), Some(slow_ema_vec)) =
|
||||
(fast_emas.get(symbol), slow_emas_c.get(symbol))
|
||||
{
|
||||
let symbol_c = symbol.clone();
|
||||
let fast_ema_vec_c = fast_ema_vec.clone();
|
||||
let slow_ema_vec_c = slow_ema_vec.clone();
|
||||
let macd_data_wrapper_arc_c = Arc::clone(&macd_data_wrapper_arc);
|
||||
task_vec.push(tokio::spawn(async move {
|
||||
if fast_ema_vec_c.len() >= signal_smoothing && slow_ema_vec_c.len() >= signal_smoothing {
|
||||
if fast_ema_vec_c.len() >= signal_smoothing
|
||||
&& slow_ema_vec_c.len() >= signal_smoothing
|
||||
{
|
||||
let result = fast_ema_vec_c.binary_search_by_key(
|
||||
&slow_ema_vec_c.first().unwrap().close_time,
|
||||
|&EmaData {
|
||||
|
|
@ -124,10 +128,7 @@ pub async fn ema_macd(
|
|||
|
||||
let result = macd_vec.binary_search_by_key(
|
||||
&macd_signal_vec.first().unwrap().close_time,
|
||||
|&TempData {
|
||||
value,
|
||||
close_time,
|
||||
}| close_time,
|
||||
|&TempData { value, close_time }| close_time,
|
||||
);
|
||||
|
||||
if result.is_ok() {
|
||||
|
|
@ -143,7 +144,8 @@ pub async fn ema_macd(
|
|||
macd.close_time = element.0.close_time;
|
||||
macd_vec.push(macd);
|
||||
}
|
||||
let mut macd_data_wrapper_lock = macd_data_wrapper_arc_c.lock().await;
|
||||
let mut macd_data_wrapper_lock =
|
||||
macd_data_wrapper_arc_c.lock().await;
|
||||
macd_data_wrapper_lock.insert(symbol_c, macd_vec.clone());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
pub mod adx;
|
||||
pub mod bollingerband;
|
||||
pub mod dema;
|
||||
pub mod ema;
|
||||
pub mod heatmap_volume;
|
||||
pub mod macd;
|
||||
|
|
@ -8,11 +9,10 @@ pub mod sma;
|
|||
pub mod stoch_rsi;
|
||||
pub mod supertrend;
|
||||
pub mod tema;
|
||||
pub mod dema;
|
||||
|
||||
use crate::strategy_team::FilteredDataValue;
|
||||
use crate::value_estimation_team::datapoints::price_data::RealtimePriceData;
|
||||
use futures::future::try_join_all;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use tokio::{fs::*, io::AsyncWriteExt, sync::Mutex, time::*};
|
||||
use std::collections::HashMap;
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
#![allow(unused)]
|
||||
#![allow(warnings)]
|
||||
|
||||
use super::HashMap;
|
||||
use crate::database_control::*;
|
||||
use crate::value_estimation_team::datapoints::price_data::RealtimePriceData;
|
||||
use crate::strategy_team::FilteredDataValue;
|
||||
use crate::value_estimation_team::datapoints::price_data::RealtimePriceData;
|
||||
use futures::future::try_join_all;
|
||||
use serde::Deserialize;
|
||||
use sqlx::FromRow;
|
||||
use std::f64::NAN;
|
||||
use std::sync::Arc;
|
||||
use tokio::{fs::*, io::AsyncWriteExt, sync::Mutex, time::*};
|
||||
use super::HashMap;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct RsiData {
|
||||
|
|
@ -132,8 +132,8 @@ pub async fn rsi(
|
|||
prev_avg_ups = current_avg_ups;
|
||||
prev_avg_downs = current_avg_downs;
|
||||
|
||||
let rs = current_avg_ups.unwrap()
|
||||
/ (current_avg_downs.unwrap() + 0.00000001); // 0.00000001 is used to avoid division by 0
|
||||
let rs =
|
||||
current_avg_ups.unwrap() / (current_avg_downs.unwrap() + 0.00000001); // 0.00000001 is used to avoid division by 0
|
||||
|
||||
let rsi = 100.0 - (100.0 / (1.0 + rs));
|
||||
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
#![allow(unused)]
|
||||
#![allow(warnings)]
|
||||
|
||||
use super::HashMap;
|
||||
use crate::database_control::*;
|
||||
use crate::value_estimation_team::datapoints::price_data::RealtimePriceData;
|
||||
use crate::strategy_team::FilteredDataValue;
|
||||
use crate::value_estimation_team::datapoints::price_data::RealtimePriceData;
|
||||
use futures::future::try_join_all;
|
||||
use serde::Deserialize;
|
||||
use sqlx::FromRow;
|
||||
use std::sync::Arc;
|
||||
use tokio::{fs::*, io::AsyncWriteExt, sync::Mutex, time::*};
|
||||
use super::HashMap;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SmaData {
|
||||
|
|
|
|||
|
|
@ -2,16 +2,16 @@
|
|||
#![allow(warnings)]
|
||||
|
||||
use crate::database_control::*;
|
||||
use crate::value_estimation_team::indicators::rsi::{RsiData, rsi};
|
||||
use crate::value_estimation_team::datapoints::price_data::RealtimePriceData;
|
||||
use crate::strategy_team::FilteredDataValue;
|
||||
use crate::value_estimation_team::datapoints::price_data::RealtimePriceData;
|
||||
use crate::value_estimation_team::indicators::rsi::{rsi, RsiData};
|
||||
use futures::{future::try_join_all, lock::Mutex};
|
||||
use serde::Deserialize;
|
||||
use sqlx::FromRow;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::f64::NAN;
|
||||
use std::sync::Arc;
|
||||
use tokio::{fs::*, io::AsyncWriteExt, time::*};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct StochRsiData {
|
||||
|
|
|
|||
|
|
@ -1,21 +1,27 @@
|
|||
use super::{FilteredDataValue, HashMap};
|
||||
use crate::value_estimation_team::datapoints::price_data::RealtimePriceData;
|
||||
use super::{HashMap, FilteredDataValue};
|
||||
use std::sync::Arc;
|
||||
use futures::future::try_join_all;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
#[derive(PartialEq, Clone, Debug)]
|
||||
pub enum SuperTrendArea { UP, DOWN }
|
||||
pub enum SuperTrendArea {
|
||||
UP,
|
||||
DOWN,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Clone, Debug)]
|
||||
pub enum SuperTrendSignal { BUY, SELL }
|
||||
pub enum SuperTrendSignal {
|
||||
BUY,
|
||||
SELL,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SupertrendData {
|
||||
pub band_value: f64,
|
||||
pub signal: Option<SuperTrendSignal>, // BUY or SELL
|
||||
pub area: SuperTrendArea, // UP or DOWN
|
||||
pub close_time: i64
|
||||
pub close_time: i64,
|
||||
}
|
||||
|
||||
impl SupertrendData {
|
||||
|
|
@ -24,7 +30,7 @@ impl SupertrendData {
|
|||
band_value: 0.0,
|
||||
signal: None,
|
||||
area: SuperTrendArea::DOWN,
|
||||
close_time: 0
|
||||
close_time: 0,
|
||||
};
|
||||
|
||||
a
|
||||
|
|
@ -81,7 +87,7 @@ pub async fn supertrend(
|
|||
let mut task_vec = Vec::new();
|
||||
for (symbol, filtered_data) in filtered_symbols {
|
||||
if let Some(rt_price_vec) = input_rt_data.get(symbol) {
|
||||
if atr_period < rt_price_vec.len()-1 {
|
||||
if atr_period < rt_price_vec.len() - 1 {
|
||||
let symbol_c = symbol.clone();
|
||||
let supertrend_data_wrapper_arc_c = Arc::clone(&supertrend_data_wrapper_arc);
|
||||
let rt_price_vec_c = rt_price_vec.clone();
|
||||
|
|
@ -130,7 +136,8 @@ pub async fn supertrend(
|
|||
|
||||
let mut temp_prev_atr_value = first_value;
|
||||
for element in &true_range_vec[atr_period..] {
|
||||
atr_data.atr_value = ((temp_prev_atr_value * ((atr_period - 1) as f64))
|
||||
atr_data.atr_value = ((temp_prev_atr_value
|
||||
* ((atr_period - 1) as f64))
|
||||
+ element.tr_value)
|
||||
/ atr_period as f64;
|
||||
atr_data.close_time = element.close_time;
|
||||
|
|
@ -245,7 +252,8 @@ pub async fn supertrend(
|
|||
prev_final_lowerband = final_lowerband;
|
||||
prev_trend = trend;
|
||||
}
|
||||
let mut supertrend_data_wrapper_lock = supertrend_data_wrapper_arc_c.lock().await;
|
||||
let mut supertrend_data_wrapper_lock =
|
||||
supertrend_data_wrapper_arc_c.lock().await;
|
||||
supertrend_data_wrapper_lock.insert(symbol_c, supertrend_vec.clone());
|
||||
}));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
#![allow(unused)]
|
||||
#![allow(warnings)]
|
||||
use super::ema::{ema, EmaData};
|
||||
use super::FilteredDataValue;
|
||||
use crate::database_control::*;
|
||||
use crate::value_estimation_team::datapoints::price_data::RealtimePriceData;
|
||||
use futures::future::try_join_all;
|
||||
use serde::Deserialize;
|
||||
use sqlx::FromRow;
|
||||
use std::collections::HashMap;
|
||||
use std::{iter::zip, sync::Arc};
|
||||
use tokio::{fs::*, io::AsyncWriteExt, sync::Mutex, time::*};
|
||||
use super::FilteredDataValue;
|
||||
use std::collections::HashMap;
|
||||
use super::ema::{ema, EmaData};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct TemaData {
|
||||
|
|
@ -81,7 +81,6 @@ pub async fn tema(
|
|||
ema_data_wrapper_lock.insert(symbol_c, ema_data_vec.clone());
|
||||
}
|
||||
}));
|
||||
|
||||
}
|
||||
try_join_all(task_vec).await?;
|
||||
let e2 = ema_data_wrapper_arc.lock().await.to_owned();
|
||||
|
|
@ -126,7 +125,6 @@ pub async fn tema(
|
|||
ema_data_wrapper_lock.insert(symbol_c, ema_data_vec.clone());
|
||||
}
|
||||
}));
|
||||
|
||||
}
|
||||
try_join_all(task_vec).await?;
|
||||
let e3 = ema_data_wrapper_arc.lock().await.to_owned();
|
||||
|
|
@ -136,25 +134,29 @@ pub async fn tema(
|
|||
let mut task_vec = Vec::new();
|
||||
for (symbol, e3_vec) in e3 {
|
||||
if let (Some(e1_vec), Some(e2_vec)) = (e1.get(&symbol), e2.get(&symbol)) {
|
||||
let tema_data_wrapper_arc_c: Arc<Mutex<HashMap<String, Vec<TemaData>>>> = Arc::clone(&tema_data_wrapper_arc);
|
||||
let tema_data_wrapper_arc_c: Arc<Mutex<HashMap<String, Vec<TemaData>>>> =
|
||||
Arc::clone(&tema_data_wrapper_arc);
|
||||
let symbol_c = symbol.clone();
|
||||
let e1_vec_c = e1_vec.clone();
|
||||
let e2_vec_c = e2_vec.clone();
|
||||
task_vec.push(tokio::spawn(async move {
|
||||
if e3_vec.last().unwrap().close_time == e1_vec_c.last().unwrap().close_time &&
|
||||
e3_vec.last().unwrap().close_time == e2_vec_c.last().unwrap().close_time &&
|
||||
e3_vec.len() < e1_vec_c.len() &&
|
||||
e3_vec.len() < e2_vec_c.len() &&
|
||||
e2_vec_c.len() < e1_vec_c.len() {
|
||||
if e3_vec.last().unwrap().close_time == e1_vec_c.last().unwrap().close_time
|
||||
&& e3_vec.last().unwrap().close_time == e2_vec_c.last().unwrap().close_time
|
||||
&& e3_vec.len() < e1_vec_c.len()
|
||||
&& e3_vec.len() < e2_vec_c.len()
|
||||
&& e2_vec_c.len() < e1_vec_c.len()
|
||||
{
|
||||
let mut tema_data_vec: Vec<TemaData> = Vec::new();
|
||||
let e1_vec_part = e1_vec_c.get(e1_vec_c.len()-e3_vec.len()..).unwrap();
|
||||
let e2_vec_part = e2_vec_c.get(e2_vec_c.len()-e3_vec.len()..).unwrap();
|
||||
let e1_vec_part = e1_vec_c.get(e1_vec_c.len() - e3_vec.len()..).unwrap();
|
||||
let e2_vec_part = e2_vec_c.get(e2_vec_c.len() - e3_vec.len()..).unwrap();
|
||||
let zipped_e1_e2 = e1_vec_part.iter().zip(e2_vec_part.iter());
|
||||
let zipped_e1_e2_e3 = zipped_e1_e2.zip(e3_vec.iter());
|
||||
for element in zipped_e1_e2_e3 {
|
||||
let mut tema_data = TemaData::new();
|
||||
tema_data.close_time = element.0.0.close_time;
|
||||
tema_data.tema_value = (3.0 * (element.0.0.ema_value - element.0.1.ema_value)) + element.1.ema_value;
|
||||
tema_data.close_time = element.0 .0.close_time;
|
||||
tema_data.tema_value = (3.0
|
||||
* (element.0 .0.ema_value - element.0 .1.ema_value))
|
||||
+ element.1.ema_value;
|
||||
tema_data_vec.push(tema_data);
|
||||
}
|
||||
let mut dema_data_wrapper_lock = tema_data_wrapper_arc_c.lock().await;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user