File size: 2,188 Bytes
59da845
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
use serde::{Deserialize, Serialize};
use tokio::sync::mpsc;
use zeromq::{Socket, SocketRecv, SocketSend};

#[derive(Clone, Debug, Serialize)]
pub struct HistoryRequest {
    #[serde(rename = "type")]
    pub req_type: String, // "download_history"
    pub symbol: String,
    pub timeframe: String,
    pub start: String,
    pub end: String,
    pub mode: String, // "OHLC" or "TICKS"
}

#[derive(Clone, Debug, Deserialize)]
pub struct HistoryResponse {
    pub success: bool,
    pub error: Option<String>,
    pub message: Option<String>,
}

pub struct Mt5Client {
    pub rep_address: String,
}

impl Mt5Client {
    pub fn new(rep_address: &str) -> Self {
        Self {
            rep_address: rep_address.to_string(),
        }
    }

    pub async fn download_history(&self, request: HistoryRequest) -> Result<String, String> {
        let mut socket = zeromq::ReqSocket::new();
        socket.connect(&self.rep_address).await.map_err(|e| format!("Failed to connect: {}", e))?;

        let json_request = serde_json::to_string(&request).map_err(|e| format!("Serialization error: {}", e))?;
        
        socket.send(json_request.into()).await.map_err(|e| format!("Send error: {}", e))?;

        let msg = socket.recv().await.map_err(|e| format!("Receive error: {}", e))?;
        let payload = msg.get(0).ok_or("Empty response")?;
        let json_str = std::str::from_utf8(payload).map_err(|e| format!("UTF8 error: {}", e))?;
        
        let response: HistoryResponse = serde_json::from_str(json_str).map_err(|e| format!("JSON Parse error: {}", e))?;

        if response.success {
            if let Some(msg) = response.message {
                if msg.contains("||CSV_DATA||") {
                    let parts: Vec<&str> = msg.splitn(2, "||CSV_DATA||").collect();
                    if parts.len() == 2 {
                        let csv_content = parts[1].replace("|NL|", "\n");
                        return Ok(csv_content);
                    }
                }
                return Ok(msg);
            }
            Ok("Success".to_string())
        } else {
            Err(response.error.unwrap_or_else(|| "Unknown error".to_string()))
        }
    }
}