rs_backtester/
strategies.rs1use csv::Writer;
2use crate::datas::Data;
3use crate::orders::Order;
4use crate::orders::Order::{BUY,SHORTSELL,NULL};
5use std::error::Error;
6use crate::ta::{Indicator,sma,rsi};
7use serde::{Serialize};
8
9#[derive(Clone, Serialize)]
13pub struct Strategy{
14 pub name:String,
15 pub choices:Vec<Order>,
16 pub indicator:Option<Vec<Vec<f64>>>,
17}
18
19impl Strategy{
20 pub fn choices(&self)->Vec<Order>{
21 return self.choices.clone();
22 }
23 pub fn name(&self)->&String{ return &self.name;}
24 pub fn indicator(&self)->Option<Vec<Vec<f64>>>{ return self.indicator.clone();}
25 pub fn invert(&self) ->Self{
26 let length = self.choices.len();
27 let mut inv_choices = self.choices.clone();
28 for i in 0..length{
29 if self.choices[i]==BUY { inv_choices[i]=SHORTSELL} else if self.choices[i]==SHORTSELL { inv_choices[i]=BUY}
30 }
31 let indicator = self.indicator.clone();
32 Strategy{
33 name:self.name.clone()+"_inv",
34 choices: inv_choices,
35 indicator,
36 }
37 }
38 pub fn long_only(&self) ->Self{
39 let length = self.choices.len();
40 let mut long_choices = self.choices.clone();
41 for i in 0..length{
42 if self.choices[i]==SHORTSELL { long_choices[i]=NULL}
43 }
44 let indicator = self.indicator.clone();
45 Strategy{
46 name:self.name.clone()+"_long",
47 choices: long_choices,
48 indicator,
49 }
50 }
51 pub fn short_only(&self) ->Self{
52 let length = self.choices.len();
53 let mut short_choices = self.choices.clone();
54 for i in 0..length{
55 if self.choices[i]==BUY { short_choices[i]=NULL}
56 }
57 let indicator = self.indicator.clone();
58 Strategy{
59 name:self.name.clone()+"_short",
60 choices: short_choices,
61 indicator,
62 }
63 }
64 pub fn to_csv(&self, filename:&str)->Result<(),Box<dyn Error>>{
65 let mut wrt = Writer::from_path(filename)?;
66 let choices_transpose:Vec<Vec<String>>= self.choices.iter().map(|e|vec![e.clone().to_string().to_string()]).collect();
67 wrt.serialize("choices")?;
68 for col in choices_transpose.iter(){
69 wrt.serialize(col)?;}
70 wrt.flush()?;
71 Ok(())
72 }
73}
74
75pub fn buy_n_hold(quotes:Data)->Strategy{
77 let length = quotes.timestamps().len();
78 let choices = vec![BUY;length];
79 let name = "buy_and_hold".to_string();
80 let indicator = Some(vec![vec![-1.;length]]);
81 Strategy{
82 name:name,
83 choices:choices,
84 indicator,
85 }
86}
87pub fn short_n_hold(quotes:Data)->Strategy{
90 let length = quotes.timestamps().len();
91 let choices = vec![SHORTSELL;length];
92 let name = "short and hold".to_string();
93 let indicator = Some(vec![vec![-1.;length]]);
94 Strategy{
95 name:name,
96 choices:choices,
97 indicator,
98 }
99}
100pub fn do_nothing(quotes:Data)->Strategy{
102 let length = quotes.timestamps().len();
103 let choices = vec![NULL;length];
104 let name = "do nothing".to_string();
105 let indicator = Some(vec![vec![-1.;length]]);
106 Strategy{
107 name:name,
108 choices:choices,
109 indicator,
110 }
111}
112pub fn simple_sma(quotes:Data, period:usize) ->Strategy{
114 let sma = sma("es,period);
115 let indicator = Indicator{indicator:sma,quotes:quotes};
116 let length = indicator.quotes.timestamps().len();
117 let mut choices = vec![NULL;length];
118 for i in 0..length{
119 if indicator.indicator[i]!=-1.{
120 if indicator.indicator[i]<=indicator.quotes.close()[i]{
121 choices[i] = BUY;
122 }else if indicator.indicator[i]>indicator.quotes.close()[i]{
123 choices[i] = SHORTSELL}
124 }
125 }
126 let name = format!("simple_sma_{}",period);
127 let indicator = Some(vec![indicator.indicator()]);
128 Strategy{
129 name:name,
130 choices:choices,
131 indicator,
132 }
133}
134pub fn sma_cross(quotes:Data, short_period:usize, long_period:usize)->Strategy{
137 if short_period >= long_period {panic!("Error: short SMA parameter should be shorter than long SMA parameter");}
138 let sma_short = sma("es, short_period);
139 let sma_long = sma("es, long_period);
140 let ind_short = Indicator{indicator:sma_short,quotes:quotes.clone()};
141 let ind_long = Indicator{indicator:sma_long, quotes:quotes.clone()};
142 let length = ind_short.quotes().timestamps().len();
143 let mut choices = vec![NULL;length];
144 for i in 0..length{
145 if ind_long.indicator()[i]!=-1.{
146 if ind_short.indicator()[i]>ind_long.indicator()[i]{choices[i]=BUY}
147 else {choices[i]=SHORTSELL};
148 }
149 }
150 let name=format!("sma_cross_{}_{}",short_period,long_period);
151 let indicator = Some(vec![ind_short.indicator(),ind_long.indicator()]);
152 Strategy{
153 name:name,
154 choices:choices,
155 indicator:indicator,
156 }
157}
158pub fn rsi_strategy(quotes:Data, period:usize)->Strategy{
160 let rsi = rsi("es,period);
161 let indicator = Indicator{indicator:rsi,quotes};
162 let length = indicator.quotes().timestamps().len();
163 let mut choices = vec![NULL;length];
164 for i in 0..length{
165 if indicator.indicator()[i]!=-1.{
166 if indicator.indicator()[i]>70.{choices[i]=SHORTSELL}
167 else if indicator.indicator()[i]<30. {choices[i]=BUY}
168 }
169 }
170 let name = format!("rsi_{}",period);
171 let indicator=Some(vec![indicator.indicator()]);
172 Strategy{
173 name,
174 choices,
175 indicator,
176 }
177}