_orderbook.jl
1 @doc "Utilities for orderbook based strategies." 2 3 using StatsBase: iqr 4 5 function mon_obi(exc, pair, runs=60 * 5) 6 imbs = Array{Real}(undef, runs) 7 price = similar(imbs) 8 r = 1 9 while r < runs + 1 10 imbs[r], price[r] = obimbalance(exc, pair; use_last=true) 11 sleep(1) 12 r += 1 13 end 14 imbs, price 15 end 16 17 macro fetchob(args...) 18 ob = esc(:ob) 19 exc = esc(:exc) 20 pair = esc(:pair) 21 quote 22 if isnothing($ob) 23 $ob = $exc.fetchOrderBook($pair) 24 end 25 end 26 end 27 28 @doc "Aggregates orderbook prices based on volume." 29 function vwap(data, stepvalue; price_vol=true, bid_ask=true, dosort=true) 30 by = price_vol ? :price : :volume 31 div_sym = price_vol ? :price_div : :volume_div 32 if isnothing(stepvalue) 33 stepvalue = iqr(data[:, by]) 34 end 35 # the range label 36 data[:, div_sym] = div.(data[:, by], stepvalue) 37 # the volume in quote currency 38 data[:, :q_volume] = data[:, :price] .* data[:, :volume] 39 # group by ranges 40 gd = groupby(data, div_sym) 41 # apply/combine 42 groups = combine(gd, [:q_volume => sum, :volume => sum]) 43 groups[:, :vwap] = groups[:, :q_volume_sum] ./ groups[:, :volume_sum] 44 dosort ? sort(groups, :vwap; rev=bid_ask) : groups 45 end 46 47 @doc "The orderbook imbalance function. [(bids_price - ask_price) / (bids_price + ask_price)]" 48 function obimbalance(exc, pair; ob=nothing, level=nothing, use_last=false) 49 @fetchob 50 if isnothing(level) && use_last 51 ticker = exc.fetchTicker(pair) 52 level = ticker["last"] 53 end 54 aob = orderbook(exc, pair; ob, stepvalue=level) 55 bvs = aob.bids[1, :vwap] 56 avs = aob.asks[1, :vwap] 57 ((bvs - avs) / (bvs + avs), level) 58 end 59 60 @doc """ 61 - `by` key by which to aggregate values (:price or :volume) 62 - `stepvalue` size of the bins for aggregation (the range value of :price or :volume). If it is nothing, 63 it takes the average of the first 10 elements of the array. 64 """ 65 function orderbook(exc, pair; ob=nothing, stepvalue::Union{Nothing,Real}=nothing, by=:price) 66 @fetchob 67 bids = DataFrame(ob["bids"], ["price", "volume"]) 68 asks = DataFrame(ob["asks"], ["price", "volume"]) 69 price_vol = by === :price 70 ( 71 ob=ob, 72 bids=vwap(bids, stepvalue; price_vol, bid_ask=true), 73 asks=vwap(asks, stepvalue; price_vol, bid_ask=false), 74 ) 75 end