shindo_coding_utils 0.3.9

A utils crates which will be used in various micro-services
Documentation
use anyhow;
use core::str;
use thiserror::Error;

use crate::helpers::{
    format_datetime, multiply_by_10_i64, multiply_by_10_string, multiply_by_1000_f64,
    multiply_by_1000_string, parse_string_to_float, remove_special_character_from_string,
    time_to_datetime, putthrough_order_side,
};
use chrono::{DateTime, NaiveDateTime, Utc};
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct TimeRange {
    pub start: DateTime<Utc>,
    pub end: DateTime<Utc>,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct RabbitMQMessage {
    pub last_failed_ticker: Option<String>,
    pub time_range: Option<TimeRange>,
    pub table_name: Option<String>,
}

#[derive(Debug, Clone)]
pub struct Pagination {
    pub page: u64,
    pub limit: u64,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PaginationMetadata {
    pub page: u64,
    pub limit: u64,
    pub has_next_page: bool,
    pub next_page: Option<u64>,
}

#[derive(Debug, Clone, PartialEq)]
pub enum SortOrder {
    Ascending,
    Descending,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct IntradayTrading {
    pub id: i32,

    #[serde(rename = "sym")]
    pub ticker: String,

    #[serde(rename = "lastPrice", deserialize_with = "multiply_by_1000_f64")]
    pub last_price: i64,

    #[serde(rename = "openPrice", deserialize_with = "multiply_by_1000_f64")]
    pub open_price: i64,

    #[serde(rename = "hp", deserialize_with = "multiply_by_1000_f64")]
    pub high_price: i64,

    #[serde(rename = "lp", deserialize_with = "multiply_by_1000_f64")]
    pub low_price: i64,

    #[serde(deserialize_with = "multiply_by_1000_string")]
    pub change: i64,

    #[serde(rename = "lastVol", deserialize_with = "multiply_by_10_i64")]
    pub last_vol: i64,

    #[serde(rename = "totalVol", deserialize_with = "multiply_by_10_i64")]
    pub total_vol: i64,

    #[serde(rename = "sID", deserialize_with = "format_datetime")]
    pub trading_timestamp: DateTime<Utc>,

    pub side: String,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct IntradayTradingV2 {
    #[serde(rename = "lastPrice", deserialize_with = "multiply_by_1000_f64")]
    pub last_price: i64,

    #[serde(rename = "lastVol", deserialize_with = "multiply_by_10_i64")]
    pub last_vol: i64,

    #[serde(rename = "totalVol", deserialize_with = "multiply_by_10_i64")]
    pub total_vol: i64,

    #[serde(deserialize_with = "multiply_by_1000_string")]
    pub change: i64,

    #[serde(rename = "time", deserialize_with = "time_to_datetime")]
    pub trading_timestamp: DateTime<Utc>,

    #[serde(
        default = "putthrough_order_side"
    )]
    pub side: String,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct VpsIntradayTradingResponseV2 {
    #[serde(rename = "nextidx")]
    pub next_idx: i32,

    #[serde(rename = "numpage")]
    pub num_page: i32,

    pub data: Vec<IntradayTradingV2>,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct VpsForeignTradingData {
    #[serde(rename = "sym")]
    pub ticker: String,

    #[serde(rename = "fBVol", deserialize_with = "multiply_by_10_string")]
    pub buy_volume: i64,

    #[serde(rename = "fSVolume", deserialize_with = "multiply_by_10_string")]
    pub sell_volume: i64,

    #[serde(rename = "lastPrice", deserialize_with = "multiply_by_1000_f64")]
    pub last_price: i64,

    #[serde(rename = "changePc", deserialize_with = "parse_string_to_float")]
    pub change_percent: f64,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct TaggedSymbol {
    pub symbol: String,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct User {
    pub id: String,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct UserPostResponse {
    #[serde(rename = "postID")]
    pub post_id: i64,

    #[serde(rename = "replyToPostID")]
    pub reply_to_post_id: Option<i64>,

    pub user: User,
    pub date: DateTime<Utc>,

    #[serde(
        rename = "originalContent",
        deserialize_with = "remove_special_character_from_string"
    )]
    pub content: String,

    #[serde(rename = "taggedSymbols")]
    pub tagged_symbols: Vec<TaggedSymbol>,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct UserPost {
    pub post_id: i64,
    pub user: User,
    pub date: DateTime<Utc>,
    pub content: String,
    pub tagged_symbols: Vec<TaggedSymbol>,
    pub post_type: String, // user_homepage || user_comment
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PostCommentTickerSuggestion {
    pub ticker: String,
    pub user_id: String,
    pub post_id: String,
    pub post_type: String,
    pub content: String,
    pub date: NaiveDateTime,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TickerPost {
    pub post_id: i64,
    pub user_id: String,
    pub ticker: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UserPostReply {
    pub post_id: i64,
    pub user_id: String,
    pub content: String,
    pub date: NaiveDateTime,
    pub ticker: String,
}

#[derive(Debug, Error)]
pub enum ConsumerError {
    #[error("Processing failed for ticker {ticker_code}")]
    TickerFailed { ticker_code: String },
    #[error("Failed to get next ticker from data stream")]
    StreamError(#[from] anyhow::Error),
}

#[derive(Serialize, Deserialize, Debug)]
pub struct AiResponseMessage {
    pub content: String,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct AiResponseChoice {
    pub message: AiResponseMessage,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct StockAnalysisResponse {
    pub choices: Vec<AiResponseChoice>,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct StockAnalysis {
    pub analysis_date: String,
    pub symbol: String,
    pub current_state_analysis: CurrentStateAnalysis,
    pub next_day_prediction: NextDayPrediction,
    pub long_term_outlook: LongTermOutlook,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct CurrentStateAnalysis {
    pub last_date_in_dataset: String,
    pub recent_indicators: RecentIndicators,
    pub recent_candlestick: String,
    pub recent_volume: String,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct RecentIndicators {
    pub sma20: f64,
    pub sma50: f64,
    pub rsi14: f64,
    pub macd: f64,
    pub macd_signal: f64,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct TrendAndPatternContext {
    pub dominant_trend: String,
    pub trend_justification: String,
    pub active_pattern: String,
    pub key_levels: KeyLevels,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct KeyLevels {
    pub immediate_support: u32,
    pub immediate_resistance: u32,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct NextDayPrediction {
    pub predicted_date: String,
    pub conclusion: String,
    pub predicted_price_high: u32,
    pub predicted_price_low: u32,
    pub predicted_volume: u64,
    pub confidence: String,
    pub justification: String,
    pub invalidating_signal: String,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct LongTermOutlook {
    pub timeframe: String,
    pub expected_behavior: String,
    pub predicted_price_range: PredictedPriceRange,
    pub justification: String,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct PredictedPriceRange {
    pub min: u32,
    pub max: u32,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct AbnormalStockTrade {
    pub created_at: DateTime<Utc>,
    pub ticker: String,
    pub analysis_type: String,
    pub last_vol: i64,
    pub last_price: i64,
    pub price_change: i64,
    pub total_vol: i64,
    pub score: i64,
    pub action_time: DateTime<Utc>,
    pub notification_sent: bool,
    pub reason: String,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct BreakoutAnalysis {
    pub date: DateTime<Utc>,
    pub is_breakout: bool,
    pub score: u8,
    pub analysis_details: serde_json::Value,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Experiment {
    pub json_string: String,
    pub ticker: String,
    pub reviewed: bool,
    pub created_at: DateTime<Utc>,
}