#![warn(clippy::all, clippy::pedantic, clippy::nursery)] #![allow(clippy::missing_docs_in_private_items)] #![feature(hash_extract_if)] mod config; mod init; mod routes; mod threads; use config::{ Config, ALPACA_API_BASE, ALPACA_MODE, ALPACA_SOURCE, CLICKHOUSE_BATCH_BARS_SIZE, CLICKHOUSE_BATCH_NEWS_SIZE, CLICKHOUSE_MAX_CONNECTIONS, }; use dotenv::dotenv; use log::info; use log4rs::config::Deserializers; use qrust::{create_send_await, database}; use tokio::{join, spawn, sync::mpsc, try_join}; #[tokio::main] async fn main() { dotenv().ok(); log4rs::init_file("log4rs.yaml", Deserializers::default()).unwrap(); let config = Config::arc_from_env(); let _ = *ALPACA_MODE; let _ = *ALPACA_API_BASE; let _ = *ALPACA_SOURCE; let _ = *CLICKHOUSE_BATCH_BARS_SIZE; let _ = *CLICKHOUSE_BATCH_NEWS_SIZE; let _ = *CLICKHOUSE_MAX_CONNECTIONS; info!("Marking all assets as stale."); let assets = database::assets::select( &config.clickhouse_client, &config.clickhouse_concurrency_limiter, ) .await .unwrap() .into_iter() .map(|asset| (asset.symbol, asset.class)) .collect::>(); let symbols = assets.iter().map(|(symbol, _)| symbol).collect::>(); try_join!( database::backfills_bars::set_fresh_where_symbols( &config.clickhouse_client, &config.clickhouse_concurrency_limiter, false, &symbols ), database::backfills_news::set_fresh_where_symbols( &config.clickhouse_client, &config.clickhouse_concurrency_limiter, false, &symbols ) ) .unwrap(); info!("Cleaning up database."); database::cleanup_all( &config.clickhouse_client, &config.clickhouse_concurrency_limiter, ) .await .unwrap(); info!("Optimizing database."); database::optimize_all( &config.clickhouse_client, &config.clickhouse_concurrency_limiter, ) .await .unwrap(); info!("Rehydrating account data."); init::check_account(&config).await; join!( init::rehydrate_orders(&config), init::rehydrate_positions(&config) ); info!("Starting threads."); spawn(threads::trading::run(config.clone())); let (data_sender, data_receiver) = mpsc::channel::(100); let (clock_sender, clock_receiver) = mpsc::channel::(1); spawn(threads::data::run( config.clone(), data_receiver, clock_receiver, )); spawn(threads::clock::run(config.clone(), clock_sender)); create_send_await!( data_sender, threads::data::Message::new, threads::data::Action::Enable, assets ); routes::run(config, data_sender).await; }