Name
Utility-Logger
Author
btcvegas
Strategy Description
设置不同的level,控制日志输出等级
Strategy Arguments
Argument | Default | Description |
---|---|---|
level | 0 | Logging Level: DEBUG |
routeFilter | 0 | Route Filter: All |
Source (javascript)
//var COLOR_ERROR = "#FF0000"
//var COLOR_WARN = "#FF0000"
//var COLOR_INFO = "#0000FF"
//var COLOR_DEBUG = "#000000"
var LEVER_PATTERN = {
DEBUG: 0,
INFO: 1,
WARNING: 2,
ERROR: 3
}
$.changeLoggerLever = function (val) {
level = val
}
//var loggerLever = [LEVER_PATTERN.DEBUG, LEVER_PATTERN.INFO, LEVER_PATTERN.WARNING, LEVER_PATTERN.ERROR][level]
$.Error = function (msg, obj, route = 'route') {
if (level == 0 || "route" + routeFilter == route) {
Log('[ERR] ', "[" + route.toUpperCase() + "]", msg, obj, '#0000FF')
}
}
$.Warn = function (msg, obj, route = 'route') {
if (routeFilter == 0 || "route" + routeFilter == route) {
if (level <= LEVER_PATTERN.WARNING) {
Log('[WAR] ', "[" + route.toUpperCase() + "]", msg, obj, '#0000FF')
}
}
}
$.Info = function (msg, obj, route = 'route') {
if (routeFilter == 0 || "route" + routeFilter == route) {
if (level <= LEVER_PATTERN.INFO) {
Log('[INF] ', "[" + route.toUpperCase() + "]", msg, obj, '#0000FF')
}
}
}
$.Debug = function (msg, obj, route = 'route') {
if (routeFilter == 0 || "route" + routeFilter == route) {
if (level <= LEVER_PATTERN.DEBUG) {
Log('[DBG] ', "[" + route.toUpperCase() + "]", msg, obj, '#0000FF')
}
}
}
var executedBlocksCross = []
var executedBlocksCrossIds = []
var takerExecutionSummary = []
var executedTrades = []
var blocksLatency = []
var blocksLatencyV2 = []
var executedTradesTriangular = []
var positionHistory = []
var volumeHistory = []
var currentStatus = []
var blocksTimestamps = []
var tradesTable = {
type: 'table',
title: 'Executed Trades',
cols: ['Timestamp', 'Label-Id', 'Contract', 'Exch-Id', 'Exchange', 'Side', 'Px', 'Amt', 'Fees'],
rows: executedTrades
}
var timestampsTable = {
type: 'table',
title: 'Timestamps',
cols: ['Label-Id', 'Exch-Mkr', 'Start', 'End', 'Mkr-Live', 'Cancel-Mkr', 'Cancel-Exec', 'Creating-Tkr', 'Tkr-Live', 'Complete'],
rows: blocksTimestamps
}
var latencyTable = {
type: 'table',
title: 'Latency',
cols: ['Label-Id', 'Exch-Mkr', 'Start', 'End', 'Book-T', 'Book-M', 'Mkr-Live', 'Cancel-Mkr', 'Cancel-Exec', 'Creating-Tkr', 'Tkr-Live', 'Complete'],
rows: blocksLatencyV2
}
var posTable = {
type: 'table',
title: 'Position History',
cols: ['Timestamp', 'Exch1', 'Exch2', 'Exch1-Pos', 'Exch2-Pos', 'Exposure'],
rows: positionHistory
}
var volumeTable = {
type: 'table',
title: 'Volume Traded',
cols: ['Date', 'Exch1', 'Exch2', 'Exch1-Trade Amt', 'Exch2-Trade Amt', 'Exch1-Total Volume', 'Exch2-Total Volume'],
rows: volumeHistory
}
var blocksTableIds = {
type: 'table',
title: 'Executed Blocks - Ids',
cols: ['Date', 'Label-Id', 'Exch-B', 'Exch-S', 'MkrId', 'TkrId', 'Route'],
rows: executedBlocksCrossIds
}
var blocksTable = {
type: 'table',
title: 'Executed Blocks',
cols: ['Date', 'Label-Id', 'Exch-B', 'Sprd-%', 'Slip-%', 'Sprd-$', 'Val', 'B-Px', 'S-Px', 'B-Amt', 'S-Amt', 'Lc', 'Lat', 'Tries'],
rows: executedBlocksCross
}
var blocksTakerSummary = {
type: 'table',
title: 'Taker Exec',
cols: ['Label-Id', 'Exch-B', 'Slip-%', 'Book-T', 'Book-M', 'Taker-Liq', 'Taker-Px-Init', 'Taker-Px-Sent'],
rows: takerExecutionSummary
}
var tradesTable_triangular = {
type: 'table',
title: 'Executed Blocks',
cols: ['Timestamp', 'Label-Id', 'Exc Sprd', 'Buy-Px', 'Sell-Px', 'Con-Px', 'Buy-Amt', 'Sell-Amt', 'Con-Amt', 'Mkr-Id', 'Tkr-Id', 'Con-Id', 'Loc', 'Lat-Exch', 'Lat-React'],
rows: executedTradesTriangular
}
var currentStatusTable = {
type: 'table',
title: 'Current Status',
cols: ['Timestamp', 'Variable Name', 'Route 1', 'Route 2', 'Route 3', 'Route 4'],
rows: currentStatus
}
/*
Logs the current status of the bot per route. Variables that it tracks:
- Bot State
- Taker Book
- Maker Book
*/
$.logBotStatus = function () {
currentStatus.push(
[
new Date().toLocaleString("da-DK"), // Timestamp
"botState",
_G("botStateroute1"),
_G("botStateroute2"),
_G("botStateroute3"),
_G("botStateroute4")
]
)
LogStatus('`' + JSON.stringify([blocksTable, blocksTableIds, tradesTable, posTable, volumeTable, latencyTable, timestampsTable, currentStatusTable, blocksTakerSummary]) + '`')
}
/* LOC, represents the part of the code that triggered the liquidation.
0- Order creation -> order executed as taker.
1- Order Status -> normal check via websocket.
2- Order Cancellation -> order was executed while the bot was trying to cancel it.
3- REST Update -> bot had to check status via rest.
*/
$.logArbProfit = function (makerTrade, takerTrade, conversionPrice, route, conversionTrade = null) {
if (makerTrade.side == 0 || makerTrade.side == "Buy") {
buyTrade = makerTrade
sellTrade = takerTrade
}
else if (makerTrade.side == 1 || makerTrade.side == "Sell") {
buyTrade = takerTrade
sellTrade = makerTrade
}
else if (takerTrade.side == 0 || takerTrade.side == "Buy") {
buyTrade = takerTrade
sellTrade = makerTrade
}
else if (takerTrade.side == 1 || takerTrade.side == "Sell") {
buyTrade = makerTrade
sellTrade = takerTrade
}
tradeSpread = 0
if (conversionTrade) {
tradeSpread = tradeSpreadTriangular(makerTrade, takerTrade, conversionTrade)
}
else {
tradeSpread = tradeSpreadCross(buyTrade, sellTrade, route)
}
if (tradeSpread > -50 && tradeSpread < 200) {
LogProfit(tradeSpread)
}
}
$.logBlockTrades = function (makerTrade, takerTrade, conversionTrade, labelId, loc, route, lat_mkr, lat_trk, lat_mkr_cancel, lat_cyc, tries, premiumTarget, discountTarget) {
if (takerTrade && makerTrade) {
logTradesCross(makerTrade, takerTrade, labelId, loc, route, lat_trk, lat_cyc, tries, premiumTarget, discountTarget)
$.logLatency(labelId, makerTrade.exchange, lat_mkr, lat_trk, lat_mkr_cancel, lat_cyc)
LogStatus('`' + JSON.stringify([blocksTable, blocksTableIds, tradesTable, posTable, volumeTable, latencyTable, timestampsTable, currentStatusTable, blocksTakerSummary]) + '`')
}
else {
$.Warn("[Utility Logger] Cannot Log Trade", takerTrade)
}
}
$.logExecutions = function (trade, exchange) {
var date = Date.now().toLocaleString()
if (trade.DealAmount > 0) {
// insert to executed Trades
executedTrades.splice(0, 0,
[
date.substring(0, date.length - 3),
trade.label,
trade.contract,
trade.Id,
exchange,
trade.Type,
trade.AvgPrice,
trade.DealAmount,
trade.fees
]
)
// updates executed Blocks Cross if order found
for (block of executedBlocksCross) {
if (trade.label == block[1] && trade.label != null) {
if (trade.Type == "Buy") {
block[7] = trade.AvgPrice // Price
block[9] = trade.DealAmount // Amount
block[5] = _N(block[8] - trade.AvgPrice, 4) // Spread Nominal
block[3] = _N(((block[8] / trade.AvgPrice - 1) * 100), 3) // Spread %
block[6] = _N((block[8] * block[10]) - (trade.AvgPrice * trade.DealAmount), 2) // Value
}
else if (trade.Type == "Sell") {
block[8] = trade.AvgPrice
block[10] = trade.DealAmount
block[5] = _N(trade.AvgPrice - block[7], 4) // Spread Nominal
block[3] = _N(((trade.AvgPrice / block[7] - 1) * 100), 3) // Spread %
block[6] = _N((trade.AvgPrice * trade.DealAmount) - (block[7] * block[9]), 2)
}
}
}
LogStatus('`' + JSON.stringify([blocksTable, blocksTableIds, tradesTable, posTable, volumeTable, latencyTable, timestampsTable, currentStatusTable, blocksTakerSummary]) + '`')
}
}
$.logPosition = function (exch1, exch2, exh1pos, exch2pos) {
positionHistory.splice(0, 0,
[
new Date().toLocaleString("da-DK"),
exch1,
exch2,
exh1pos,
exch2pos,
_N(exh1pos + exch2pos, 3)
]
)
LogStatus('`' + JSON.stringify([blocksTable, blocksTableIds, tradesTable, posTable, volumeTable, latencyTable, timestampsTable, currentStatusTable, blocksTakerSummary]) + '`')
}
$.logTakerExecutionSummary = function (labelId, exchange, orderbook_latency_taker, orderbook_latency_maker, taker_liquidity, taker_price_init, taker_price_sent) {
takerExecutionSummary.splice(0, 0,
[
labelId,
exchange.GetName(),
0,
orderbook_latency_taker,
orderbook_latency_maker,
taker_liquidity,
taker_price_init,
taker_price_sent
]
)
LogStatus('`' + JSON.stringify([blocksTable, blocksTableIds, tradesTable, posTable, volumeTable, latencyTable, timestampsTable, currentStatusTable, blocksTakerSummary]) + '`')
}
$.logVolume = function (exch1, exch2, amt1, amt2) {
var volExchange1 = _G("accumulatedVolume" + exch1) + amt1
var volExchange2 = _G("accumulatedVolume" + exch2) + amt2
volumeHistory.splice(0, 0,
[
new Date().toLocaleString("da-DK"),
exch1,
exch2,
_N(amt1, 2),
_N(amt2, 2),
_N(volExchange1, 2),
_N(volExchange2, 2)
]
)
_G("accumulatedVolume" + exch1, volExchange1),
_G("accumulatedVolume" + exch2, volExchange2)
LogStatus('`' + JSON.stringify([blocksTable, blocksTableIds, tradesTable, posTable, volumeTable, latencyTable, timestampsTable, currentStatusTable, blocksTakerSummary]) + '`')
}
/* Latencies measured.
Send Maker Latency -> latency from sending the order to the maker exchange. Status CREATING_MAKER to RECEIVING_MAKER
Cancel Maker Latency -> latency from trying to cancel the order at the maker exchange. Status SENDING_CANCEL to RECEIVING_CANCEL
Execution Report Latency -> order was executed while the bot was trying to cancel it. Status CANCELLED_EXECUTION to CREATING_TAKER
Sending Taker Latency -> latencry from sending the liquidation order to taker exchange. Status CREATING_TAKER to TAKER_LIVE
Reaction Latency -> Composite latency from moment of transaction notification to sending taker. CANCELLED_EXECUTION to TAKER_LIVE
Full Cycle Latency -> Composite latency from moment of transaction notification to full taker liquidation. CANCELLED_EXECUTION to START.
*/
$.logLatency = function (labelId, exchange, lat_mkr, lat_tkr, lat_mkr_cancel, lat_cyc, lat_er = 0, lat_react = 0) {
blocksLatency.splice(0, 0,
[
labelId,
exchange.GetName(),
lat_mkr,
lat_mkr_cancel,
lat_er,
lat_tkr,
lat_react,
lat_cyc
]
)
LogStatus('`' + JSON.stringify([blocksTable, blocksTableIds, tradesTable, posTable, volumeTable, latencyTable, timestampsTable, currentStatusTable, blocksTakerSummary]) + '`')
}
$.logTimestamps = function (labelId, exchange, loc, start, creating_maker, maker_live, cancelling_maker, cancelled_execution, creating_taker, taker_live, process_execution, orderbook_latency_taker, orderbook_latency_maker) {
// If order is executed before the bot tries to cancel these status are irrelevante
if (loc < 2) {
cancelling_maker = maker_live
cancelled_execution = maker_live
}
blocksLatencyV2.splice(0, 0,
[
labelId,
exchange.GetName(),
start,
process_execution,
orderbook_latency_taker,
orderbook_latency_maker,
maker_live - creating_maker,
cancelling_maker - maker_live,
cancelled_execution - cancelling_maker,
creating_taker - cancelled_execution,
taker_live - creating_taker,
process_execution - taker_live,
]
)
blocksTimestamps.splice(0, 0,
[
labelId,
exchange.GetName(),
start,
process_execution,
maker_live,
cancelling_maker,
cancelled_execution,
creating_taker,
taker_live,
process_execution,
]
)
LogStatus('`' + JSON.stringify([blocksTable, blocksTableIds, tradesTable, posTable, volumeTable, latencyTable, timestampsTable, currentStatusTable, blocksTakerSummary]) + '`')
}
function logTradesCross(makerTrade, takerTrade, labelId, loc, route, lat_tkr, lat_cyc, tries, premiumTarget, discountTarget) {
if (makerTrade.side == 0 || makerTrade.side == "Buy") {
buyTrade = makerTrade
sellTrade = takerTrade
buyExchange = makerTrade.exchange.GetName()
sellExchange = takerTrade.exchange.GetName()
}
else if (makerTrade.side == 1 || makerTrade.side == "Sell") {
buyTrade = takerTrade
sellTrade = makerTrade
buyExchange = takerTrade.exchange.GetName()
sellExchange = makerTrade.exchange.GetName()
}
else if (takerTrade.side == 0 || takerTrade.side == "Buy") {
buyTrade = takerTrade
sellTrade = makerTrade
buyExchange = makerTrade.exchange.GetName()
sellExchange = takerTrade.exchange.GetName()
}
else if (takerTrade.side == 1 || takerTrade.side == "Sell") {
buyTrade = makerTrade
sellTrade = takerTrade
buyExchange = takerTrade.exchange.GetName()
sellExchange = makerTrade.exchange.GetName()
}
if (route == "route1" || route == "route2") {
targetSpread = premiumTarget
}
else if (route == "route3" || route == "route4") {
targetSpread = discountTarget
}
else {
targetSpread = 0
}
var executedSpread = tradeSpreadCross(buyTrade, sellTrade)
var cur_date = new Date()
//cur_date.setHours(d.getHours() - 4)
var blockData = [
cur_date.toLocaleString("ja-JP"), // Date
labelId, // Label Id
buyExchange, // Buy exchange
executedSpread, // Spread %
tradeSlippage(executedSpread, targetSpread), // Slippage
_N(sellTrade.price - buyTrade.price, 5), // Spread $
tradeValueCross(buyTrade, sellTrade), // Value $
_N(buyTrade.price, 5), // Buy Price
_N(sellTrade.price, 5), // Sell Price
buyTrade.size, // Buy Size
sellTrade.size, // Sell Size
loc, // Location of liquidation initiation
lat_cyc, // Total Cycle duration
tries // Number of tries to liquidate
]
Log("blockData", blockData)
var blockIds = [
cur_date.toLocaleString("da-DK", { timeZone: 'America/New_York' }),
labelId,
buyExchange,
sellExchange,
makerTrade.id,
takerTrade.id,
route
]
Log("blockIds", blockIds)
executedBlocksCross.splice(0, 0, blockData)
executedBlocksCrossIds.splice(0, 0, blockIds)
}
function tradeSpreadCross(buyTrade, sellTrade) {
return _N(((sellTrade.price / buyTrade.price - 1) * 100), 3)
}
function tradeValueCross(buyTrade, sellTrade) {
return _N((sellTrade.price * sellTrade.size) - (buyTrade.price * buyTrade.size), 2)
}
function tradeSlippage(executedSpread, targetSpread) {
var result = executedSpread - targetSpread
return _N(result, 2)
}
function logTradesTriangular(makerTrade, takerTrade, conversionTrade, labelId, loc, lat) {
conversionPrice = _N(conversionTrade.price, 6)
conversionSize = conversionTrade.size
conversionId = conversionTrade.id
executedTradesTriangular.push(
[Date.now(),
labelId,
(makerTrade.side == 0 || makerTrade.side == "Sell" || makerTrade.side == "sell") ? "Buy" : "Sell",
tradeSpreadTriangular(makerTrade, takerTrade, conversionTrade),
makerTrade.price,
takerTrade.price,
conversionPrice,
makerTrade.size,
takerTrade.size,
conversionSize,
makerTrade.id,
takerTrade.id,
conversionTrade.id,
loc,
lat
]
)
}
function tradeSpreadTriangular(makerTrade, takerTrade, conversionTrade) {
var result = 0
// if it is a triangular arbitrage trade
if (conversionTrade && makerTrade && takerTrade) {
if ((makerTrade.side == 1 || makerTrade.side == "Sell" || makerTrade.side == "sell")) {
result = _N(((makerTrade.price / (takerTrade.price * conversionTrade.price) - 1) * 100), 2)
}
else {
result = _N((((takerTrade.price * conversionTrade.price) / makerTrade.price - 1) * 100), 2)
}
}
}
Detail
https://www.fmz.com/strategy/209236
Last Modified
2023-02-28 05:26:51