Skip to content

Commit

Permalink
stash
Browse files Browse the repository at this point in the history
  • Loading branch information
ryqdev committed May 30, 2024
1 parent 216fd8b commit de903e2
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 67 deletions.
8 changes: 5 additions & 3 deletions src/cmds/backtest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ use crate::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;

pub struct BackTestCommand;
Expand Down Expand Up @@ -39,11 +41,11 @@ impl Command for BackTestCommand {

async fn backtest(symbol: &str) -> Result<()> {
let mut green = Green::new()
// TODO: how to identify different modes
.add_data_feed(symbol)
.set_mode(GreenModeType::Backtest)
.add_broker(100_000.0)
.add_data_feed(symbol)
.add_strategy(SimpleStrategy{})
.init();
.build();

green.run();
green.plot();
Expand Down
15 changes: 0 additions & 15 deletions src/cmds/paper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,21 +50,6 @@ impl BreakoutChannel {

async fn paper_trading(){
log::info!("Paper trading...");
// let cash = 10_000.0;
// let mut green = Green::new()
// .add_data_feed(symbol)
// // .add_broker(100_000.0)
// .add_strategy(SimpleStrategy {
// name: "simple".to_string(),
// cash: Vec::from([cash]),
// position: Vec::from([0.0]),
// net_assets: Vec::from([cash]),
// order: vec![],
// })
// .build();
//
// green.run();
// green.plot();

let client = Client::connect("127.0.0.1:7497", 100).unwrap();

Expand Down
136 changes: 98 additions & 38 deletions src/green/green.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
use std::collections::hash_set::SymmetricDifference;
use std::collections::VecDeque;
use std::default::Default;
use std::fs::File;
use clickhouse::serde::time::datetime64::millis::option::deserialize;
use egui::style::default_text_styles;
use ibapi::{Client, Error};
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::{
Expand All @@ -26,6 +31,14 @@ pub enum Action {
Sell,
}

#[derive(Debug, Default, Copy, Clone)]
pub enum GreenModeType {
#[default]
Backtest,
Paper,
Live
}


#[derive(Default, Clone, Debug)]
pub(crate) struct Order {
Expand All @@ -36,17 +49,22 @@ pub(crate) struct Order {

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


#[derive(Default)]
pub struct GreenBuilder {
data: Vec<Vec<f64>>,
data: Box<dyn Iterator<Item = Bar>>,
strategy: SimpleStrategy,
broker: BackTestBroker
broker: BackTestBroker,
mode: GreenModeType,
}

impl Green {
Expand All @@ -58,13 +76,13 @@ impl Green {
pub fn run(&mut self) {
log::info!("Running {:?}...", self.strategy);

//! .iter() : borrows the ownership
//! .into_iter(): transfers the ownership
for bar in self.data.iter() {
let order = self.strategy.next(bar);
// .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 close_price = bar.last().unwrap();
let close_price = &bar.close;
match order.action {
Action::Buy => {
log::info!("Buy: {:?}", order);
Expand Down Expand Up @@ -105,36 +123,39 @@ impl Green {
}
}

type HistoricalData = (String, Vec<f64>);

impl GreenBuilder{
impl GreenBuilder {
pub fn add_data_feed(&mut self, symbol: &str) -> &mut GreenBuilder{
let file = File::open(format!("data/{symbol}.csv")).unwrap();

let mut reader = csv::ReaderBuilder::new()
.has_headers(true)
.from_reader(file);

let mut finance_data = vec![];
for result in reader.deserialize() {
let record: HistoricalData = result.unwrap();
// use record.1[2] rather than record.1.get(2)
// to get higher performance
let low = record.1[2];
let open = record.1[0];
let close = record.1[3];
let high = record.1[1];
finance_data.push(vec![open, high, low, close])
}
self.data = finance_data;
// 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::Live => todo!()
};
self
}
pub fn set_mode(&mut self, mode: GreenModeType) -> &mut GreenBuilder{
self.mode = mode;
self
}
pub fn add_broker(&mut self, cash: f64) -> &mut GreenBuilder {
self.broker = BackTestBroker{
cash: Vec::from([cash]),
position: Vec::from([0.0]),
net_assets: Vec::from([cash]),
order: vec![],
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::Paper => Client::connect("127.0.0.1:7497", 100).unwrap(),
GreenModeType::Live => todo!()
};
self
}
Expand All @@ -145,11 +166,50 @@ impl GreenBuilder{
// pub fn add_analyzer(&mut self, analyzer: Box<dyn Analyzer>) -> &GreenBuilder {
// self
// }
pub fn init(&self) -> Box<Green> {
pub fn build(&self) -> Box<Green> {
Box::new(Green{
data: self.data.clone(),
data: self.data,
strategy: self.strategy.clone(),
broker: self.broker.clone()
broker: self.broker.clone(),
mode: self.mode,
})
}
}
}

#[derive(Clone, Debug)]
pub struct Bar {
pub date: OffsetDateTime,
pub open: f64,
pub high: f64,
pub low: f64,
pub close: f64,
pub volume: f64,
pub wap: f64,
pub count: i32,
}


fn fetch_csv_data(symbol: &str) -> impl Iterator<Item = Bar> {
let csv_file = File::open(format!("data/{symbol}.csv")).unwrap();

let mut reader = csv::ReaderBuilder::new()
.has_headers(true)
.from_reader(csv_file)
.deserialize();

// TODO: correct the iterator
reader.map(|record:(String, Vec<f64>)| Bar{
date: OffsetDateTime::now_utc(),
open: record.1[0],
high: record.1[1],
low: record.1[2],
close: record.1[3],
volume: 0.0,
wap: 0.0,
count: 0,
})
}

// fn connect_and_fetch_market_data() -> impl Iterator<Item = Bar>{
//
// }
13 changes: 7 additions & 6 deletions src/green/strategy/hold.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
use crate::green::green::{Action, Order};
use crate::green::strategy::Strategy;
use crate::green::{
green::{Action, Order, Bar},
strategy::Strategy
};



#[derive(Default, Clone, Debug)]
pub struct SimpleStrategy {}

impl Strategy for SimpleStrategy {
fn next(&mut self, data: &Vec<f64>) -> Order {
let open_price = data[0];
let close_price = data[3];
if close_price > open_price {
fn next(&mut self, data: &Bar) -> Order {
if data.close > data.open {
Order{
action: Action::Buy,
size: 1.0
Expand Down
11 changes: 8 additions & 3 deletions src/green/strategy/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
pub mod hold;

use crate::green::broker::Broker;
use crate::green::green::Order;
use crate::green::{
broker::Broker,
green::{
Order,
Bar
},
};

pub trait Strategy {
fn next(&mut self, _: &Vec<f64>) -> Order;
fn next(&mut self, _: &Bar) -> Order;
}
8 changes: 6 additions & 2 deletions src/green/visualization/candle.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
use egui::{Stroke, Color32};
use egui_plot::{Plot, BoxPlot, BoxElem, BoxSpread, Legend, Line};

use crate::green::green::Order;
use crate::green::green::{
Order,
Bar
};

#[derive(Default)]
pub struct App {
pub(crate) candle_data: Vec<Vec<f64>>,
// 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>
Expand Down

0 comments on commit de903e2

Please sign in to comment.