-module(ursatoro@microstructure). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/ursatoro/microstructure.gleam"). -export([vpin/2, amihud/3, roll_measure/2]). -export_type([trade_bar/0]). -type trade_bar() :: {trade_bar, float(), float(), float(), float()}. -file("src/ursatoro/microstructure.gleam", 137). -spec compute_amihud_ratios(list(float()), list(float()), list(float())) -> list(float()). compute_amihud_ratios(Returns, Prices, Volumes) -> case {Returns, Prices, Volumes} of {[R | Rest_r], [P | Rest_p], [V | Rest_v]} -> Denom = P * V, Ratio = case Denom > +0.0 of true -> case Denom of +0.0 -> +0.0; -0.0 -> -0.0; Gleam@denominator -> gleam@float:absolute_value(R) / Gleam@denominator end; false -> +0.0 end, [Ratio | compute_amihud_ratios(Rest_r, Rest_p, Rest_v)]; {_, _, _} -> [] end. -file("src/ursatoro/microstructure.gleam", 157). -spec compute_changes(list(float())) -> list(float()). compute_changes(Prices) -> case Prices of [] -> []; [_] -> []; [First | Rest] -> {Changes, _} = gleam@list:fold( Rest, {[], First}, fun(Acc, P) -> {Cs, Prev} = Acc, {[P - Prev | Cs], P} end ), lists:reverse(Changes) end. -file("src/ursatoro/microstructure.gleam", 171). -spec compute_returns(list(float())) -> list(float()). compute_returns(Prices) -> case Prices of [] -> []; [_] -> []; [First | Rest] -> {Returns, _} = gleam@list:fold( Rest, {[], First}, fun(Acc, P) -> {Rs, Prev} = Acc, Ret = case Prev > +0.0 of true -> case Prev of +0.0 -> +0.0; -0.0 -> -0.0; Gleam@denominator -> (P - Prev) / Gleam@denominator end; false -> +0.0 end, {[Ret | Rs], P} end ), lists:reverse(Returns) end. -file("src/ursatoro/microstructure.gleam", 225). -spec int_to_float(integer()) -> float(). int_to_float(N) -> erlang:float(N). -file("src/ursatoro/microstructure.gleam", 57). -spec compute_vpin_window(list(trade_bar()), integer()) -> float(). compute_vpin_window(Bars, Window) -> Sum = gleam@list:fold( Bars, +0.0, fun(Acc, Bar) -> case erlang:element(4, Bar) > +0.0 of true -> Acc + (case erlang:element(4, Bar) of +0.0 -> +0.0; -0.0 -> -0.0; Gleam@denominator -> gleam@float:absolute_value( erlang:element(3, Bar) - erlang:element(2, Bar) ) / Gleam@denominator end); false -> Acc end end ), W = int_to_float(Window), case W > +0.0 of true -> case W of +0.0 -> +0.0; -0.0 -> -0.0; Gleam@denominator@1 -> Sum / Gleam@denominator@1 end; false -> +0.0 end. -file("src/ursatoro/microstructure.gleam", 39). -spec sliding_vpin(list(trade_bar()), integer(), list(float())) -> list(float()). sliding_vpin(Bars, Window, Acc) -> case erlang:length(Bars) >= Window of false -> lists:reverse(Acc); true -> Window_bars = gleam@list:take(Bars, Window), Value = compute_vpin_window(Window_bars, Window), case gleam@list:rest(Bars) of {ok, Rest} -> sliding_vpin(Rest, Window, [Value | Acc]); {error, _} -> lists:reverse([Value | Acc]) end end. -file("src/ursatoro/microstructure.gleam", 30). -spec vpin(list(trade_bar()), integer()) -> {ok, list(float())} | {error, ursatoro@util:indicator_error()}. vpin(Trade_bars, Window) -> gleam@result:'try'( ursatoro@util:validate_period(Window), fun(_) -> gleam@result:'try'( ursatoro@util:validate_length(Trade_bars, Window), fun(_) -> {ok, sliding_vpin(Trade_bars, Window, [])} end ) end ). -file("src/ursatoro/microstructure.gleam", 189). -spec autocovariance(list(float())) -> float(). autocovariance(Changes) -> case Changes of [] -> +0.0; [_] -> +0.0; [First | Rest] -> {Sum, Count, _} = gleam@list:fold( Rest, {+0.0, 0, First}, fun(Acc, C) -> {S, N, Prev} = Acc, {S + (Prev * C), N + 1, C} end ), case Count > 0 of true -> case int_to_float(Count) of +0.0 -> +0.0; -0.0 -> -0.0; Gleam@denominator -> Sum / Gleam@denominator end; false -> +0.0 end end. -file("src/ursatoro/microstructure.gleam", 206). -spec sliding_mean(list(float()), integer(), list(float())) -> list(float()). sliding_mean(Values, Window, Acc) -> case erlang:length(Values) >= Window of false -> lists:reverse(Acc); true -> Window_vals = gleam@list:take(Values, Window), Sum = gleam@list:fold(Window_vals, +0.0, fun(A, V) -> A + V end), Mean = case int_to_float(Window) of +0.0 -> +0.0; -0.0 -> -0.0; Gleam@denominator -> Sum / Gleam@denominator end, case gleam@list:rest(Values) of {ok, Rest} -> sliding_mean(Rest, Window, [Mean | Acc]); {error, _} -> lists:reverse([Mean | Acc]) end end. -file("src/ursatoro/microstructure.gleam", 113). -spec amihud(list(float()), list(float()), integer()) -> {ok, list(float())} | {error, ursatoro@util:indicator_error()}. amihud(Prices, Volumes, Window) -> gleam@result:'try'( ursatoro@util:validate_period(Window), fun(_) -> Min_len = Window + 1, gleam@result:'try'( ursatoro@util:validate_length(Prices, Min_len), fun(_) -> gleam@result:'try'( ursatoro@util:validate_length(Volumes, Min_len), fun(_) -> Returns = compute_returns(Prices), Vols = case gleam@list:rest(Volumes) of {ok, V} -> V; {error, _} -> [] end, Price_tail = case gleam@list:rest(Prices) of {ok, P} -> P; {error, _} -> [] end, Ratios = compute_amihud_ratios( Returns, Price_tail, Vols ), {ok, sliding_mean(Ratios, Window, [])} end ) end ) end ). -file("src/ursatoro/microstructure.gleam", 232). -spec float_sqrt(float()) -> float(). float_sqrt(X) -> case X =< +0.0 of true -> +0.0; false -> math:sqrt(X) end. -file("src/ursatoro/microstructure.gleam", 90). -spec sliding_roll(list(float()), integer(), list(float())) -> list(float()). sliding_roll(Changes, Window, Acc) -> case erlang:length(Changes) >= Window of false -> lists:reverse(Acc); true -> Window_changes = gleam@list:take(Changes, Window), Autocov = autocovariance(Window_changes), Roll = 2.0 * float_sqrt(gleam@float:absolute_value(Autocov)), case gleam@list:rest(Changes) of {ok, Rest} -> sliding_roll(Rest, Window, [Roll | Acc]); {error, _} -> lists:reverse([Roll | Acc]) end end. -file("src/ursatoro/microstructure.gleam", 79). -spec roll_measure(list(float()), integer()) -> {ok, list(float())} | {error, ursatoro@util:indicator_error()}. roll_measure(Prices, Window) -> gleam@result:'try'( ursatoro@util:validate_period(Window), fun(_) -> Min_len = Window + 1, gleam@result:'try'( ursatoro@util:validate_length(Prices, Min_len), fun(_) -> Changes = compute_changes(Prices), {ok, sliding_roll(Changes, Window, [])} end ) end ).