Skip to content

Commit

Permalink
add lifetime
Browse files Browse the repository at this point in the history
  • Loading branch information
ryqdev committed May 30, 2024
1 parent 2ccd045 commit 7dc72f2
Show file tree
Hide file tree
Showing 11 changed files with 75 additions and 94 deletions.
5 changes: 0 additions & 5 deletions src/cmds/backtest.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
use super::Command;
use anyhow::{Result};
use clap::{Arg, ArgMatches, Command as ClapCommand};
use serde_derive::{Deserialize, Serialize};
use async_trait::async_trait;
use time::Date;
use crate::green::{
green::Green,
feeds, broker
};
use crate::green::broker::backtest::BackTestBroker;
use crate::green::green::DataType::Backtest;
use crate::green::green::GreenModeType;
use crate::green::strategy::hold::SimpleStrategy;

Expand Down
3 changes: 0 additions & 3 deletions src/cmds/paper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,11 @@ use crate::cmds::Command;
pub struct PaperTradingCommand;

use std::collections::VecDeque;
use std::io::Write;

use ibapi::contracts::{Contract, SecurityType};
use ibapi::market_data::realtime::{BarSize, Bar, WhatToShow};
use ibapi::orders::{order_builder, Action, OrderNotification};
use ibapi::Client;
use crate::green::green::Green;
use crate::green::strategy::hold::SimpleStrategy;

struct BreakoutChannel {
ticks: VecDeque<(f64, f64)>,
Expand Down
3 changes: 1 addition & 2 deletions src/green/broker/alpaca/alpaca.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use url::Url;
use tungstenite::{connect, Message};
use serde_json;
use tungstenite::{connect};

const BASE_URL: &str = "wss://stream.data.alpaca.markets/v2/test";

Expand Down
16 changes: 0 additions & 16 deletions src/green/broker/ibkr/backtest.rs

This file was deleted.

1 change: 1 addition & 0 deletions src/green/broker/ibkr/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mod live;
5 changes: 2 additions & 3 deletions src/green/broker/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,5 @@ pub trait Broker{
fn set_cash(&mut self, cash: f64);
}

pub mod live;
pub mod backtest;
mod alpaca;
mod alpaca;
pub(crate) mod ibkr;
2 changes: 0 additions & 2 deletions src/green/feeds/yahoo.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
use std::collections::VecDeque;
use std::fs::File;
use eframe::epaint::{Color32, Stroke};
use egui_plot::{BoxElem, BoxPlot, BoxSpread};
use time::OffsetDateTime;

pub struct YahooFinanceData{
Expand Down
117 changes: 63 additions & 54 deletions src/green/green.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,15 @@
use std::collections::hash_set::SymmetricDifference;
use std::collections::VecDeque;
use std::fs::File;
use clickhouse::serde::time::datetime64::millis::option::deserialize;
use egui::style::default_text_styles;
use ibapi::{Client, Error};
use ibapi::{Client};
use ibapi::contracts::{Contract, SecurityType};
use ibapi::market_data::realtime::{BarSize, WhatToShow};

use ibapi::orders::{order_builder, OrderNotification};
use time::OffsetDateTime;

use crate::cmds::backtest::BackTestCommand;
use crate::green::{
feeds::BaseData,
strategy::{
Strategy,
hold::{SimpleStrategy}
},
broker::Broker,
broker::backtest::BackTestBroker,
analyzer::Analyzer,
visualization
};

Expand All @@ -46,24 +36,32 @@ pub(crate) struct Order {
pub(crate) size: f64,
}

struct BackTestClient {
pub(crate) cash: Vec<f64>,
pub position: Vec<f64>,
pub(crate) net_assets: Vec<f64>,
pub order: Vec<Order>
}

struct BaseBroker{
name: String,
client: Option<Client>,
backtest_client: Option<BackTestClient>
}

#[derive(Default)]
pub struct Green {
// TODO: why to use dyn here
// TODO: why to use Box here
data: Box<dyn Iterator<Item = Bar>>,
data: dyn Iterator<Item= Bar>,
// TODO: change to BaseType
strategy: SimpleStrategy,
broker: BackTestBroker,
broker: BaseBroker,
mode: GreenModeType,
}


#[derive(Default)]
pub struct GreenBuilder {
data: Box<dyn Iterator<Item = Bar>>,
// use stack or heap, this is a question
data: dyn Iterator<Item=Bar>,
strategy: SimpleStrategy,
broker: BackTestBroker,
broker: BaseBroker,
mode: GreenModeType,
}

Expand All @@ -79,35 +77,39 @@ impl Green {
// .iter() : borrows the ownership
// .into_iter(): transfers the ownership
for bar in self.data {
let order = self.strategy.next(&bar);
let cash = self.broker.cash.last().unwrap();
let position = self.broker.position.last().unwrap();
let order = &self.strategy.next(&bar);
let mut backtest_client = match &self.broker.backtest_client {
Some(client) => &client,
None => todo!()
};
let close_price = &bar.close;

match order.action {
Action::Buy => {
log::info!("Buy: {:?}", order);
self.broker.cash.push(cash - order.size * close_price);
self.broker.position.push(position + order.size);
self.broker.net_assets.push(self.broker.cash.last().unwrap() + self.broker.position.last().unwrap() * close_price);
self.broker.order.push(order)
}
Action::Sell => {
log::info!("Sell: {:?}", order);
self.broker.cash.push(cash + order.size * close_price);
self.broker.position.push(position - order.size);
self.broker.net_assets.push(self.broker.cash.last().unwrap() + self.broker.position.last().unwrap() * close_price);
self.broker.order.push(order)
}
_ => ()
_ => todo!()
}
}
}
pub fn plot(&self) {
log::info!("Plotting {:?}...", self.strategy);
let candle_data = self.data.clone();
let cash_data = self.broker.cash.clone();
let net_asset_data = self.broker.net_assets.clone();
let order_data = self.broker.order.clone();
let candle_data = &self.data;
let cash_data = match &self.broker.backtest_client {
Some(client) => &client.cash,
None => todo!()
};
let net_asset_data = match &self.broker.backtest_client {
Some(client) => &client.net_assets,
None => todo!()
};
let order_data = match &self.broker.backtest_client {
Some(client) => &client.order,
None => todo!()
};

let native_options = eframe::NativeOptions::default();
eframe::run_native(
Expand All @@ -126,18 +128,17 @@ impl Green {

impl GreenBuilder {
pub fn set_data_feed(&mut self, symbol: &str) -> &mut GreenBuilder{
// TODO: refactor code
let contract = Contract {
symbol: "USD".to_owned(),
security_type: SecurityType::ForexPair,
currency: "JPY".to_owned(),
exchange: "IDEALPRO".to_owned(),
..Default::default()
};

self.data = match self.mode{
GreenModeType::Backtest => fetch_csv_data(symbol),
GreenModeType::Paper => self.broker.realtime_bars(&contract, BarSize::Sec5, WhatToShow::MidPoint, false).unwrap(),

GreenModeType::Paper => self.broker.realtime_bars(&Contract {
symbol: "USD".to_owned(),
security_type: SecurityType::ForexPair,
currency: "JPY".to_owned(),
exchange: "IDEALPRO".to_owned(),
..Default::default()
}, BarSize::Sec5, WhatToShow::MidPoint, false).unwrap(),

GreenModeType::Live => todo!()
};
self
Expand All @@ -148,13 +149,22 @@ impl GreenBuilder {
}
pub fn set_broker(&mut self, cash: f64) -> &mut GreenBuilder {
self.broker = match self.mode {
GreenModeType::Backtest => BackTestBroker{
cash: Vec::from([cash]),
position: Vec::from([0.0]),
net_assets: Vec::from([cash]),
order: vec![],
GreenModeType::Backtest => BaseBroker{
name: "backtest".to_owned(),
client: None,
backtest_client: Option::from(BackTestClient {
cash: Vec::from([cash]),
position: Vec::from([0.0]),
net_assets: Vec::from([cash]),
order: vec![],
})

},
GreenModeType::Paper => BaseBroker {
name: "paper".to_owned(),
client: Some(Client::connect("127.0.0.1:7497", 100).unwrap()),
backtest_client: None
},
GreenModeType::Paper => Client::connect("127.0.0.1:7497", 100).unwrap(),
GreenModeType::Live => todo!()
};
self
Expand All @@ -168,7 +178,7 @@ impl GreenBuilder {
// }
pub fn build(&self) -> Box<Green> {
Box::new(Green{
data: self.data,
data: &self.data,
strategy: self.strategy.clone(),
broker: self.broker.clone(),
mode: self.mode,
Expand Down Expand Up @@ -197,7 +207,6 @@ fn fetch_csv_data(symbol: &str) -> impl Iterator<Item = Bar> {
.from_reader(csv_file)
.deserialize();

// TODO: correct the iterator
reader.map(|record:(String, Vec<f64>)| Bar{
date: OffsetDateTime::now_utc(),
open: record.1[0],
Expand Down
1 change: 0 additions & 1 deletion src/green/strategy/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
pub mod hold;

use crate::green::{
broker::Broker,
green::{
Order,
Bar
Expand Down
15 changes: 8 additions & 7 deletions src/green/visualization/candle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ use crate::green::green::{
};

#[derive(Default)]
pub struct App {
// TODO: iterator vs vector
pub(crate) candle_data: dyn Iterator<Item=Bar>,
pub cash_data: Vec<f64>,
pub net_asset_data: Vec<f64>,
pub order_data: Vec<Order>
pub struct App<'a> {
// impl Iterator<Item = ...> can be used in scenarios where the size of object is known and fixed
// while Box<dyn Interator<Item = ...> is used otherwise
pub(crate) candle_data: &'a dyn Iterator<Item=Bar>,
pub cash_data: &'a Vec<f64>,
pub net_asset_data: &'a Vec<f64>,
pub order_data: &'a Vec<Order>
}

fn fetch_box_data(candle_data: Vec<Vec<f64>>) -> anyhow::Result<BoxPlot> {
Expand All @@ -37,7 +38,7 @@ fn fetch_box_data(candle_data: Vec<Vec<f64>>) -> anyhow::Result<BoxPlot> {
}


impl eframe::App for App {
impl eframe::App for App<'_> {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
egui::TopBottomPanel::top("Menu").show(ctx, |ui| {
ctx.request_repaint_after(std::time::Duration::from_millis(200));
Expand Down
1 change: 0 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use std::io::Write;
use colored::Colorize;

mod cmds;
mod green;
Expand Down

0 comments on commit 7dc72f2

Please sign in to comment.