Packages

TIC Crypto Liquidity Integrator

Current section

Files

Jump to
tic src tic.erl
Raw

src/tic.erl

-module(tic).
-description('TIC Trade Integration Platform').
-behaviour(supervisor).
-behaviour(application).
-compile(export_all).
-export([start/2, stop/1, init/1, log_modules/0]).
venues() -> [{bitmex, "wss://www.bitmex.com/realtime?subscribe=trade,orderBookL2"},
{gdax, "wss://ws-feed.gdax.com"}].
f(T,[]) -> [];
f(T,[P,A]) -> io_lib:format("['~s', -~p, 0]", [timestamp(),A]);
f(T,[trade,P,S,bid]) -> io_lib:format("['~s', ~s, ~s]", [timestamp(), tic:print_float(P),tic:print_float(S)]);
f(T,[trade,P,S,ask]) -> io_lib:format("['~s', ~s, -~s]", [timestamp(), tic:print_float(P),tic:print_float(S)]);
f(T,[A,P,S,ask]) -> io_lib:format("['~s', -~p, ~s, ~s]",[timestamp(),A,tic:print_float(P),tic:print_float(S)]);
f(T,[A,P,S,bid]) -> io_lib:format("['~s', +~p, ~s, ~s]",[timestamp(),A,tic:print_float(P),tic:print_float(S)]);
f(T,X) -> io_lib:format("['~s', ~p]", [timestamp(),X]).
trace(Venue,[Stream,A,Sym,S,P,Side,Debug,Timestamp,OID,Seq]) ->
{{Y,M,D},_}=calendar:universal_time(),
file:make_dir(lists:concat(["priv/",Venue,"/",Stream,"/",Y,"-",M,"-",D])),
FileName = lists:concat(["priv/",Venue,"/",Stream,"/",Y,"-",M,"-",D,"/",Sym]),
Order = lists:flatten(f(Timestamp,Venue:Stream(Sym,A,Side,normal(p(S)),normal(p(P)),Debug,OID,Seq))),
case application:get_env(trade,log,hide) of
show -> io:format("~p:~p:~p:~s ~p~n",[Venue,Sym,Side,Order,Debug]);
_ -> skip end,
wf:send({Venue,wf:to_atom(Sym)},{text,list_to_binary(Order)}),
wrap(FileName,Order).
wrap(N,[]) -> skip;
wrap(N,List) -> file:write_file(N, list_to_binary(List++"\n"), [raw, binary, append, read, write]).
spec(Port) -> ranch:child_spec(http, 1, ranch_tcp, port(Port), cowboy_protocol, env()).
env() -> [ { env, [ { dispatch, points() } ] } ].
port(Port) -> [ { port, Port } ].
points() -> cowboy_router:compile([{'_', [ {"/[...]", n2o_stream, []} ]}]).
log_modules() -> [ bitmex, gdax, book, bsym, bshot, gshot, app, snapshot, venue, protocol ].
init([]) -> { ok, { { one_for_one, 5, 1 }, [spec(application:get_env(n2o,port,9001))] ++
[ ws(A,B) || {A,B} <- venues() ] } }.
start(_,_) -> dirs(), %kvs:join(),
supervisor:start_link({local,?MODULE},?MODULE,[]).
stop(_) -> ok.
precision() -> 8.
pad(I,X) -> string:right(integer_to_list(I),X,$0).
ws(Venue,URL) -> {Venue,{venue,start_link,[Venue,URL]},permanent,1000,worker,[Venue]}.
dirs() -> file:make_dir("priv"),
[ begin file:make_dir(lists:concat(["priv/",X])),
[ file:make_dir(lists:concat(["priv/",X,"/",Y]))
|| Y <- [trade,order] ]
end || X <- [bitmex, gdax] ].
p(X) when is_integer(X) -> integer_to_list(X);
p(X) when is_float(X) -> float_to_list(X,[{decimals,8},compact]);
p(X) -> X.
timestamp() ->
{Ma,Sa,Micro} = os:timestamp(),
{_,{A,B,C}} = calendar:seconds_to_daystime(Ma*1000000 + Sa),
io_lib:format("~s:~s:~s.~s",[pad(A,2),pad(B,2),pad(C,2),pad(Micro div 1000,3)]).
n([Z,Y]) -> lists:concat([Z,Y,lists:duplicate(precision() - length(Y),"0")]).
normal(Price) -> lists:flatten(c(string:tokens(Price,"."))).
main(A)-> mad:main(A).
nn([]) -> 0;
nn(X) -> try list_to_integer(X) catch _:_ -> list_to_float(X) end.
c([]) -> [];
c([X]) -> n([X,[]]);
c(X) -> n(X).
flo(N) -> P = string:right(N,precision(),$0),
lists:concat([case string:substr(N,1,erlang:max(length(N)-precision(),0)) of
[] -> "0"; E -> case string:strip(E, left, $0) of
[] -> "0"; B -> B end end, ".",
case string:substr(P,length(P)-precision()+1,precision()) of
[] -> "0"; E -> case string:strip(E, right, $0) of
[] -> "0"; B -> B end end]).
print_float(X) ->
case X of
"+"++N -> lists:concat(["+",flo(N)]);
"-"++N -> lists:concat(["-",flo(N)]);
I when is_list(I) -> flo(I);
I -> flo(p(I)) end.