use std::pin::Pin;
use async_trait::async_trait;
use futures::Stream;
use qs_service::TransportFailure;
use thiserror::Error;
use crate::{
AddProfileRequest, AddProfileResponse, BacktestEvent, BacktestStatusResponse,
CancelBacktestResponse, DeleteResultArtifactRequest, DeleteResultArtifactResponse,
GetBacktestResultResponse, GetResultArtifactChunkRequest, GetResultArtifactChunkResponse,
GetSearchResultResponse, ListProfilesResponse, ListSymbolsRequest, ListSymbolsResponse,
PingResponse, ReloadProfilesResponse, RemoveProfileRequest, RemoveProfileResponse,
RunBacktestMultiRequest, RunBacktestMultiResponse, RunBacktestRequest, RunBacktestResponse,
RunConfiguredStrategyRequest, RunPortfolioRequest, SubmitBacktestRequest,
SubmitBacktestResponse, SubmitConfiguredStrategyRequest, SubmitPortfolioRequest,
SubmitSearchRequest,
};
pub type BacktestEventStream =
Pin<Box<dyn Stream<Item = Result<BacktestEvent, BacktestClientError>> + Send>>;
#[async_trait]
pub trait BacktestClient: Send + Sync {
async fn ping(&self) -> Result<PingResponse, BacktestClientError>;
async fn submit(
&self,
request: SubmitBacktestRequest,
) -> Result<SubmitBacktestResponse, BacktestClientError>;
async fn status(&self, job_id: &str) -> Result<BacktestStatusResponse, BacktestClientError>;
async fn watch(&self, job_id: &str) -> Result<BacktestEventStream, BacktestClientError>;
async fn result(&self, job_id: &str) -> Result<GetBacktestResultResponse, BacktestClientError>;
async fn get_result_artifact_chunk(
&self,
request: GetResultArtifactChunkRequest,
) -> Result<GetResultArtifactChunkResponse, BacktestClientError>;
async fn delete_result_artifact(
&self,
request: DeleteResultArtifactRequest,
) -> Result<DeleteResultArtifactResponse, BacktestClientError>;
async fn cancel(&self, job_id: &str) -> Result<CancelBacktestResponse, BacktestClientError>;
}
#[async_trait]
pub trait BacktestSyncClient: Send + Sync {
async fn run_backtest(
&self,
request: RunBacktestRequest,
) -> Result<RunBacktestResponse, BacktestClientError>;
async fn run_backtest_multi(
&self,
request: RunBacktestMultiRequest,
) -> Result<RunBacktestMultiResponse, BacktestClientError>;
}
#[async_trait]
pub trait BacktestDiscoveryClient: Send + Sync {
async fn list_profiles(&self) -> Result<ListProfilesResponse, BacktestClientError>;
async fn list_symbols(
&self,
request: ListSymbolsRequest,
) -> Result<ListSymbolsResponse, BacktestClientError>;
}
#[async_trait]
pub trait BacktestStrategyClient: Send + Sync {
async fn run_configured_strategy(
&self,
request: RunConfiguredStrategyRequest,
) -> Result<RunBacktestResponse, BacktestClientError>;
async fn submit_configured_strategy(
&self,
request: SubmitConfiguredStrategyRequest,
) -> Result<SubmitBacktestResponse, BacktestClientError>;
async fn run_portfolio(
&self,
request: RunPortfolioRequest,
) -> Result<RunBacktestResponse, BacktestClientError>;
async fn submit_portfolio(
&self,
request: SubmitPortfolioRequest,
) -> Result<SubmitBacktestResponse, BacktestClientError>;
async fn submit_search(
&self,
request: SubmitSearchRequest,
) -> Result<SubmitBacktestResponse, BacktestClientError>;
async fn search_result(
&self,
job_id: &str,
) -> Result<GetSearchResultResponse, BacktestClientError>;
}
#[async_trait]
pub trait BacktestAdminClient: Send + Sync {
async fn add_profile(
&self,
request: AddProfileRequest,
) -> Result<AddProfileResponse, BacktestClientError>;
async fn remove_profile(
&self,
request: RemoveProfileRequest,
) -> Result<RemoveProfileResponse, BacktestClientError>;
async fn reload_profiles(&self) -> Result<ReloadProfilesResponse, BacktestClientError>;
}
#[derive(Debug, Clone, Error)]
pub enum BacktestClientError {
#[error("backtest service rejected the request: {0}")]
Service(String),
#[error(transparent)]
Transport(#[from] TransportFailure),
#[error(transparent)]
Protocol(#[from] BacktestServiceProtocolError),
}
#[derive(Debug, Clone, Error)]
#[error("backtest service protocol failure: {detail}")]
pub struct BacktestServiceProtocolError {
pub detail: String,
}