diff --git a/tick/feed.py b/tick/feed.py new file mode 100644 index 0000000..3b9dbfa --- /dev/null +++ b/tick/feed.py @@ -0,0 +1,66 @@ +import logging +from datetime import datetime +import argparse + +import pykx as kx + +from cryptofeed import FeedHandler +from cryptofeed.exchanges import ( + Coinbase, + Bitfinex, + Binance, + BinanceFutures, + BinanceUS +) +from cryptofeed.defines import TRADES, L2_BOOK +from cryptofeed.types import Trade + +parser = argparse.ArgumentParser(description='CryptoFeed Script') +parser.add_argument('--host', type=str, default='localhost', help='KDB+ host') +parser.add_argument('--port', type=int, default=5000, help='KDB+ port') +args = parser.parse_args() + +h = kx.SyncQConnection(args.host, args.port) +logging.basicConfig(level=logging.INFO) + + +async def trade(t: Trade, receipt_timestamp): + time = datetime.fromtimestamp(receipt_timestamp) + ins = kx.q('{[time;s;e;si;am;pr] ("n"$time;s;e;si;am;pr)}', + time, t.symbol.replace('-', '_'), t.exchange, t.side, + float(t.amount), float(t.price)) + h('.u.upd[`trade;]', ins) + + +async def l2_book(t, receipt_timestamp): + time = datetime.fromtimestamp(receipt_timestamp) + bid_price, bid_size = t.book.bids.index(0) + ask_price, ask_size = t.book.asks.index(0) + ins = kx.q('{[time;s;e;b;a;bs;as] ("n"$time;s;e;b;a;bs;as)}', + time, t.symbol.replace('-', '_'), t.exchange, float(bid_price), + float(ask_price), float(bid_size), float(ask_size)) + h('.u.upd[`quote;]', ins) + + +def main(): + f = FeedHandler() + f.add_feed(Coinbase(symbols=['ADA-USDT', 'XRP-USDT'], + channels=[TRADES], + callbacks={TRADES: trade})) + f.add_feed(Binance(symbols=['ADA-USDT', 'XRP-USDT'], + channels=[TRADES, L2_BOOK], + callbacks={TRADES: trade, L2_BOOK: l2_book})) + f.add_feed(BinanceFutures(symbols=['ADA-USDT-PERP', 'XRP-USDT-PERP'], + channels=[TRADES, L2_BOOK], + callbacks={TRADES: trade, L2_BOOK: l2_book})) + f.add_feed(BinanceUS(symbols=['ADA-USDT', 'XRP-USDT'], + channels=[TRADES, L2_BOOK], + callbacks={TRADES: trade, L2_BOOK: l2_book})) + f.add_feed(Bitfinex(symbols=['ADA-USDT', 'XRP-USDT'], + channels=[TRADES, L2_BOOK], + callbacks={TRADES: trade, L2_BOOK: l2_book})) + f.run() + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/tick/feed.q b/tick/feed.q deleted file mode 100644 index 9fbcf80..0000000 --- a/tick/feed.q +++ /dev/null @@ -1,26 +0,0 @@ -// / Read data -tab1: update sym:`SP500 from 1_ flip `dateTime`bid`ask`bidVol`askVol!("*FFFF";",") 0: `:data/USA500IDXUSD.csv; -tab2: update sym:`NASDAQ100 from 1_ flip `dateTime`bid`ask`bidVol`askVol!("*FFFF";",") 0: `:data/USATECHIDXUSD.csv; -tradesSP: 0!1_(update delta:0f^deltas dateTime from - distinct select "n"$dateTime,sym, log bid, log ask from - update dateTime:"P"$@[;19;:;"."] each dateTime from - `dateTime xasc tab1); - -tradesNYS: 0!1_(update delta:0f^deltas dateTime from - distinct select "n"$dateTime,sym, log bid, log ask from - update dateTime:"P"$@[;19;:;"."] each dateTime from - `dateTime xasc tab2); - -.tick.i:-1 -timer:{t:.z.p;while[.z.pcount .z.x;show"Supply directory of historical database";exit 0]; +hdb:.z.x 0 +/Mount the Historical Date Partitioned Database +@[{system"l ",x};hdb;{show "Error message - ",x;exit 0}] \ No newline at end of file diff --git a/tick/launch.sh b/tick/launch.sh new file mode 100644 index 0000000..54eaa80 --- /dev/null +++ b/tick/launch.sh @@ -0,0 +1,58 @@ +#!/bin/sh +# arguments: +# - tickerplant port +# - rdb port +# - hdb port +# - rts port + +TPP=${1:-5000} +HDBP=${2:-5001} +RDBP=${3:-5002} +RTSP=${4:-5003} + +echo TP port: $TPP +echo HDB port: $HDBP +echo RDB port: $RDBP +echo RTS port: $RTSP + +kill_processes() { + echo "Killing all processes" + kill -9 $TP_JOB $HDB_JOB $RDB_JOB $RTS_JOB $FEED_JOB + echo "Done!" + exit 0 +} + +start_processes() { + echo "Starting tickerplant..." + q tick.q sym db -p $1 & + TP_JOB=$! + echo TP job: $TP_JOB + + echo "Starting HDB..." + q hdb.q db/sym -p $2 & + HDB_JOB=$! + echo HDB job: $HDB_JOB + + echo "Starting RDB..." + q tick/r.q localhost:$1 localhost:$2 -p $3 & + RDB_JOB=$! + echo RDB job $RDB_JOB + + # echo "Starting real time subscriber..." + # q rts.q localhost:$1 -p $4 & + # RTS_JOB=$! + # echo RTS job $RTS_JOB + + echo "Starting feedhandler..." + 2>/dev/null 1>&2 python3 feed.py --host localhost --port $1 & + FEED_JOB=$! + echo Feed job $FEED_JOB + + trap "kill_processes" INT +} + +start_processes $TPP $HDBP $RDBP $FEED_JOB # $RTSP + +while [ true ]; do + sleep 2 +done \ No newline at end of file diff --git a/tick/sym.q b/tick/sym.q deleted file mode 100644 index 500191a..0000000 --- a/tick/sym.q +++ /dev/null @@ -1,2 +0,0 @@ -// trade table schema -trade:([]time:`timespan$();sym:`g#`symbol$();bid:`float$();ask:`float$()); \ No newline at end of file diff --git a/tick/r.q b/tick/tick/r.q similarity index 100% rename from tick/r.q rename to tick/tick/r.q diff --git a/tick/tick/sym.q b/tick/tick/sym.q new file mode 100644 index 0000000..317aab5 --- /dev/null +++ b/tick/tick/sym.q @@ -0,0 +1,4 @@ +quote:([]time:`timespan$();sym:`g#`symbol$();exch:`symbol$(); + bid:`float$();ask:`float$();bsize:`float$();asize:`float$()) +trade:([]time:`timespan$();sym:`g#`symbol$();exch:`symbol$(); + side:`symbol$();size:`float$();price:`float$()) \ No newline at end of file diff --git a/tick/u.q b/tick/tick/u.q similarity index 100% rename from tick/u.q rename to tick/tick/u.q