pub mod divergence;
pub use self::divergence::Divergence;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SignalEvent {
Long,
Short,
Exit,
Hold,
}
pub trait Signal {
type Input;
fn next(&mut self, value: Self::Input) -> Option<SignalEvent>;
fn reset(&mut self);
}
pub trait SignalExt: Signal + Sized {
fn and<O>(self, other: O) -> AndSignal<Self, O>
where
O: Signal<Input = Self::Input>,
{
AndSignal { a: self, b: other }
}
fn or<O>(self, other: O) -> OrSignal<Self, O>
where
O: Signal<Input = Self::Input>,
{
OrSignal { a: self, b: other }
}
fn not(self) -> NotSignal<Self> {
NotSignal { inner: self }
}
}
impl<S: Signal + Sized> SignalExt for S {}
#[derive(Debug, Default)]
pub struct CrossUp {
prev: Option<(f64, f64)>,
}
impl CrossUp {
pub fn new() -> Self {
Self::default()
}
}
impl Signal for CrossUp {
type Input = (f64, f64);
fn next(&mut self, (a, b): (f64, f64)) -> Option<SignalEvent> {
let event = match self.prev {
Some((pa, pb)) if pa <= pb && a > b => Some(SignalEvent::Long),
Some(_) => Some(SignalEvent::Hold),
None => None,
};
self.prev = Some((a, b));
event
}
fn reset(&mut self) {
self.prev = None;
}
}
#[derive(Debug, Default)]
pub struct CrossDown {
prev: Option<(f64, f64)>,
}
impl CrossDown {
pub fn new() -> Self {
Self::default()
}
}
impl Signal for CrossDown {
type Input = (f64, f64);
fn next(&mut self, (a, b): (f64, f64)) -> Option<SignalEvent> {
let event = match self.prev {
Some((pa, pb)) if pa >= pb && a < b => Some(SignalEvent::Short),
Some(_) => Some(SignalEvent::Hold),
None => None,
};
self.prev = Some((a, b));
event
}
fn reset(&mut self) {
self.prev = None;
}
}
#[derive(Debug)]
pub struct ThresholdAbove {
level: f64,
prev: Option<f64>,
}
impl ThresholdAbove {
pub fn new(level: f64) -> Self {
Self { level, prev: None }
}
}
impl Signal for ThresholdAbove {
type Input = f64;
fn next(&mut self, value: f64) -> Option<SignalEvent> {
let event = match self.prev {
Some(prev) if prev <= self.level && value > self.level => Some(SignalEvent::Long),
Some(_) => Some(SignalEvent::Hold),
None => None,
};
self.prev = Some(value);
event
}
fn reset(&mut self) {
self.prev = None;
}
}
#[derive(Debug)]
pub struct ThresholdBelow {
level: f64,
prev: Option<f64>,
}
impl ThresholdBelow {
pub fn new(level: f64) -> Self {
Self { level, prev: None }
}
}
impl Signal for ThresholdBelow {
type Input = f64;
fn next(&mut self, value: f64) -> Option<SignalEvent> {
let event = match self.prev {
Some(prev) if prev >= self.level && value < self.level => Some(SignalEvent::Short),
Some(_) => Some(SignalEvent::Hold),
None => None,
};
self.prev = Some(value);
event
}
fn reset(&mut self) {
self.prev = None;
}
}
#[derive(Debug, Default)]
pub struct Breakout {
inside: Option<bool>,
}
impl Breakout {
pub fn new() -> Self {
Self::default()
}
}
impl Signal for Breakout {
type Input = (f64, f64, f64);
fn next(&mut self, (value, upper, lower): (f64, f64, f64)) -> Option<SignalEvent> {
let was_inside = self.inside;
let now_inside = value <= upper && value >= lower;
self.inside = Some(now_inside);
match was_inside {
None => None,
Some(true) if value > upper => Some(SignalEvent::Long),
Some(true) if value < lower => Some(SignalEvent::Short),
_ => Some(SignalEvent::Hold),
}
}
fn reset(&mut self) {
self.inside = None;
}
}
#[derive(Debug)]
pub struct AndSignal<A, B> {
a: A,
b: B,
}
impl<A, B> Signal for AndSignal<A, B>
where
A: Signal,
B: Signal<Input = A::Input>,
A::Input: Clone,
{
type Input = A::Input;
fn next(&mut self, value: Self::Input) -> Option<SignalEvent> {
match (self.a.next(value.clone()), self.b.next(value)) {
(Some(SignalEvent::Long), Some(SignalEvent::Long)) => Some(SignalEvent::Long),
(Some(SignalEvent::Short), Some(SignalEvent::Short)) => Some(SignalEvent::Short),
(Some(SignalEvent::Exit), _) | (_, Some(SignalEvent::Exit)) => Some(SignalEvent::Exit),
(Some(_), Some(_)) => Some(SignalEvent::Hold),
_ => None,
}
}
fn reset(&mut self) {
self.a.reset();
self.b.reset();
}
}
#[derive(Debug)]
pub struct OrSignal<A, B> {
a: A,
b: B,
}
impl<A, B> Signal for OrSignal<A, B>
where
A: Signal,
B: Signal<Input = A::Input>,
A::Input: Clone,
{
type Input = A::Input;
fn next(&mut self, value: Self::Input) -> Option<SignalEvent> {
let ea = self.a.next(value.clone());
let eb = self.b.next(value);
match (ea, eb) {
(Some(SignalEvent::Long), _) | (_, Some(SignalEvent::Long)) => Some(SignalEvent::Long),
(Some(SignalEvent::Short), _) | (_, Some(SignalEvent::Short)) => {
Some(SignalEvent::Short)
}
(Some(SignalEvent::Exit), _) | (_, Some(SignalEvent::Exit)) => Some(SignalEvent::Exit),
(Some(SignalEvent::Hold), Some(SignalEvent::Hold)) => Some(SignalEvent::Hold),
(Some(e), None) | (None, Some(e)) => Some(e),
_ => None,
}
}
fn reset(&mut self) {
self.a.reset();
self.b.reset();
}
}
#[derive(Debug)]
pub struct NotSignal<S> {
inner: S,
}
impl<S: Signal> Signal for NotSignal<S> {
type Input = S::Input;
fn next(&mut self, value: Self::Input) -> Option<SignalEvent> {
self.inner.next(value).map(|e| match e {
SignalEvent::Long => SignalEvent::Short,
SignalEvent::Short => SignalEvent::Long,
other => other,
})
}
fn reset(&mut self) {
self.inner.reset();
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn cross_up_fires_only_on_transition() {
let mut s = CrossUp::new();
assert_eq!(s.next((9.0, 10.0)), None);
assert_eq!(s.next((9.5, 10.0)), Some(SignalEvent::Hold));
assert_eq!(s.next((11.0, 10.0)), Some(SignalEvent::Long));
assert_eq!(s.next((12.0, 10.0)), Some(SignalEvent::Hold));
}
#[test]
fn cross_down_mirrors_cross_up() {
let mut s = CrossDown::new();
assert_eq!(s.next((11.0, 10.0)), None);
assert_eq!(s.next((10.5, 10.0)), Some(SignalEvent::Hold));
assert_eq!(s.next((9.0, 10.0)), Some(SignalEvent::Short));
assert_eq!(s.next((8.0, 10.0)), Some(SignalEvent::Hold));
}
#[test]
fn threshold_above_triggers_on_up_crossing() {
let mut s = ThresholdAbove::new(70.0);
assert_eq!(s.next(50.0), None);
assert_eq!(s.next(65.0), Some(SignalEvent::Hold));
assert_eq!(s.next(75.0), Some(SignalEvent::Long));
assert_eq!(s.next(80.0), Some(SignalEvent::Hold));
}
#[test]
fn breakout_fires_on_channel_break() {
let mut s = Breakout::new();
assert_eq!(s.next((10.0, 11.0, 9.0)), None);
assert_eq!(s.next((10.5, 11.0, 9.0)), Some(SignalEvent::Hold));
assert_eq!(s.next((11.5, 11.0, 9.0)), Some(SignalEvent::Long));
assert_eq!(s.next((10.0, 11.0, 9.0)), Some(SignalEvent::Hold));
}
#[test]
fn and_combinator_requires_agreement() {
let mut s = CrossUp::new().and(CrossUp::new());
assert_eq!(s.next((9.0, 10.0)), None);
assert_eq!(s.next((11.0, 10.0)), Some(SignalEvent::Long));
}
#[test]
fn not_combinator_flips_long_short() {
let mut s = CrossUp::new().not();
assert_eq!(s.next((9.0, 10.0)), None);
assert_eq!(s.next((11.0, 10.0)), Some(SignalEvent::Short));
}
}