Add position types
Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
This commit is contained in:
@@ -16,6 +16,7 @@ use tokio::sync::Mutex;
|
||||
|
||||
pub const ALPACA_ASSET_API_URL: &str = "https://api.alpaca.markets/v2/assets";
|
||||
pub const ALPACA_ORDER_API_URL: &str = "https://api.alpaca.markets/v2/orders";
|
||||
pub const ALPACA_POSITION_API_URL: &str = "https://api.alpaca.markets/v2/positions";
|
||||
pub const ALPACA_CLOCK_API_URL: &str = "https://api.alpaca.markets/v2/clock";
|
||||
|
||||
pub const ALPACA_STOCK_DATA_URL: &str = "https://data.alpaca.markets/v2/stocks/bars";
|
||||
|
@@ -3,3 +3,4 @@ pub mod backfills;
|
||||
pub mod bars;
|
||||
pub mod news;
|
||||
pub mod orders;
|
||||
pub mod positions;
|
||||
|
0
src/database/positions.rs
Normal file
0
src/database/positions.rs
Normal file
@@ -3,3 +3,4 @@ pub mod bar;
|
||||
pub mod clock;
|
||||
pub mod news;
|
||||
pub mod order;
|
||||
pub mod position;
|
||||
|
95
src/types/alpaca/api/incoming/position.rs
Normal file
95
src/types/alpaca/api/incoming/position.rs
Normal file
@@ -0,0 +1,95 @@
|
||||
use crate::{
|
||||
config::{Config, ALPACA_POSITION_API_URL},
|
||||
types::{
|
||||
self,
|
||||
alpaca::shared::{
|
||||
self,
|
||||
asset::{Class, Exchange},
|
||||
},
|
||||
},
|
||||
};
|
||||
use backoff::{future::retry_notify, ExponentialBackoff};
|
||||
use log::warn;
|
||||
use serde::Deserialize;
|
||||
use std::{sync::Arc, time::Duration};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum Side {
|
||||
Long,
|
||||
Short,
|
||||
}
|
||||
|
||||
impl From<Side> for shared::order::Side {
|
||||
fn from(side: Side) -> Self {
|
||||
match side {
|
||||
Side::Long => Self::Buy,
|
||||
Side::Short => Self::Sell,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Position {
|
||||
pub asset_id: Uuid,
|
||||
pub symbol: String,
|
||||
pub exchange: Exchange,
|
||||
pub asset_class: Class,
|
||||
pub avg_entry_price: f64,
|
||||
pub qty: f64,
|
||||
pub qty_available: f64,
|
||||
pub side: Side,
|
||||
pub market_value: f64,
|
||||
pub cost_basis: f64,
|
||||
pub unrealized_pl: f64,
|
||||
pub unrealized_plpc: f64,
|
||||
pub unrealized_intraday_pl: f64,
|
||||
pub unrealized_intraday_plpc: f64,
|
||||
pub current_price: f64,
|
||||
pub lastday_price: f64,
|
||||
pub change_today: f64,
|
||||
pub asset_marginable: bool,
|
||||
}
|
||||
|
||||
impl From<Position> for types::Position {
|
||||
fn from(position: Position) -> Self {
|
||||
Self {
|
||||
symbol: position.symbol,
|
||||
qty: position.qty_available,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get(
|
||||
config: &Arc<Config>,
|
||||
backoff: Option<ExponentialBackoff>,
|
||||
) -> Result<Vec<Position>, reqwest::Error> {
|
||||
retry_notify(
|
||||
backoff.unwrap_or_default(),
|
||||
|| async {
|
||||
config.alpaca_rate_limit.until_ready().await;
|
||||
config
|
||||
.alpaca_client
|
||||
.get(ALPACA_POSITION_API_URL)
|
||||
.send()
|
||||
.await?
|
||||
.error_for_status()
|
||||
.map_err(|e| match e.status() {
|
||||
Some(reqwest::StatusCode::FORBIDDEN) => backoff::Error::Permanent(e),
|
||||
_ => e.into(),
|
||||
})?
|
||||
.json::<Vec<Position>>()
|
||||
.await
|
||||
.map_err(backoff::Error::Permanent)
|
||||
},
|
||||
|e, duration: Duration| {
|
||||
warn!(
|
||||
"Failed to get positions, will retry in {} seconds: {}",
|
||||
duration.as_secs(),
|
||||
e
|
||||
);
|
||||
},
|
||||
)
|
||||
.await
|
||||
}
|
@@ -4,9 +4,11 @@ pub mod backfill;
|
||||
pub mod bar;
|
||||
pub mod news;
|
||||
pub mod order;
|
||||
pub mod position;
|
||||
|
||||
pub use asset::{Asset, Class, Exchange};
|
||||
pub use backfill::Backfill;
|
||||
pub use bar::Bar;
|
||||
pub use news::News;
|
||||
pub use order::Order;
|
||||
pub use position::Position;
|
||||
|
8
src/types/position.rs
Normal file
8
src/types/position.rs
Normal file
@@ -0,0 +1,8 @@
|
||||
use clickhouse::Row;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, Row)]
|
||||
pub struct Position {
|
||||
pub symbol: String,
|
||||
pub qty: f64,
|
||||
}
|
@@ -118,3 +118,9 @@ ENGINE = ReplacingMergeTree()
|
||||
PARTITION BY toYYYYMM(time_submitted)
|
||||
PRIMARY KEY id;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS qrust.positions (
|
||||
symbol LowCardinality(String),
|
||||
qty Float64
|
||||
)
|
||||
ENGINE = ReplacingMergeTree()
|
||||
PRIMARY KEY symbol;
|
||||
|
Reference in New Issue
Block a user