Skip to content

Commit

Permalink
Merge branch 'main' into dependabot/cargo/base64-0.22
Browse files Browse the repository at this point in the history
  • Loading branch information
nguyenthdat authored Apr 18, 2024
2 parents 6aa6cf2 + 9e7e603 commit 4844fed
Show file tree
Hide file tree
Showing 26 changed files with 1,144 additions and 465 deletions.
5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@ path = "src/lib.rs"
default = ["user"]
user = ["dep:google-authenticator"]
protobuf = ["dep:prost"]
sqlx = []

[dependencies]
async-trait = "0.1" # Remove this when Rust 1.75 async trait is stable
tokio = { version = "1", default-features = false }
tokio = { version = "1", default-features = false, features = ["rt", "macros"] }
serde = { version = "1", features = ["derive"] }
serde_json = { version = "1" }
reqwest = { version = "0.11", features = ["rustls-tls", "json", "cookies"] }
reqwest = { version = "0.12", features = ["rustls-tls", "json", "cookies"] }
lazy_static = "1.4"
url = "2"
urlencoding = "2"
Expand Down
18 changes: 10 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,28 @@
This is a data source library for algorithmic trading written in Rust inspired by [TradingView-API](https://github.com/Mathieu2301/TradingView-API). It is currently in **alpha** stage and not ready for production use.

## Features

- [x] Async support
- [x] Multi-Threading for working with large amounts of data
- [ ] Shared session between threads (Not overwhelming TradingView servers)
- [ ] TradingView Premium features
- [ ] Realtime data
- [x] Shared session between threads (Not overwhelming TradingView servers)
- [x] TradingView Premium features
- [x] Realtime data
- [ ] Fundamental data
- [ ] Technical data
- [ ] Get drawings you made on your chart
- [x] Get drawings you made on your chart
- [ ] Works with invite-only indicators
- [ ] Unlimited simultaneous indicators
- [x] Unlimited simultaneous indicators
- [ ] Get TradingView's technical analysis
- [ ] Replay mode
- [x] Replay mode
- [ ] Get values from a specific date range
- [ ] Interact with public chats
- [ ] Get Screener top values
- [ ] Get Calendar
- [ ] Get News
- [ ] Convert to Vectorized Data

## Use cases

- [Fenrir Data](https://github.com/bitbytelabio/fenrir-data) - A data engine that applies an event-driven architecture with RedPanda (Kafka), SurrealDB, DragonflyDB (Redis).
- [Fenrir Data](https://github.com/bitbytelabio/fenrir-data) - A data engine that applies an event-driven architecture with RedPanda (Kafka), PostgreSQL with TimeScaleDB, PGVector, DragonflyDB (Redis).

## Getting Started

Expand Down
38 changes: 23 additions & 15 deletions examples/all.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,35 @@ use dotenv::dotenv;
use std::env;

use tradingview::{
chart,
callback::Callbacks,
chart::ChartOptions,
data_loader::DataLoader,
models::{pine_indicator::ScriptType, Interval},
quote,
socket::{DataServer, SocketSession},
pine_indicator::ScriptType,
socket::DataServer,
websocket::{WebSocket, WebSocketClient},
Interval, QuoteValue,
};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
dotenv().ok();
tracing_subscriber::fmt::init();
let auth_token = env::var("TV_AUTH_TOKEN").unwrap();
let auth_token = env::var("TV_AUTH_TOKEN").expect("TV_AUTH_TOKEN is not set");

let socket = SocketSession::new(DataServer::ProData, auth_token).await?;
let quote_callback = |data: QuoteValue| async move {
println!("{:#?}", data);
};

let publisher: DataLoader = DataLoader::default();
let callbacks = Callbacks::default().on_quote_data(quote_callback);

let mut chart = chart::session::WebSocket::new(publisher.clone(), socket.clone());
let mut quote = quote::session::WebSocket::new(publisher.clone(), socket.clone());
let client = WebSocketClient::default().set_callbacks(callbacks);

let mut websocket = WebSocket::new()
.server(DataServer::ProData)
.auth_token(&auth_token)
.client(client)
.build()
.await
.unwrap();

let opts = ChartOptions::new("BINANCE:BTCUSDT", Interval::OneMinute).bar_count(100);
let opts2 = ChartOptions::new("BINANCE:BTCUSDT", Interval::Daily)
Expand All @@ -35,16 +44,16 @@ async fn main() -> anyhow::Result<()> {
.replay_mode(true)
.replay_from(1698624060);

chart
websocket
.set_market(opts)
.await?
.set_market(opts2)
.await?
.set_market(opts3)
.await?;

quote
.create_session()
websocket
.create_quote_session()
.await?
.set_fields()
.await?
Expand All @@ -57,8 +66,7 @@ async fn main() -> anyhow::Result<()> {
])
.await?;

tokio::spawn(async move { chart.clone().subscribe().await });
tokio::spawn(async move { quote.clone().subscribe().await });
tokio::spawn(async move { websocket.subscribe().await });

loop {}
}
5 changes: 3 additions & 2 deletions examples/misc.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use tracing::info;
use tradingview::models::pine_indicator::*;
use tradingview::pine_indicator::*;

#[tokio::main]
async fn main() {
Expand All @@ -13,7 +13,8 @@ async fn main() {
// info!("{:#?}", info);

let pine = PineIndicator::build()
.fetch("STD;Fund_total_revenue_fq", "62.0", ScriptType::Script).await
.fetch("STD;Fund_total_revenue_fq", "62.0", ScriptType::Script)
.await
.unwrap();

let test = pine.to_study_inputs().unwrap();
Expand Down
2 changes: 1 addition & 1 deletion examples/user.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#![cfg(feature = "user")]
use tradingview::user::UserCookies;
use tradingview::UserCookies;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
Expand Down
24 changes: 9 additions & 15 deletions src/callback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,20 +52,17 @@ impl Default for Callbacks<'_> {

impl<'a> Callbacks<'a> {
pub fn on_chart_data<Fut>(
&mut self,
mut self,
f: impl Fn((ChartOptions, Vec<DataPoint>)) -> Fut + Send + Sync + 'a,
) -> &mut Self
) -> Self
where
Fut: Future<Output = ()> + Send + 'a,
{
self.on_chart_data = Arc::new(Box::new(move |data| Box::pin(f(data))));
self
}

pub fn on_quote_data<Fut>(
&mut self,
f: impl Fn(QuoteValue) -> Fut + Send + Sync + 'a,
) -> &mut Self
pub fn on_quote_data<Fut>(mut self, f: impl Fn(QuoteValue) -> Fut + Send + Sync + 'a) -> Self
where
Fut: Future<Output = ()> + Send + 'a,
{
Expand All @@ -74,28 +71,25 @@ impl<'a> Callbacks<'a> {
}

pub fn on_study_data<Fut>(
&mut self,
mut self,
f: impl Fn((StudyOptions, StudyResponseData)) -> Fut + Send + Sync + 'a,
) -> &mut Self
) -> Self
where
Fut: Future<Output = ()> + Send + 'a,
{
self.on_study_data = Arc::new(Box::new(move |data| Box::pin(f(data))));
self
}

pub fn on_error<Fut>(&mut self, f: impl Fn(Error) -> Fut + Send + Sync + 'a) -> &mut Self
pub fn on_error<Fut>(mut self, f: impl Fn(Error) -> Fut + Send + Sync + 'a) -> Self
where
Fut: Future<Output = ()> + Send + 'a,
{
self.on_error = Arc::new(Box::new(move |data| Box::pin(f(data))));
self
}

pub fn on_symbol_info<Fut>(
&mut self,
f: impl Fn(SymbolInfo) -> Fut + Send + Sync + 'a,
) -> &mut Self
pub fn on_symbol_info<Fut>(mut self, f: impl Fn(SymbolInfo) -> Fut + Send + Sync + 'a) -> Self
where
Fut: Future<Output = ()> + Send + 'a,
{
Expand All @@ -104,9 +98,9 @@ impl<'a> Callbacks<'a> {
}

pub fn on_other_event<Fut>(
&mut self,
mut self,
f: impl Fn((TradingViewDataEvent, Vec<Value>)) -> Fut + Send + Sync + 'a,
) -> &mut Self
) -> Self
where
Fut: Future<Output = ()> + Send + 'a,
{
Expand Down
21 changes: 10 additions & 11 deletions src/chart/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use crate::models::{pine_indicator::ScriptType, Interval, MarketAdjustment, Sess

pub mod models;
pub(crate) mod options;
pub mod session;
pub mod study;
pub(crate) mod utils;

Expand All @@ -13,17 +12,17 @@ pub struct ChartOptions {
// Required
pub symbol: String,
pub interval: Interval,
bar_count: u64,
pub(crate) bar_count: u64,

range: Option<String>,
from: Option<u64>,
to: Option<u64>,
replay_mode: bool,
replay_from: i64,
replay_session: Option<String>,
adjustment: Option<MarketAdjustment>,
currency: Option<Currency>,
session_type: Option<SessionType>,
pub(crate) range: Option<String>,
pub(crate) from: Option<u64>,
pub(crate) to: Option<u64>,
pub(crate) replay_mode: bool,
pub(crate) replay_from: i64,
pub(crate) replay_session: Option<String>,
pub(crate) adjustment: Option<MarketAdjustment>,
pub(crate) currency: Option<Currency>,
pub(crate) session_type: Option<SessionType>,
pub study_config: Option<StudyOptions>,
}

Expand Down
2 changes: 1 addition & 1 deletion src/chart/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ pub struct GraphicDataResponse {

#[cfg_attr(not(feature = "protobuf"), derive(Debug, Default))]
#[cfg_attr(feature = "protobuf", derive(prost::Message))]
#[derive(Clone, Deserialize)]
#[derive(Clone, Deserialize, Serialize, PartialEq)]
pub struct DataPoint {
#[cfg_attr(feature = "protobuf", prost(int64, tag = "1"))]
#[serde(rename(deserialize = "i"))]
Expand Down
5 changes: 4 additions & 1 deletion src/chart/utils.rs
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@

// TODO: Implement this module
pub fn _graphics_parser() {
unimplemented!()
}
1 change: 1 addition & 0 deletions src/client/fin_calendar.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Loading

0 comments on commit 4844fed

Please sign in to comment.