Skip to content

Commit

Permalink
Added indicator streams and reference indicators (#60)
Browse files Browse the repository at this point in the history
  • Loading branch information
codeplea committed Mar 31, 2019
1 parent e018520 commit bdc09f9
Show file tree
Hide file tree
Showing 4 changed files with 364 additions and 37 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ CC ?= gcc
AR ?= ar
RANLIB ?= ranlib

CCFLAGS ?= -Wall -Wextra -Wshadow -Wconversion -std=c89 -pedantic -Wno-declaration-after-statement -O2
CCFLAGS ?= -Wall -Wextra -Wshadow -Wconversion -std=c99 -pedantic -O2 -g

SRCS=$(wildcard indicators/*.c)
SRCS+=$(wildcard utils/*.c)
Expand Down
105 changes: 99 additions & 6 deletions indicators.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ puts "Generate interface for indicator library."


set indicators {}
#type name func_name inputs options outputs
#type name func_name inputs options outputs extra_features

#Moving averages
lappend indicators [list overlay "Double Exponential Moving Average" dema 1 1 1 {real} {period} {dema}]
Expand Down Expand Up @@ -153,7 +153,7 @@ lappend indicators [list overlay "Typical Price" typprice 3 0 1 {high low close}
lappend indicators [list overlay "Weighted Close Price" wcprice 3 0 1 {high low close} {} {wcprice}]

#Volatility
lappend indicators [list indicator "Average True Range" atr 3 1 1 {high low close} {period} {atr}]
lappend indicators [list indicator "Average True Range" atr 3 1 1 {high low close} {period} {atr} {stream ref}]
lappend indicators [list indicator "Normalized Average True Range" natr 3 1 1 {high low close} {period} {natr}]
lappend indicators [list indicator "True Range" tr 3 0 1 {high low close} {} {tr}]
lappend indicators [list indicator "Annualized Historical Volatility" volatility 1 1 1 {real} {period} {volatility}]
Expand Down Expand Up @@ -250,6 +250,9 @@ long int ti_build();

set fun_args_start {TI_REAL const *options}
set fun_args "int size, TI_REAL const *const *inputs, TI_REAL const *options, TI_REAL *const *outputs"
set fun_stream_new_args {TI_REAL const *options, ti_stream **stream}
set fun_stream_run_args "ti_stream *stream, int size, TI_REAL const *const *inputs, TI_REAL *const *outputs"
set fun_stream_free_args "ti_stream *stream"

puts $h "
Expand All @@ -259,6 +262,7 @@ long int ti_build();
#define TI_OKAY 0
#define TI_INVALID_OPTION 1
#define TI_OUT_OF_MEMORY 2
#define TI_TYPE_OVERLAY 1 /* These have roughly the same range as the input data. */
#define TI_TYPE_INDICATOR 2 /* Everything else (e.g. oscillators). */
Expand All @@ -272,15 +276,26 @@ long int ti_build();
typedef int (*ti_indicator_start_function)($fun_args_start);
typedef int (*ti_indicator_function)($fun_args);
struct ti_stream; typedef struct ti_stream ti_stream;
typedef int (*ti_indicator_stream_new)($fun_stream_new_args);
typedef int (*ti_indicator_stream_run)($fun_stream_run_args);
typedef void (*ti_indicator_stream_free)($fun_stream_free_args);
typedef struct ti_indicator_info {
char *name;
char *full_name;
ti_indicator_start_function start;
ti_indicator_function indicator;
ti_indicator_function indicator_ref;
int type, inputs, options, outputs;
char *input_names\[TI_MAXINDPARAMS\];
char *option_names\[TI_MAXINDPARAMS\];
char *output_names\[TI_MAXINDPARAMS\];
ti_indicator_stream_new stream_new;
ti_indicator_stream_run stream_run;
ti_indicator_stream_free stream_free;
} ti_indicator_info;
Expand All @@ -294,6 +309,17 @@ const ti_indicator_info *ti_find_indicator(const char *name);
int ti_stream_run(ti_stream *stream, int size, TI_REAL const *const *inputs, TI_REAL *const *outputs);
ti_indicator_info *ti_stream_get_info(ti_stream *stream);
int ti_stream_get_progress(ti_stream *stream);
void ti_stream_free(ti_stream *stream);
/*
Expand All @@ -319,9 +345,12 @@ const ti_indicator_info *ti_find_indicator(const char *name);
file mkdir indicators
file mkdir docs

set index 0

foreach func $indicators {
lassign $func type fn n in opt out in_names opt_names out_names


if {$in != [llength $in_names]} {
puts "WARNING: Bad in names array: $n"
}
Expand Down Expand Up @@ -380,10 +409,27 @@ foreach func $indicators {
append prototype "/* Options: none */\n"
}
append prototype "/* Outputs: [join $out_names {, }] */\n"
append prototype "#define TI_INDICATOR_[string toupper $n]_INDEX $index\n"
append prototype "$start;\n"
append prototype "$fun;"
append prototype "$fun;\n"


if {[llength $func] > 9} {
set extra [lindex $func 9]
if {[lsearch $extra ref] != -1} {
append prototype "int ti_[set n]_ref($fun_args);\n"
}
if {[lsearch $extra stream] != -1} {
append prototype "int ti_[set n]_stream_new($fun_stream_new_args);\n"
append prototype "int ti_[set n]_stream_run($fun_stream_run_args);\n"
append prototype "void ti_[set n]_stream_free($fun_stream_free_args);\n"
}
}


puts $h "\n$prototype\n\n\n"

puts $h "\n\n$prototype\n\n\n"
incr index
}


Expand Down Expand Up @@ -430,21 +476,68 @@ foreach func $indicators {
lassign $func type n fn in opt out in_names opt_names out_names
lappend func_names $n

set ref 0
set stream_new 0
set stream_run 0
set stream_free 0

if {[llength $func] > 9} {
set extra [lindex $func 9]
foreach option $extra {
switch $option {
ref {set ref ti_[set fn]_ref}
stream {
set stream_new ti_[set fn]_stream_new
set stream_run ti_[set fn]_stream_run
set stream_free ti_[set fn]_stream_free
}
}

}
}

set type "TI_TYPE_[string toupper $type]"

set in_names "{\"[join $in_names {","}]\",0}"
set opt_names "{\"[join $opt_names {","}]\",0}"
set out_names "{\"[join $out_names {","}]\",0}"

puts $idx " {\"$fn\", \"$n\", ti_[set fn]_start, ti_[set fn], $type, $in, $opt, $out, $in_names, $opt_names, $out_names},"
puts $idx " {\"$fn\", \"$n\", ti_[set fn]_start, ti_[set fn], $ref, $type, $in, $opt, $out, $in_names, $opt_names, $out_names, $stream_new, $stream_run, $stream_free},"
}

puts $idx " {0,0,0,0,0,0,0,0,{0,0},{0,0},{0,0}}"
puts $idx " {0,0,0,0,0,0,0,0,0,{0,0},{0,0},{0,0},0,0,0}"

puts $idx "};"

puts $idx {



struct ti_stream {
int index;
int progress;
};



int ti_stream_run(ti_stream *stream, int size, TI_REAL const *const *inputs, TI_REAL *const *outputs) {
return ti_indicators[stream->index].stream_run(stream, size, inputs, outputs);
}

ti_indicator_info *ti_stream_get_info(ti_stream *stream) {
return ti_indicators + stream->index;
}

int ti_stream_get_progress(ti_stream *stream) {
return stream->progress;
}

void ti_stream_free(ti_stream *stream) {
ti_indicators[stream->index].stream_free(stream);
}



const ti_indicator_info *ti_find_indicator(const char *name) {
int imin = 0;
int imax = sizeof(ti_indicators) / sizeof(ti_indicator_info) - 2;
Expand Down
118 changes: 118 additions & 0 deletions indicators/atr.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

#include "../indicators.h"
#include "truerange.h"
#include "../utils/minmax.h"



Expand Down Expand Up @@ -69,3 +70,120 @@ int ti_atr(int size, TI_REAL const *const *inputs, TI_REAL const *options, TI_RE
assert(output - outputs[0] == size - ti_atr_start(options));
return TI_OKAY;
}


int ti_atr_ref(int size, TI_REAL const *const *inputs, TI_REAL const *options, TI_REAL *const *outputs) {

//atr = ti_wilders(ti_tr)

//First calculate true range.
const int tr_start = ti_tr_start(0);
const int tr_size = size - tr_start;
TI_REAL *truerange = malloc((unsigned int)tr_size * sizeof(TI_REAL));
if (!truerange) {return TI_OUT_OF_MEMORY;}

TI_REAL *tr_outputs[1] = {truerange};
const int tr_ret = ti_tr(size, inputs, 0, tr_outputs);
if (tr_ret != TI_OKAY) {
free(truerange);
return tr_ret;
}


//Then wilders.
const TI_REAL *wilders_inputs[1] = {truerange};
const int wilders_ret = ti_wilders(tr_size, wilders_inputs, options, outputs);

free(truerange);


assert(size - ti_atr_start(options) == size - ti_wilders_start(options));

return wilders_ret;
}


struct ti_stream {
/* required */
int index;
int progress;

/* indicator specific */
int period;
TI_REAL sum;
TI_REAL last;
};


int ti_atr_stream_new(TI_REAL const *options, ti_stream **stream) {
const int period = (int)options[0];
if (period < 1) return TI_INVALID_OPTION;

*stream = malloc(sizeof(ti_stream));
if (!*stream) {
return TI_OUT_OF_MEMORY;
}

(*stream)->index = TI_INDICATOR_ATR_INDEX;
(*stream)->progress = -ti_atr_start(options);
(*stream)->period = period;
(*stream)->sum = 0.0;

return TI_OKAY;
}


int ti_atr_stream_run(ti_stream *stream, int size, TI_REAL const *const *inputs, TI_REAL *const *outputs) {
const TI_REAL *high = inputs[0];
const TI_REAL *low = inputs[1];
const TI_REAL *close = inputs[2];

TI_REAL *output = outputs[0];

const TI_REAL per = 1.0 / ((TI_REAL)stream->period);

const int start = -(stream->period-1);
int i = 0; /* place in input */


if (stream->progress < 1) {
if (stream->progress == start) {
/* first bar of input */
stream->sum = high[0] - low[0];
++stream->progress; ++i;
}

/* still calculating first output */
while (stream->progress <= 0 && i < size) {
TI_REAL truerange; CALC_TRUERANGE();
stream->sum += truerange;
++stream->progress; ++i;
}

if (stream->progress == 1) {
const TI_REAL val = stream->sum * per;
stream->last = val;
*output++ = val;
}
}

if (stream->progress >= 1) {
/* steady state */
TI_REAL val = stream->last;
while (i < size) {
TI_REAL truerange; CALC_TRUERANGE();
val = (truerange-val) * per + val;
*output++ = val;
++stream->progress; ++i;
}

stream->last = val;
}

return TI_OKAY;
}


void ti_atr_stream_free(ti_stream *stream) {
free(stream);
}
Loading

0 comments on commit bdc09f9

Please sign in to comment.