ccxt-go/krakenfutures.go
zhangkun9038@dingtalk.com 1a2ce7046a first add
2025-02-28 10:33:20 +08:00

3317 lines
147 KiB
Go

package ccxt
// PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
// https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
type krakenfutures struct {
Exchange
}
func NewKrakenfuturesCore() krakenfutures {
p := krakenfutures{}
setDefaults(&p)
return p
}
func (this *krakenfutures) Describe() interface{} {
return this.DeepExtend(this.Exchange.Describe(), map[string]interface{} {
"id": "krakenfutures",
"name": "Kraken Futures",
"countries": []interface{}{"US"},
"version": "v3",
"userAgent": nil,
"rateLimit": 600,
"pro": true,
"has": map[string]interface{} {
"CORS": nil,
"spot": false,
"margin": false,
"swap": true,
"future": true,
"option": false,
"cancelAllOrders": true,
"cancelAllOrdersAfter": true,
"cancelOrder": true,
"cancelOrders": true,
"createMarketOrder": false,
"createOrder": true,
"createStopOrder": true,
"createTriggerOrder": true,
"editOrder": true,
"fetchBalance": true,
"fetchBorrowRateHistories": false,
"fetchBorrowRateHistory": false,
"fetchCanceledOrders": true,
"fetchClosedOrders": true,
"fetchCrossBorrowRate": false,
"fetchCrossBorrowRates": false,
"fetchDepositAddress": false,
"fetchDepositAddresses": false,
"fetchDepositAddressesByNetwork": false,
"fetchFundingHistory": nil,
"fetchFundingRate": "emulated",
"fetchFundingRateHistory": true,
"fetchFundingRates": true,
"fetchIndexOHLCV": false,
"fetchIsolatedBorrowRate": false,
"fetchIsolatedBorrowRates": false,
"fetchIsolatedPositions": false,
"fetchLeverage": true,
"fetchLeverages": true,
"fetchLeverageTiers": true,
"fetchMarketLeverageTiers": "emulated",
"fetchMarkets": true,
"fetchMarkOHLCV": true,
"fetchMyTrades": true,
"fetchOHLCV": true,
"fetchOpenOrders": true,
"fetchOrder": false,
"fetchOrderBook": true,
"fetchOrders": false,
"fetchPositions": true,
"fetchPremiumIndexOHLCV": false,
"fetchTickers": true,
"fetchTrades": true,
"sandbox": true,
"setLeverage": true,
"setMarginMode": false,
"transfer": true,
},
"urls": map[string]interface{} {
"test": map[string]interface{} {
"public": "https://demo-futures.kraken.com/derivatives/api/",
"private": "https://demo-futures.kraken.com/derivatives/api/",
"charts": "https://demo-futures.kraken.com/api/charts/",
"history": "https://demo-futures.kraken.com/api/history/",
"www": "https://demo-futures.kraken.com",
},
"logo": "https://user-images.githubusercontent.com/24300605/81436764-b22fd580-9172-11ea-9703-742783e6376d.jpg",
"api": map[string]interface{} {
"charts": "https://futures.kraken.com/api/charts/",
"history": "https://futures.kraken.com/api/history/",
"feeschedules": "https://futures.kraken.com/api/feeschedules/",
"public": "https://futures.kraken.com/derivatives/api/",
"private": "https://futures.kraken.com/derivatives/api/",
},
"www": "https://futures.kraken.com/",
"doc": []interface{}{"https://docs.futures.kraken.com/#introduction"},
"fees": "https://support.kraken.com/hc/en-us/articles/360022835771-Transaction-fees-and-rebates-for-Kraken-Futures",
"referral": nil,
},
"api": map[string]interface{} {
"public": map[string]interface{} {
"get": []interface{}{"feeschedules", "instruments", "orderbook", "tickers", "history", "historicalfundingrates"},
},
"private": map[string]interface{} {
"get": []interface{}{"feeschedules/volumes", "openpositions", "notifications", "accounts", "openorders", "recentorders", "fills", "transfers", "leveragepreferences", "pnlpreferences", "assignmentprogram/current", "assignmentprogram/history"},
"post": []interface{}{"sendorder", "editorder", "cancelorder", "transfer", "batchorder", "cancelallorders", "cancelallordersafter", "withdrawal", "assignmentprogram/add", "assignmentprogram/delete"},
"put": []interface{}{"leveragepreferences", "pnlpreferences"},
},
"charts": map[string]interface{} {
"get": []interface{}{"{price_type}/{symbol}/{interval}"},
},
"history": map[string]interface{} {
"get": []interface{}{"orders", "executions", "triggers", "accountlogcsv", "account-log", "market/{symbol}/orders", "market/{symbol}/executions"},
},
},
"fees": map[string]interface{} {
"trading": map[string]interface{} {
"tierBased": true,
"percentage": true,
"taker": this.ParseNumber("0.0005"),
"maker": this.ParseNumber("0.0002"),
"tiers": map[string]interface{} {
"taker": []interface{}{[]interface{}{this.ParseNumber("0"), this.ParseNumber("0.0005")}, []interface{}{this.ParseNumber("100000"), this.ParseNumber("0.0004")}, []interface{}{this.ParseNumber("1000000"), this.ParseNumber("0.0003")}, []interface{}{this.ParseNumber("5000000"), this.ParseNumber("0.00025")}, []interface{}{this.ParseNumber("10000000"), this.ParseNumber("0.0002")}, []interface{}{this.ParseNumber("20000000"), this.ParseNumber("0.00015")}, []interface{}{this.ParseNumber("50000000"), this.ParseNumber("0.000125")}, []interface{}{this.ParseNumber("100000000"), this.ParseNumber("0.0001")}},
"maker": []interface{}{[]interface{}{this.ParseNumber("0"), this.ParseNumber("0.0002")}, []interface{}{this.ParseNumber("100000"), this.ParseNumber("0.0015")}, []interface{}{this.ParseNumber("1000000"), this.ParseNumber("0.000125")}, []interface{}{this.ParseNumber("5000000"), this.ParseNumber("0.0001")}, []interface{}{this.ParseNumber("10000000"), this.ParseNumber("0.000075")}, []interface{}{this.ParseNumber("20000000"), this.ParseNumber("0.00005")}, []interface{}{this.ParseNumber("50000000"), this.ParseNumber("0.000025")}, []interface{}{this.ParseNumber("100000000"), this.ParseNumber("0")}},
},
},
},
"exceptions": map[string]interface{} {
"exact": map[string]interface{} {
"apiLimitExceeded": RateLimitExceeded,
"marketUnavailable": ContractUnavailable,
"requiredArgumentMissing": BadRequest,
"unavailable": ExchangeNotAvailable,
"authenticationError": AuthenticationError,
"accountInactive": ExchangeError,
"invalidAccount": BadRequest,
"invalidAmount": BadRequest,
"insufficientFunds": InsufficientFunds,
"Bad Request": BadRequest,
"Unavailable": ExchangeNotAvailable,
"invalidUnit": BadRequest,
"Json Parse Error": ExchangeError,
"nonceBelowThreshold": InvalidNonce,
"nonceDuplicate": InvalidNonce,
"notFound": BadRequest,
"Server Error": ExchangeError,
"unknownError": ExchangeError,
},
"broad": map[string]interface{} {
"invalidArgument": BadRequest,
"nonceBelowThreshold": InvalidNonce,
"nonceDuplicate": InvalidNonce,
},
},
"precisionMode": TICK_SIZE,
"options": map[string]interface{} {
"access": map[string]interface{} {
"history": map[string]interface{} {
"GET": map[string]interface{} {
"orders": "private",
"executions": "private",
"triggers": "private",
"accountlogcsv": "private",
},
},
},
"settlementCurrencies": map[string]interface{} {
"flex": []interface{}{"USDT", "BTC", "USD", "GBP", "EUR", "USDC"},
},
"symbol": map[string]interface{} {
"quoteIds": []interface{}{"USD", "XBT"},
"reversed": false,
},
"versions": map[string]interface{} {
"public": map[string]interface{} {
"GET": map[string]interface{} {
"historicalfundingrates": "v4",
},
},
"charts": map[string]interface{} {
"GET": map[string]interface{} {
"{price_type}/{symbol}/{interval}": "v1",
},
},
"history": map[string]interface{} {
"GET": map[string]interface{} {
"orders": "v2",
"executions": "v2",
"triggers": "v2",
"accountlogcsv": "v2",
},
},
},
"fetchTrades": map[string]interface{} {
"method": "historyGetMarketSymbolExecutions",
},
},
"features": map[string]interface{} {
"default": map[string]interface{} {
"sandbox": true,
"createOrder": map[string]interface{} {
"marginMode": false,
"triggerPrice": true,
"triggerPriceType": map[string]interface{} {
"last": true,
"mark": true,
"index": true,
},
"triggerDirection": false,
"stopLossPrice": true,
"takeProfitPrice": true,
"attachedStopLossTakeProfit": nil,
"timeInForce": map[string]interface{} {
"IOC": true,
"FOK": true,
"PO": true,
"GTD": false,
},
"hedged": false,
"trailing": false,
"leverage": false,
"marketBuyByCost": false,
"marketBuyRequiresPrice": false,
"selfTradePrevention": false,
"iceberg": false,
},
"createOrders": map[string]interface{} {
"max": 100,
},
"fetchMyTrades": map[string]interface{} {
"marginMode": false,
"limit": nil,
"daysBack": nil,
"untilDays": 100000,
"symbolRequired": false,
},
"fetchOrder": nil,
"fetchOpenOrders": map[string]interface{} {
"marginMode": false,
"limit": nil,
"trigger": false,
"trailing": false,
"symbolRequired": false,
},
"fetchOrders": nil,
"fetchClosedOrders": map[string]interface{} {
"marginMode": false,
"limit": nil,
"daysBack": nil,
"daysBackCanceled": nil,
"untilDays": nil,
"trigger": false,
"trailing": false,
"symbolRequired": false,
},
"fetchOHLCV": map[string]interface{} {
"limit": 5000,
},
},
"spot": nil,
"swap": map[string]interface{} {
"linear": map[string]interface{} {
"extends": "default",
},
"inverse": map[string]interface{} {
"extends": "default",
},
},
"future": map[string]interface{} {
"linear": map[string]interface{} {
"extends": "default",
},
"inverse": map[string]interface{} {
"extends": "default",
},
},
},
"timeframes": map[string]interface{} {
"1m": "1m",
"5m": "5m",
"15m": "15m",
"30m": "30m",
"1h": "1h",
"4h": "4h",
"12h": "12h",
"1d": "1d",
"1w": "1w",
},
})
}
/**
* @method
* @name krakenfutures#fetchMarkets
* @description Fetches the available trading markets from the exchange, Multi-collateral markets are returned as linear markets, but can be settled in multiple currencies
* @see https://docs.futures.kraken.com/#http-api-trading-v3-api-instrument-details-get-instruments
* @param {object} [params] exchange specific params
* @returns An array of market structures
*/
func (this *krakenfutures) FetchMarkets(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
params := GetArg(optionalArgs, 0, map[string]interface{} {})
_ = params
response:= (<-this.PublicGetInstruments(params))
PanicOnError(response)
//
// {
// "result": "success",
// "instruments": [
// {
// "symbol": "fi_ethusd_180928",
// "type": "futures_inverse", // futures_vanilla // spot index
// "underlying": "rr_ethusd",
// "lastTradingTime": "2018-09-28T15:00:00.000Z",
// "tickSize": 0.1,
// "contractSize": 1,
// "tradeable": true,
// "marginLevels": [
// {
// "contracts":0,
// "initialMargin":0.02,
// "maintenanceMargin":0.01
// },
// {
// "contracts":250000,
// "initialMargin":0.04,
// "maintenanceMargin":0.02
// },
// ...
// ],
// "isin": "GB00JVMLMP88",
// "retailMarginLevels": [
// {
// "contracts": 0,
// "initialMargin": 0.5,
// "maintenanceMargin": 0.25
// }
// ],
// "tags": [],
// },
// {
// "symbol": "in_xbtusd",
// "type": "spot index",
// "tradeable":false
// }
// ]
// "serverTime": "2018-07-19T11:32:39.433Z"
// }
//
var instruments interface{} = this.SafeValue(response, "instruments", []interface{}{})
var result interface{} = []interface{}{}
for i := 0; IsLessThan(i, GetArrayLength(instruments)); i++ {
var market interface{} = GetValue(instruments, i)
var id interface{} = this.SafeString(market, "symbol")
var marketType interface{} = this.SafeString(market, "type")
var typeVar interface{} = nil
var index interface{} = (IsGreaterThanOrEqual(GetIndexOf(marketType, " index"), 0))
var linear interface{} = nil
var inverse interface{} = nil
var expiry interface{} = nil
if !IsTrue(index) {
linear = (IsGreaterThanOrEqual(GetIndexOf(marketType, "_vanilla"), 0))
inverse = !IsTrue(linear)
var settleTime interface{} = this.SafeString(market, "lastTradingTime")
typeVar = Ternary(IsTrue((IsEqual(settleTime, nil))), "swap", "future")
expiry = this.Parse8601(settleTime)
} else {
typeVar = "index"
}
var swap interface{} = (IsEqual(typeVar, "swap"))
var future interface{} = (IsEqual(typeVar, "future"))
var symbol interface{} = id
var split interface{} = Split(id, "_")
var splitMarket interface{} = this.SafeString(split, 1)
var baseId interface{} = Slice(splitMarket, 0, Subtract(GetLength(splitMarket), 3))
var quoteId interface{} = "usd" // always USD
var base interface{} = this.SafeCurrencyCode(baseId)
var quote interface{} = this.SafeCurrencyCode(quoteId)
// swap == perpetual
var settle interface{} = nil
var settleId interface{} = nil
var cvtp interface{} = this.SafeString(market, "contractValueTradePrecision")
var amountPrecision interface{} = this.ParseNumber(this.IntegerPrecisionToAmount(cvtp))
var pricePrecision interface{} = this.SafeNumber(market, "tickSize")
var contract interface{} = (IsTrue(IsTrue(swap) || IsTrue(future)) || IsTrue(index))
var swapOrFutures interface{} = (IsTrue(swap) || IsTrue(future))
if IsTrue(swapOrFutures) {
var exchangeType interface{} = this.SafeString(market, "type")
if IsTrue(IsEqual(exchangeType, "futures_inverse")) {
settle = base
settleId = baseId
inverse = true
} else {
settle = quote
settleId = quoteId
inverse = false
}
linear = !IsTrue(inverse)
symbol = Add(Add(Add(Add(base, "/"), quote), ":"), settle)
if IsTrue(future) {
symbol = Add(Add(symbol, "-"), this.Yymmdd(expiry))
}
}
AppendToArray(&result,map[string]interface{} {
"id": id,
"symbol": symbol,
"base": base,
"quote": quote,
"settle": settle,
"baseId": baseId,
"quoteId": quoteId,
"settleId": settleId,
"type": typeVar,
"spot": false,
"margin": false,
"swap": swap,
"future": future,
"option": false,
"index": index,
"active": nil,
"contract": contract,
"linear": linear,
"inverse": inverse,
"contractSize": this.SafeNumber(market, "contractSize"),
"maintenanceMarginRate": nil,
"expiry": expiry,
"expiryDatetime": this.Iso8601(expiry),
"strike": nil,
"optionType": nil,
"precision": map[string]interface{} {
"amount": amountPrecision,
"price": pricePrecision,
},
"limits": map[string]interface{} {
"leverage": map[string]interface{} {
"min": nil,
"max": nil,
},
"amount": map[string]interface{} {
"min": nil,
"max": nil,
},
"price": map[string]interface{} {
"min": nil,
"max": nil,
},
"cost": map[string]interface{} {
"min": nil,
"max": nil,
},
},
"created": this.Parse8601(this.SafeString(market, "openingDate")),
"info": market,
})
}
var settlementCurrencies interface{} = GetValue(GetValue(this.Options, "settlementCurrencies"), "flex")
var currencies interface{} = []interface{}{}
for i := 0; IsLessThan(i, GetArrayLength(settlementCurrencies)); i++ {
var code interface{} = GetValue(settlementCurrencies, i)
AppendToArray(&currencies,map[string]interface{} {
"id": ToLower(code),
"numericId": nil,
"code": code,
"precision": nil,
})
}
this.Currencies = this.DeepExtend(currencies, this.Currencies)
ch <- result
return nil
}()
return ch
}
/**
* @method
* @name krakenfutures#fetchOrderBook
* @see https://docs.futures.kraken.com/#http-api-trading-v3-api-market-data-get-orderbook
* @description Fetches a list of open orders in a market
* @param {string} symbol Unified market symbol
* @param {int} [limit] Not used by krakenfutures
* @param {object} [params] exchange specific params
* @returns An [order book structure]{@link https://docs.ccxt.com/#/?id=order-book-structure}
*/
func (this *krakenfutures) FetchOrderBook(symbol interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
limit := GetArg(optionalArgs, 0, nil)
_ = limit
params := GetArg(optionalArgs, 1, map[string]interface{} {})
_ = params
retRes5448 := (<-this.LoadMarkets())
PanicOnError(retRes5448)
var market interface{} = this.Market(symbol)
var request interface{} = map[string]interface{} {
"symbol": GetValue(market, "id"),
}
response:= (<-this.PublicGetOrderbook(this.Extend(request, params)))
PanicOnError(response)
//
// {
// "result": "success",
// "serverTime": "2016-02-25T09:45:53.818Z",
// "orderBook": {
// "bids": [
// [
// 4213,
// 2000,
// ],
// [
// 4210,
// 4000,
// ],
// ...
// ],
// "asks": [
// [
// 4218,
// 4000,
// ],
// [
// 4220,
// 5000,
// ],
// ...
// ],
// },
// }
//
var timestamp interface{} = this.Parse8601(GetValue(response, "serverTime"))
ch <- this.ParseOrderBook(GetValue(response, "orderBook"), symbol, timestamp)
return nil
}()
return ch
}
/**
* @method
* @name krakenfutures#fetchTickers
* @description fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
* @see https://docs.futures.kraken.com/#http-api-trading-v3-api-market-data-get-tickers
* @param {string[]} symbols unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} an array of [ticker structures]{@link https://docs.ccxt.com/#/?id=ticker-structure}
*/
func (this *krakenfutures) FetchTickers(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
symbols := GetArg(optionalArgs, 0, nil)
_ = symbols
params := GetArg(optionalArgs, 1, map[string]interface{} {})
_ = params
retRes5948 := (<-this.LoadMarkets())
PanicOnError(retRes5948)
response:= (<-this.PublicGetTickers(params))
PanicOnError(response)
//
// {
// "result": "success",
// "tickers": [
// {
// "tag": 'semiannual', // 'month', 'quarter', "perpetual", "semiannual",
// "pair": "ETH:USD",
// "symbol": "fi_ethusd_220624",
// "markPrice": "2925.72",
// "bid": "2923.8",
// "bidSize": "16804",
// "ask": "2928.65",
// "askSize": "1339",
// "vol24h": "860493",
// "openInterest": "3023363.00000000",
// "open24h": "3021.25",
// "indexPrice": "2893.71",
// "last": "2942.25",
// "lastTime": "2022-02-18T14:08:15.578Z",
// "lastSize": "151",
// "suspended": false
// },
// {
// "symbol": "in_xbtusd", // "rr_xbtusd",
// "last": "40411",
// "lastTime": "2022-02-18T14:16:28.000Z"
// },
// ...
// ],
// "serverTime": "2022-02-18T14:16:29.440Z"
// }
//
var tickers interface{} = this.SafeList(response, "tickers")
ch <- this.ParseTickers(tickers, symbols)
return nil
}()
return ch
}
func (this *krakenfutures) ParseTicker(ticker interface{}, optionalArgs ...interface{}) interface{} {
//
// {
// "tag": 'semiannual', // 'month', 'quarter', "perpetual", "semiannual",
// "pair": "ETH:USD",
// "symbol": "fi_ethusd_220624",
// "markPrice": "2925.72",
// "bid": "2923.8",
// "bidSize": "16804",
// "ask": "2928.65",
// "askSize": "1339",
// "vol24h": "860493",
// "openInterest": "3023363.00000000",
// "open24h": "3021.25",
// "indexPrice": "2893.71",
// "last": "2942.25",
// "lastTime": "2022-02-18T14:08:15.578Z",
// "lastSize": "151",
// "suspended": false
// }
//
// {
// "symbol": "in_xbtusd", // "rr_xbtusd",
// "last": "40411",
// "lastTime": "2022-02-18T14:16:28.000Z"
// }
//
market := GetArg(optionalArgs, 0, nil)
_ = market
var marketId interface{} = this.SafeString(ticker, "symbol")
market = this.SafeMarket(marketId, market)
var symbol interface{} = GetValue(market, "symbol")
var timestamp interface{} = this.Parse8601(this.SafeString(ticker, "lastTime"))
var open interface{} = this.SafeString(ticker, "open24h")
var last interface{} = this.SafeString(ticker, "last")
var change interface{} = Precise.StringSub(last, open)
var percentage interface{} = Precise.StringMul(Precise.StringDiv(change, open), "100")
var average interface{} = Precise.StringDiv(Precise.StringAdd(open, last), "2")
var volume interface{} = this.SafeString(ticker, "vol24h")
var baseVolume interface{} = nil
var quoteVolume interface{} = nil
var isIndex interface{} = this.SafeBool(market, "index", false)
if !IsTrue(isIndex) {
if IsTrue(GetValue(market, "linear")) {
baseVolume = volume
} else if IsTrue(GetValue(market, "inverse")) {
quoteVolume = volume
}
}
return this.SafeTicker(map[string]interface{} {
"symbol": symbol,
"timestamp": timestamp,
"datetime": this.Iso8601(timestamp),
"high": nil,
"low": nil,
"bid": this.SafeString(ticker, "bid"),
"bidVolume": this.SafeString(ticker, "bidSize"),
"ask": this.SafeString(ticker, "ask"),
"askVolume": this.SafeString(ticker, "askSize"),
"vwap": nil,
"open": open,
"close": last,
"last": last,
"previousClose": nil,
"change": change,
"percentage": percentage,
"average": average,
"baseVolume": baseVolume,
"quoteVolume": quoteVolume,
"markPrice": this.SafeString(ticker, "markPrice"),
"indexPrice": this.SafeString(ticker, "indexPrice"),
"info": ticker,
})
}
/**
* @method
* @name krakenfutures#fetchOHLCV
* @see https://docs.futures.kraken.com/#http-api-charts-candles
* @description fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
* @param {string} symbol unified symbol of the market to fetch OHLCV data for
* @param {string} timeframe the length of time each candle represents
* @param {int} [since] timestamp in ms of the earliest candle to fetch
* @param {int} [limit] the maximum amount of candles to fetch
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
* @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
*/
func (this *krakenfutures) FetchOHLCV(symbol interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
timeframe := GetArg(optionalArgs, 0, "1m")
_ = timeframe
since := GetArg(optionalArgs, 1, nil)
_ = since
limit := GetArg(optionalArgs, 2, nil)
_ = limit
params := GetArg(optionalArgs, 3, map[string]interface{} {})
_ = params
retRes7198 := (<-this.LoadMarkets())
PanicOnError(retRes7198)
var market interface{} = this.Market(symbol)
var paginate interface{} = false
paginateparamsVariable := this.HandleOptionAndParams(params, "fetchOHLCV", "paginate");
paginate = GetValue(paginateparamsVariable,0);
params = GetValue(paginateparamsVariable,1)
if IsTrue(paginate) {
retRes72419 := (<-this.FetchPaginatedCallDeterministic("fetchOHLCV", symbol, since, limit, timeframe, params, 5000))
PanicOnError(retRes72419)
ch <- retRes72419
return nil
}
var request interface{} = map[string]interface{} {
"symbol": GetValue(market, "id"),
"price_type": this.SafeString(params, "price", "trade"),
"interval": GetValue(this.Timeframes, timeframe),
}
params = this.Omit(params, "price")
if IsTrue(!IsEqual(since, nil)) {
var duration interface{} = this.ParseTimeframe(timeframe)
AddElementToObject(request, "from", this.ParseToInt(Divide(since, 1000)))
if IsTrue(IsEqual(limit, nil)) {
limit = 5000
}
limit = mathMin(limit, 5000)
var toTimestamp interface{} = this.Sum(GetValue(request, "from"), Subtract(Multiply(limit, duration), 1))
var currentTimestamp interface{} = this.Seconds()
AddElementToObject(request, "to", mathMin(toTimestamp, currentTimestamp))
} else if IsTrue(!IsEqual(limit, nil)) {
limit = mathMin(limit, 5000)
var duration interface{} = this.ParseTimeframe(timeframe)
AddElementToObject(request, "to", this.Seconds())
AddElementToObject(request, "from", this.ParseToInt(Subtract(GetValue(request, "to"), (Multiply(duration, limit)))))
}
response:= (<-this.ChartsGetPriceTypeSymbolInterval(this.Extend(request, params)))
PanicOnError(response)
//
// {
// "candles": [
// {
// "time": 1645198500000,
// "open": "309.15000000000",
// "high": "309.15000000000",
// "low": "308.70000000000",
// "close": "308.85000000000",
// "volume": 0
// }
// ],
// "more_candles": true
// }
//
var candles interface{} = this.SafeList(response, "candles")
ch <- this.ParseOHLCVs(candles, market, timeframe, since, limit)
return nil
}()
return ch
}
func (this *krakenfutures) ParseOHLCV(ohlcv interface{}, optionalArgs ...interface{}) interface{} {
//
// {
// "time": 1645198500000,
// "open": "309.15000000000",
// "high": "309.15000000000",
// "low": "308.70000000000",
// "close": "308.85000000000",
// "volume": 0
// }
//
market := GetArg(optionalArgs, 0, nil)
_ = market
return []interface{}{this.SafeInteger(ohlcv, "time"), this.SafeNumber(ohlcv, "open"), this.SafeNumber(ohlcv, "high"), this.SafeNumber(ohlcv, "low"), this.SafeNumber(ohlcv, "close"), this.SafeNumber(ohlcv, "volume")}
}
/**
* @method
* @name krakenfutures#fetchTrades
* @see https://docs.futures.kraken.com/#http-api-trading-v3-api-market-data-get-trade-history
* @see https://docs.futures.kraken.com/#http-api-history-market-history-get-public-execution-events
* @description Fetch a history of filled trades that this account has made
* @param {string} symbol Unified CCXT market symbol
* @param {int} [since] Timestamp in ms of earliest trade. Not used by krakenfutures except in combination with params.until
* @param {int} [limit] Total number of trades, cannot exceed 100
* @param {object} [params] Exchange specific params
* @param {int} [params.until] Timestamp in ms of latest trade
* @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
* @param {string} [params.method] The method to use to fetch trades. Can be 'historyGetMarketSymbolExecutions' or 'publicGetHistory' default is 'historyGetMarketSymbolExecutions'
* @returns An array of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
*/
func (this *krakenfutures) FetchTrades(symbol interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
since := GetArg(optionalArgs, 0, nil)
_ = since
limit := GetArg(optionalArgs, 1, nil)
_ = limit
params := GetArg(optionalArgs, 2, map[string]interface{} {})
_ = params
retRes8058 := (<-this.LoadMarkets())
PanicOnError(retRes8058)
var paginate interface{} = false
paginateparamsVariable := this.HandleOptionAndParams(params, "fetchTrades", "paginate");
paginate = GetValue(paginateparamsVariable,0);
params = GetValue(paginateparamsVariable,1)
if IsTrue(paginate) {
retRes80919 := (<-this.FetchPaginatedCallDynamic("fetchTrades", symbol, since, limit, params))
PanicOnError(retRes80919)
ch <- retRes80919
return nil
}
var market interface{} = this.Market(symbol)
var request interface{} = map[string]interface{} {
"symbol": GetValue(market, "id"),
}
var method interface{} = nil
methodparamsVariable := this.HandleOptionAndParams(params, "fetchTrades", "method", "historyGetMarketSymbolExecutions");
method = GetValue(methodparamsVariable,0);
params = GetValue(methodparamsVariable,1)
var rawTrades interface{} = nil
var isFullHistoryEndpoint interface{} = (IsEqual(method, "historyGetMarketSymbolExecutions"))
if IsTrue(isFullHistoryEndpoint) {
requestparamsVariable := this.HandleUntilOption("before", request, params);
request = GetValue(requestparamsVariable,0);
params = GetValue(requestparamsVariable,1)
if IsTrue(!IsEqual(since, nil)) {
AddElementToObject(request, "since", since)
AddElementToObject(request, "sort", "asc")
}
if IsTrue(!IsEqual(limit, nil)) {
AddElementToObject(request, "count", limit)
}
response:= (<-this.HistoryGetMarketSymbolExecutions(this.Extend(request, params)))
PanicOnError(response)
//
// {
// "elements": [
// {
// "uid": "a5105030-f054-44cc-98ab-30d5cae96bef",
// "timestamp": "1710150778607",
// "event": {
// "Execution": {
// "execution": {
// "uid": "2d485b71-cd28-4a1e-9364-371a127550d2",
// "makerOrder": {
// "uid": "0a25f66b-1109-49ec-93a3-d17bf9e9137e",
// "tradeable": "PF_XBTUSD",
// "direction": "Buy",
// "quantity": "0.26500",
// "timestamp": "1710150778570",
// "limitPrice": "71907",
// "orderType": "Post",
// "reduceOnly": false,
// "lastUpdateTimestamp": "1710150778570"
// },
// "takerOrder": {
// "uid": "04de3ee0-9125-4960-bf8f-f63b577b6790",
// "tradeable": "PF_XBTUSD",
// "direction": "Sell",
// "quantity": "0.0002",
// "timestamp": "1710150778607",
// "limitPrice": "71187.00",
// "orderType": "Market",
// "reduceOnly": false,
// "lastUpdateTimestamp": "1710150778607"
// },
// "timestamp": "1710150778607",
// "quantity": "0.0002",
// "price": "71907",
// "markPrice": "71903.32715463147",
// "limitFilled": false,
// "usdValue": "14.38"
// },
// "takerReducedQuantity": ""
// }
// }
// },
// ... followed by older items
// ],
// "len": "1000",
// "continuationToken": "QTexMDE0OTe33NTcyXy8xNDIzAjc1NjY5MwI="
// }
//
var elements interface{} = this.SafeList(response, "elements", []interface{}{})
// we need to reverse the list to fix chronology
rawTrades = []interface{}{}
var length interface{} = GetArrayLength(elements)
for i := 0; IsLessThan(i, length); i++ {
var index interface{} = Subtract(Subtract(length, 1), i)
var element interface{} = GetValue(elements, index)
var event interface{} = this.SafeDict(element, "event", map[string]interface{} {})
var executionContainer interface{} = this.SafeDict(event, "Execution", map[string]interface{} {})
var rawTrade interface{} = this.SafeDict(executionContainer, "execution", map[string]interface{} {})
AppendToArray(&rawTrades,rawTrade)
}
} else {
requestparamsVariable := this.HandleUntilOption("lastTime", request, params);
request = GetValue(requestparamsVariable,0);
params = GetValue(requestparamsVariable,1)
response:= (<-this.PublicGetHistory(this.Extend(request, params)))
PanicOnError(response)
//
// {
// "result": "success",
// "history": [
// {
// "time": "2022-03-18T04:55:37.692Z",
// "trade_id": 100,
// "price": 0.7921,
// "size": 1068,
// "side": "sell",
// "type": "fill",
// "uid": "6c5da0b0-f1a8-483f-921f-466eb0388265"
// },
// ...
// ],
// "serverTime": "2022-03-18T06:39:18.056Z"
// }
//
rawTrades = this.SafeList(response, "history", []interface{}{})
}
ch <- this.ParseTrades(rawTrades, market, since, limit)
return nil
}()
return ch
}
func (this *krakenfutures) ParseTrade(trade interface{}, optionalArgs ...interface{}) interface{} {
//
// fetchTrades (recent trades)
//
// {
// "time": "2019-02-14T09:25:33.920Z",
// "trade_id": 100,
// "price": 3574,
// "size": 100,
// "side": "buy",
// "type": "fill" // fill, liquidation, assignment, termination
// "uid": "11c3d82c-9e70-4fe9-8115-f643f1b162d4"
// }
//
// fetchTrades (executions history)
//
// {
// "timestamp": "1710152516830",
// "price": "71927.0",
// "quantity": "0.0695",
// "markPrice": "71936.38701675525",
// "limitFilled": true,
// "usdValue": "4998.93",
// "uid": "116ae634-253f-470b-bd20-fa9d429fb8b1",
// "makerOrder": { "uid": "17bfe4de-c01e-4938-926c-617d2a2d0597", "tradeable": "PF_XBTUSD", "direction": "Buy", "quantity": "0.0695", "timestamp": "1710152515836", "limitPrice": "71927.0", "orderType": "Post", "reduceOnly": false, "lastUpdateTimestamp": "1710152515836" },
// "takerOrder": { "uid": "d3e437b4-aa70-4108-b5cf-b1eecb9845b5", "tradeable": "PF_XBTUSD", "direction": "Sell", "quantity": "0.940100", "timestamp": "1710152516830", "limitPrice": "71915", "orderType": "IoC", "reduceOnly": false, "lastUpdateTimestamp": "1710152516830" }
// }
//
// fetchMyTrades (private)
//
// {
// "fillTime": "2016-02-25T09:47:01.000Z",
// "order_id": "c18f0c17-9971-40e6-8e5b-10df05d422f0",
// "fill_id": "522d4e08-96e7-4b44-9694-bfaea8fe215e",
// "cliOrdId": "d427f920-ec55-4c18-ba95-5fe241513b30", // OPTIONAL
// "symbol": "fi_xbtusd_180615",
// "side": "buy",
// "size": 2000,
// "price": 4255,
// "fillType": "maker" // taker, takerAfterEdit, maker, liquidation, assignee
// }
//
// execution report (createOrder, editOrder)
//
// {
// "executionId": "e1ec9f63-2338-4c44-b40a-43486c6732d7",
// "price": 7244.5,
// "amount": 10,
// "orderPriorEdit": null,
// "orderPriorExecution": {
// "orderId": "61ca5732-3478-42fe-8362-abbfd9465294",
// "cliOrdId": null,
// "type": "lmt",
// "symbol": "pi_xbtusd",
// "side": "buy",
// "quantity": 10,
// "filled": 0,
// "limitPrice": 7500,
// "reduceOnly": false,
// "timestamp": "2019-12-11T17:17:33.888Z",
// "lastUpdateTimestamp": "2019-12-11T17:17:33.888Z"
// },
// "takerReducedQuantity": null,
// "type": "EXECUTION"
// }
//
market := GetArg(optionalArgs, 0, nil)
_ = market
var timestamp interface{} = this.Parse8601(this.SafeString2(trade, "time", "fillTime"))
var price interface{} = this.SafeString(trade, "price")
var amount interface{} = this.SafeStringN(trade, []interface{}{"size", "amount", "quantity"}, "0.0")
var id interface{} = this.SafeString2(trade, "uid", "fill_id")
if IsTrue(IsEqual(id, nil)) {
id = this.SafeString(trade, "executionId")
}
var order interface{} = this.SafeString(trade, "order_id")
var marketId interface{} = this.SafeString(trade, "symbol")
var side interface{} = this.SafeString(trade, "side")
var typeVar interface{} = nil
var priorEdit interface{} = this.SafeValue(trade, "orderPriorEdit")
var priorExecution interface{} = this.SafeValue(trade, "orderPriorExecution")
if IsTrue(!IsEqual(priorExecution, nil)) {
order = this.SafeString(priorExecution, "orderId")
marketId = this.SafeString(priorExecution, "symbol")
side = this.SafeString(priorExecution, "side")
typeVar = this.SafeString(priorExecution, "type")
} else if IsTrue(!IsEqual(priorEdit, nil)) {
order = this.SafeString(priorEdit, "orderId")
marketId = this.SafeString(priorEdit, "symbol")
side = this.SafeString(priorEdit, "type")
typeVar = this.SafeString(priorEdit, "type")
}
if IsTrue(!IsEqual(typeVar, nil)) {
typeVar = this.ParseOrderType(typeVar)
}
market = this.SafeMarket(marketId, market)
var cost interface{} = nil
var linear interface{} = this.SafeBool(market, "linear")
if IsTrue(IsTrue(IsTrue((!IsEqual(amount, nil))) && IsTrue((!IsEqual(price, nil)))) && IsTrue((!IsEqual(market, nil)))) {
if IsTrue(linear) {
cost = Precise.StringMul(amount, price) // in quote
} else {
cost = Precise.StringDiv(amount, price) // in base
}
var contractSize interface{} = this.SafeString(market, "contractSize")
cost = Precise.StringMul(cost, contractSize)
}
var takerOrMaker interface{} = nil
var fillType interface{} = this.SafeString(trade, "fillType")
if IsTrue(!IsEqual(fillType, nil)) {
if IsTrue(IsGreaterThanOrEqual(GetIndexOf(fillType, "taker"), 0)) {
takerOrMaker = "taker"
} else if IsTrue(IsGreaterThanOrEqual(GetIndexOf(fillType, "maker"), 0)) {
takerOrMaker = "maker"
}
}
var isHistoricalExecution interface{} = (InOp(trade, "takerOrder"))
if IsTrue(isHistoricalExecution) {
timestamp = this.SafeInteger(trade, "timestamp")
var taker interface{} = this.SafeDict(trade, "takerOrder", map[string]interface{} {})
if IsTrue(!IsEqual(taker, nil)) {
side = this.SafeStringLower(taker, "direction")
takerOrMaker = "taker"
}
}
return this.SafeTrade(map[string]interface{} {
"info": trade,
"id": id,
"symbol": this.SafeString(market, "symbol"),
"timestamp": timestamp,
"datetime": this.Iso8601(timestamp),
"order": order,
"type": typeVar,
"side": side,
"takerOrMaker": takerOrMaker,
"price": price,
"amount": Ternary(IsTrue(linear), amount, nil),
"cost": cost,
"fee": nil,
})
}
func (this *krakenfutures) CreateOrderRequest(symbol interface{}, typeVar interface{}, side interface{}, amount interface{}, optionalArgs ...interface{}) interface{} {
price := GetArg(optionalArgs, 0, nil)
_ = price
params := GetArg(optionalArgs, 1, map[string]interface{} {})
_ = params
var market interface{} = this.Market(symbol)
symbol = GetValue(market, "symbol")
typeVar = this.SafeString(params, "orderType", typeVar)
var timeInForce interface{} = this.SafeString(params, "timeInForce")
var postOnly interface{} = false
postOnlyparamsVariable := this.HandlePostOnly(IsEqual(typeVar, "market"), IsEqual(typeVar, "post"), params);
postOnly = GetValue(postOnlyparamsVariable,0);
params = GetValue(postOnlyparamsVariable,1)
if IsTrue(postOnly) {
typeVar = "post"
} else if IsTrue(IsEqual(timeInForce, "ioc")) {
typeVar = "ioc"
} else if IsTrue(IsEqual(typeVar, "limit")) {
typeVar = "lmt"
} else if IsTrue(IsEqual(typeVar, "market")) {
typeVar = "mkt"
}
var request interface{} = map[string]interface{} {
"symbol": GetValue(market, "id"),
"side": side,
"size": this.AmountToPrecision(symbol, amount),
}
var clientOrderId interface{} = this.SafeString2(params, "clientOrderId", "cliOrdId")
if IsTrue(!IsEqual(clientOrderId, nil)) {
AddElementToObject(request, "cliOrdId", clientOrderId)
}
var triggerPrice interface{} = this.SafeString2(params, "triggerPrice", "stopPrice")
var isTriggerOrder interface{} = !IsEqual(triggerPrice, nil)
var stopLossTriggerPrice interface{} = this.SafeString(params, "stopLossPrice")
var takeProfitTriggerPrice interface{} = this.SafeString(params, "takeProfitPrice")
var isStopLossTriggerOrder interface{} = !IsEqual(stopLossTriggerPrice, nil)
var isTakeProfitTriggerOrder interface{} = !IsEqual(takeProfitTriggerPrice, nil)
var isStopLossOrTakeProfitTrigger interface{} = IsTrue(isStopLossTriggerOrder) || IsTrue(isTakeProfitTriggerOrder)
var triggerSignal interface{} = this.SafeString(params, "triggerSignal", "last")
var reduceOnly interface{} = this.SafeValue(params, "reduceOnly")
if IsTrue(IsTrue(isStopLossOrTakeProfitTrigger) || IsTrue(isTriggerOrder)) {
AddElementToObject(request, "triggerSignal", triggerSignal)
}
if IsTrue(isTriggerOrder) {
typeVar = "stp"
AddElementToObject(request, "stopPrice", this.PriceToPrecision(symbol, triggerPrice))
} else if IsTrue(isStopLossOrTakeProfitTrigger) {
reduceOnly = true
if IsTrue(isStopLossTriggerOrder) {
typeVar = "stp"
AddElementToObject(request, "stopPrice", this.PriceToPrecision(symbol, stopLossTriggerPrice))
} else if IsTrue(isTakeProfitTriggerOrder) {
typeVar = "take_profit"
AddElementToObject(request, "stopPrice", this.PriceToPrecision(symbol, takeProfitTriggerPrice))
}
}
if IsTrue(reduceOnly) {
AddElementToObject(request, "reduceOnly", true)
}
AddElementToObject(request, "orderType", typeVar)
if IsTrue(!IsEqual(price, nil)) {
AddElementToObject(request, "limitPrice", this.PriceToPrecision(symbol, price))
}
params = this.Omit(params, []interface{}{"clientOrderId", "timeInForce", "triggerPrice", "stopLossPrice", "takeProfitPrice"})
return this.Extend(request, params)
}
/**
* @method
* @name krakenfutures#createOrder
* @description Create an order on the exchange
* @see https://docs.kraken.com/api/docs/futures-api/trading/send-order
* @param {string} symbol unified market symbol
* @param {string} type 'limit' or 'market'
* @param {string} side 'buy' or 'sell'
* @param {float} amount number of contracts
* @param {float} [price] limit order price
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {bool} [params.reduceOnly] set as true if you wish the order to only reduce an existing position, any order which increases an existing position will be rejected, default is false
* @param {bool} [params.postOnly] set as true if you wish to make a postOnly order, default is false
* @param {string} [params.clientOrderId] UUID The order identity that is specified from the user, It must be globally unique
* @param {float} [params.triggerPrice] the price that a stop order is triggered at
* @param {float} [params.stopLossPrice] the price that a stop loss order is triggered at
* @param {float} [params.takeProfitPrice] the price that a take profit order is triggered at
* @param {string} [params.triggerSignal] for triggerPrice, stopLossPrice and takeProfitPrice orders, the trigger price type, 'last', 'mark' or 'index', default is 'last'
* @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
func (this *krakenfutures) CreateOrder(symbol interface{}, typeVar interface{}, side interface{}, amount interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
price := GetArg(optionalArgs, 0, nil)
_ = price
params := GetArg(optionalArgs, 1, map[string]interface{} {})
_ = params
retRes11388 := (<-this.LoadMarkets())
PanicOnError(retRes11388)
var market interface{} = this.Market(symbol)
var orderRequest interface{} = this.CreateOrderRequest(symbol, typeVar, side, amount, price, params)
response:= (<-this.PrivatePostSendorder(orderRequest))
PanicOnError(response)
//
// {
// "result": "success",
// "sendStatus": {
// "order_id": "salf320-e337-47ac-b345-30sdfsalj",
// "status": "placed",
// "receivedTime": "2022-02-28T19:32:17.122Z",
// "orderEvents": [
// {
// "order": {
// "orderId": "salf320-e337-47ac-b345-30sdfsalj",
// "cliOrdId": null,
// "type": "lmt",
// "symbol": "pi_xrpusd",
// "side": "buy",
// "quantity": 1,
// "filled": 0,
// "limitPrice": 0.7,
// "reduceOnly": false,
// "timestamp": "2022-02-28T19:32:17.122Z",
// "lastUpdateTimestamp": "2022-02-28T19:32:17.122Z"
// },
// "reducedQuantity": null,
// "type": "PLACE"
// }
// ]
// },
// "serverTime": "2022-02-28T19:32:17.122Z"
// }
//
var sendStatus interface{} = this.SafeValue(response, "sendStatus")
var status interface{} = this.SafeString(sendStatus, "status")
this.VerifyOrderActionSuccess(status, "createOrder", []interface{}{"filled"})
ch <- this.ParseOrder(sendStatus, market)
return nil
}()
return ch
}
/**
* @method
* @name krakenfutures#createOrders
* @description create a list of trade orders
* @see https://docs.kraken.com/api/docs/futures-api/trading/send-batch-order
* @param {Array} orders list of orders to create, each object should contain the parameters required by createOrder, namely symbol, type, side, amount, price and params
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
func (this *krakenfutures) CreateOrders(orders interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
params := GetArg(optionalArgs, 0, map[string]interface{} {})
_ = params
retRes11888 := (<-this.LoadMarkets())
PanicOnError(retRes11888)
var ordersRequests interface{} = []interface{}{}
for i := 0; IsLessThan(i, GetArrayLength(orders)); i++ {
var rawOrder interface{} = GetValue(orders, i)
var marketId interface{} = this.SafeString(rawOrder, "symbol")
var typeVar interface{} = this.SafeString(rawOrder, "type")
var side interface{} = this.SafeString(rawOrder, "side")
var amount interface{} = this.SafeValue(rawOrder, "amount")
var price interface{} = this.SafeValue(rawOrder, "price")
var orderParams interface{} = this.SafeValue(rawOrder, "params", map[string]interface{} {})
var extendedParams interface{} = this.Extend(orderParams, params) // the request does not accept extra params since it's a list, so we're extending each order with the common params
if !IsTrue((InOp(extendedParams, "order_tag"))) {
// order tag is mandatory so we will generate one if not provided
AddElementToObject(extendedParams, "order_tag", ToString(this.Sum(i, 1))) // sequential counter
}
AddElementToObject(extendedParams, "order", "send")
var orderRequest interface{} = this.CreateOrderRequest(marketId, typeVar, side, amount, price, extendedParams)
AppendToArray(&ordersRequests,orderRequest)
}
var request interface{} = map[string]interface{} {
"batchOrder": ordersRequests,
}
response:= (<-this.PrivatePostBatchorder(this.Extend(request, params)))
PanicOnError(response)
//
// {
// "result": "success",
// "serverTime": "2023-10-24T08:40:57.339Z",
// "batchStatus": [
// {
// "status": "requiredArgumentMissing",
// "orderEvents": []
// },
// {
// "status": "requiredArgumentMissing",
// "orderEvents": []
// }
// ]
// }
//
var data interface{} = this.SafeList(response, "batchStatus", []interface{}{})
ch <- this.ParseOrders(data)
return nil
}()
return ch
}
/**
* @method
* @name krakenfutures#editOrder
* @see https://docs.futures.kraken.com/#http-api-trading-v3-api-order-management-edit-order
* @description Edit an open order on the exchange
* @param {string} id order id
* @param {string} symbol Not used by Krakenfutures
* @param {string} type Not used by Krakenfutures
* @param {string} side Not used by Krakenfutures
* @param {float} amount Order size
* @param {float} [price] Price to fill order at
* @param {object} [params] Exchange specific params
* @returns An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
func (this *krakenfutures) EditOrder(id interface{}, symbol interface{}, typeVar interface{}, side interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
amount := GetArg(optionalArgs, 0, nil)
_ = amount
price := GetArg(optionalArgs, 1, nil)
_ = price
params := GetArg(optionalArgs, 2, map[string]interface{} {})
_ = params
retRes12468 := (<-this.LoadMarkets())
PanicOnError(retRes12468)
var request interface{} = map[string]interface{} {
"orderId": id,
}
if IsTrue(!IsEqual(amount, nil)) {
AddElementToObject(request, "size", amount)
}
if IsTrue(!IsEqual(price, nil)) {
AddElementToObject(request, "limitPrice", price)
}
response:= (<-this.PrivatePostEditorder(this.Extend(request, params)))
PanicOnError(response)
var status interface{} = this.SafeString(GetValue(response, "editStatus"), "status")
this.VerifyOrderActionSuccess(status, "editOrder", []interface{}{"filled"})
var order interface{} = this.ParseOrder(GetValue(response, "editStatus"))
AddElementToObject(order, "info", response)
ch <- order
return nil
}()
return ch
}
/**
* @method
* @name krakenfutures#cancelOrder
* @see https://docs.futures.kraken.com/#http-api-trading-v3-api-order-management-cancel-order
* @description Cancel an open order on the exchange
* @param {string} id Order id
* @param {string} symbol Not used by Krakenfutures
* @param {object} [params] Exchange specific params
* @returns An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
func (this *krakenfutures) CancelOrder(id interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
symbol := GetArg(optionalArgs, 0, nil)
_ = symbol
params := GetArg(optionalArgs, 1, map[string]interface{} {})
_ = params
retRes12758 := (<-this.LoadMarkets())
PanicOnError(retRes12758)
response:= (<-this.PrivatePostCancelorder(this.Extend(map[string]interface{} {
"order_id": id,
}, params)))
PanicOnError(response)
var status interface{} = this.SafeString(this.SafeValue(response, "cancelStatus", map[string]interface{} {}), "status")
this.VerifyOrderActionSuccess(status, "cancelOrder")
var order interface{} = map[string]interface{} {}
if IsTrue(InOp(response, "cancelStatus")) {
order = this.ParseOrder(GetValue(response, "cancelStatus"))
}
ch <- this.Extend(map[string]interface{} {
"info": response,
}, order)
return nil
}()
return ch
}
/**
* @method
* @name krakenfutures#cancelOrders
* @description cancel multiple orders
* @see https://docs.futures.kraken.com/#http-api-trading-v3-api-order-management-batch-order-management
* @param {string[]} ids order ids
* @param {string} [symbol] unified market symbol
* @param {object} [params] extra parameters specific to the exchange API endpoint
*
* EXCHANGE SPECIFIC PARAMETERS
* @param {string[]} [params.clientOrderIds] max length 10 e.g. ["my_id_1","my_id_2"]
* @returns {object} an list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
func (this *krakenfutures) CancelOrders(ids interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
symbol := GetArg(optionalArgs, 0, nil)
_ = symbol
params := GetArg(optionalArgs, 1, map[string]interface{} {})
_ = params
retRes13008 := (<-this.LoadMarkets())
PanicOnError(retRes13008)
var orders interface{} = []interface{}{}
var clientOrderIds interface{} = this.SafeValue(params, "clientOrderIds", []interface{}{})
var clientOrderIdsLength interface{} = GetArrayLength(clientOrderIds)
if IsTrue(IsGreaterThan(clientOrderIdsLength, 0)) {
for i := 0; IsLessThan(i, GetArrayLength(clientOrderIds)); i++ {
AppendToArray(&orders,map[string]interface{} {
"order": "cancel",
"cliOrdId": GetValue(clientOrderIds, i),
})
}
} else {
for i := 0; IsLessThan(i, GetArrayLength(ids)); i++ {
AppendToArray(&orders,map[string]interface{} {
"order": "cancel",
"order_id": GetValue(ids, i),
})
}
}
var request interface{} = map[string]interface{} {
"batchOrder": orders,
}
response:= (<-this.PrivatePostBatchorder(this.Extend(request, params)))
PanicOnError(response)
// {
// "result": "success",
// "serverTime": "2023-10-23T16:36:51.327Z",
// "batchStatus": [
// {
// "status": "cancelled",
// "order_id": "101c2327-f12e-45f2-8445-7502b87afc0b",
// "orderEvents": [
// {
// "uid": "101c2327-f12e-45f2-8445-7502b87afc0b",
// "order": {
// "orderId": "101c2327-f12e-45f2-8445-7502b87afc0b",
// "cliOrdId": null,
// "type": "lmt",
// "symbol": "PF_LTCUSD",
// "side": "buy",
// "quantity": "0.10000000000",
// "filled": "0E-11",
// "limitPrice": "50.00000000000",
// "reduceOnly": false,
// "timestamp": "2023-10-20T10:29:13.005Z",
// "lastUpdateTimestamp": "2023-10-20T10:29:13.005Z"
// },
// "type": "CANCEL"
// }
// ]
// }
// ]
// }
var batchStatus interface{} = this.SafeList(response, "batchStatus", []interface{}{})
ch <- this.ParseOrders(batchStatus)
return nil
}()
return ch
}
/**
* @method
* @name krakenfutures#cancelAllOrders
* @see https://docs.futures.kraken.com/#http-api-trading-v3-api-order-management-cancel-all-orders
* @description Cancels all orders on the exchange, including trigger orders
* @param {str} symbol Unified market symbol
* @param {dict} [params] Exchange specific params
* @returns Response from exchange api
*/
func (this *krakenfutures) CancelAllOrders(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
symbol := GetArg(optionalArgs, 0, nil)
_ = symbol
params := GetArg(optionalArgs, 1, map[string]interface{} {})
_ = params
var request interface{} = map[string]interface{} {}
if IsTrue(!IsEqual(symbol, nil)) {
AddElementToObject(request, "symbol", this.MarketId(symbol))
}
response:= (<-this.PrivatePostCancelallorders(this.Extend(request, params)))
PanicOnError(response)
//
// {
// result: 'success',
// cancelStatus: {
// receivedTime: '2024-06-06T01:12:44.814Z',
// cancelOnly: 'PF_XRPUSD',
// status: 'cancelled',
// cancelledOrders: [ { order_id: '272fd0ac-45c0-4003-b84d-d39b9e86bd36' } ],
// orderEvents: [
// {
// uid: '272fd0ac-45c0-4003-b84d-d39b9e86bd36',
// order: {
// orderId: '272fd0ac-45c0-4003-b84d-d39b9e86bd36',
// cliOrdId: null,
// type: 'lmt',
// symbol: 'PF_XRPUSD',
// side: 'buy',
// quantity: '10',
// filled: '0',
// limitPrice: '0.4',
// reduceOnly: false,
// timestamp: '2024-06-06T01:11:16.045Z',
// lastUpdateTimestamp: '2024-06-06T01:11:16.045Z'
// },
// type: 'CANCEL'
// }
// ]
// },
// serverTime: '2024-06-06T01:12:44.814Z'
// }
//
var cancelStatus interface{} = this.SafeDict(response, "cancelStatus")
var orderEvents interface{} = this.SafeList(cancelStatus, "orderEvents", []interface{}{})
var orders interface{} = []interface{}{}
for i := 0; IsLessThan(i, GetArrayLength(orderEvents)); i++ {
var orderEvent interface{} = this.SafeDict(orderEvents, 0)
var order interface{} = this.SafeDict(orderEvent, "order", map[string]interface{} {})
AppendToArray(&orders,order)
}
ch <- this.ParseOrders(orders)
return nil
}()
return ch
}
/**
* @method
* @name krakenfutures#cancelAllOrdersAfter
* @description dead man's switch, cancel all orders after the given timeout
* @see https://docs.futures.kraken.com/#http-api-trading-v3-api-order-management-dead-man-39-s-switch
* @param {number} timeout time in milliseconds, 0 represents cancel the timer
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} the api result
*/
func (this *krakenfutures) CancelAllOrdersAfter(timeout interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
params := GetArg(optionalArgs, 0, map[string]interface{} {})
_ = params
retRes14178 := (<-this.LoadMarkets())
PanicOnError(retRes14178)
var request interface{} = map[string]interface{} {
"timeout": Ternary(IsTrue((IsGreaterThan(timeout, 0))), (this.ParseToInt(Divide(timeout, 1000))), 0),
}
response:= (<-this.PrivatePostCancelallordersafter(this.Extend(request, params)))
PanicOnError(response)
//
// {
// "result": "success",
// "serverTime": "2018-06-19T16:51:23.839Z",
// "status": {
// "currentTime": "2018-06-19T16:51:23.839Z",
// "triggerTime": "0"
// }
// }
//
ch <- response
return nil
}()
return ch
}
/**
* @method
* @name krakenfutures#fetchOpenOrders
* @see https://docs.futures.kraken.com/#http-api-trading-v3-api-order-management-get-open-orders
* @description Gets all open orders, including trigger orders, for an account from the exchange api
* @param {string} symbol Unified market symbol
* @param {int} [since] Timestamp (ms) of earliest order. (Not used by kraken api but filtered internally by CCXT)
* @param {int} [limit] How many orders to return. (Not used by kraken api but filtered internally by CCXT)
* @param {object} [params] Exchange specific parameters
* @returns An array of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
func (this *krakenfutures) FetchOpenOrders(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
symbol := GetArg(optionalArgs, 0, nil)
_ = symbol
since := GetArg(optionalArgs, 1, nil)
_ = since
limit := GetArg(optionalArgs, 2, nil)
_ = limit
params := GetArg(optionalArgs, 3, map[string]interface{} {})
_ = params
retRes14478 := (<-this.LoadMarkets())
PanicOnError(retRes14478)
var market interface{} = nil
if IsTrue(!IsEqual(symbol, nil)) {
market = this.Market(symbol)
}
response:= (<-this.PrivateGetOpenorders(params))
PanicOnError(response)
var orders interface{} = this.SafeList(response, "openOrders", []interface{}{})
ch <- this.ParseOrders(orders, market, since, limit)
return nil
}()
return ch
}
/**
* @method
* @name krakenfutures#fetchClosedOrders
* @see https://docs.futures.kraken.com/#http-api-history-account-history-get-order-events
* @description Gets all closed orders, including trigger orders, for an account from the exchange api
* @param {string} symbol Unified market symbol
* @param {int} [since] Timestamp (ms) of earliest order.
* @param {int} [limit] How many orders to return.
* @param {object} [params] Exchange specific parameters
* @returns An array of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
func (this *krakenfutures) FetchClosedOrders(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
symbol := GetArg(optionalArgs, 0, nil)
_ = symbol
since := GetArg(optionalArgs, 1, nil)
_ = since
limit := GetArg(optionalArgs, 2, nil)
_ = limit
params := GetArg(optionalArgs, 3, map[string]interface{} {})
_ = params
retRes14698 := (<-this.LoadMarkets())
PanicOnError(retRes14698)
var market interface{} = nil
if IsTrue(!IsEqual(symbol, nil)) {
market = this.Market(symbol)
}
var request interface{} = map[string]interface{} {}
if IsTrue(!IsEqual(limit, nil)) {
AddElementToObject(request, "count", limit)
}
if IsTrue(!IsEqual(since, nil)) {
AddElementToObject(request, "from", since)
}
response:= (<-this.HistoryGetOrders(this.Extend(request, params)))
PanicOnError(response)
var allOrders interface{} = this.SafeList(response, "elements", []interface{}{})
var closedOrders interface{} = []interface{}{}
for i := 0; IsLessThan(i, GetArrayLength(allOrders)); i++ {
var order interface{} = GetValue(allOrders, i)
var event interface{} = this.SafeDict(order, "event", map[string]interface{} {})
var orderPlaced interface{} = this.SafeDict(event, "OrderPlaced")
if IsTrue(!IsEqual(orderPlaced, nil)) {
var innerOrder interface{} = this.SafeDict(orderPlaced, "order", map[string]interface{} {})
var filled interface{} = this.SafeString(innerOrder, "filled")
if IsTrue(!IsEqual(filled, "0")) {
AddElementToObject(innerOrder, "status", "closed") // status not available in the response
AppendToArray(&closedOrders,innerOrder)
}
}
}
ch <- this.ParseOrders(closedOrders, market, since, limit)
return nil
}()
return ch
}
/**
* @method
* @name krakenfutures#fetchCanceledOrders
* @see https://docs.futures.kraken.com/#http-api-history-account-history-get-order-events
* @description Gets all canceled orders, including trigger orders, for an account from the exchange api
* @param {string} symbol Unified market symbol
* @param {int} [since] Timestamp (ms) of earliest order.
* @param {int} [limit] How many orders to return.
* @param {object} [params] Exchange specific parameters
* @returns An array of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
func (this *krakenfutures) FetchCanceledOrders(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
symbol := GetArg(optionalArgs, 0, nil)
_ = symbol
since := GetArg(optionalArgs, 1, nil)
_ = since
limit := GetArg(optionalArgs, 2, nil)
_ = limit
params := GetArg(optionalArgs, 3, map[string]interface{} {})
_ = params
retRes15128 := (<-this.LoadMarkets())
PanicOnError(retRes15128)
var market interface{} = nil
if IsTrue(!IsEqual(symbol, nil)) {
market = this.Market(symbol)
}
var request interface{} = map[string]interface{} {}
if IsTrue(!IsEqual(limit, nil)) {
AddElementToObject(request, "count", limit)
}
if IsTrue(!IsEqual(since, nil)) {
AddElementToObject(request, "from", since)
}
response:= (<-this.HistoryGetOrders(this.Extend(request, params)))
PanicOnError(response)
var allOrders interface{} = this.SafeList(response, "elements", []interface{}{})
var canceledAndRejected interface{} = []interface{}{}
for i := 0; IsLessThan(i, GetArrayLength(allOrders)); i++ {
var order interface{} = GetValue(allOrders, i)
var event interface{} = this.SafeDict(order, "event", map[string]interface{} {})
var orderPlaced interface{} = this.SafeDict(event, "OrderPlaced")
if IsTrue(!IsEqual(orderPlaced, nil)) {
var innerOrder interface{} = this.SafeDict(orderPlaced, "order", map[string]interface{} {})
var filled interface{} = this.SafeString(innerOrder, "filled")
if IsTrue(IsEqual(filled, "0")) {
AddElementToObject(innerOrder, "status", "canceled") // status not available in the response
AppendToArray(&canceledAndRejected,innerOrder)
}
}
var orderCanceled interface{} = this.SafeDict(event, "OrderCancelled")
if IsTrue(!IsEqual(orderCanceled, nil)) {
var innerOrder interface{} = this.SafeDict(orderCanceled, "order", map[string]interface{} {})
AddElementToObject(innerOrder, "status", "canceled") // status not available in the response
AppendToArray(&canceledAndRejected,innerOrder)
}
var orderRejected interface{} = this.SafeDict(event, "OrderRejected")
if IsTrue(!IsEqual(orderRejected, nil)) {
var innerOrder interface{} = this.SafeDict(orderRejected, "order", map[string]interface{} {})
AddElementToObject(innerOrder, "status", "rejected") // status not available in the response
AppendToArray(&canceledAndRejected,innerOrder)
}
}
ch <- this.ParseOrders(canceledAndRejected, market, since, limit)
return nil
}()
return ch
}
func (this *krakenfutures) ParseOrderType(orderType interface{}) interface{} {
var typesMap interface{} = map[string]interface{} {
"lmt": "limit",
"mkt": "market",
"post": "limit",
"ioc": "market",
}
return this.SafeString(typesMap, orderType, orderType)
}
func (this *krakenfutures) VerifyOrderActionSuccess(status interface{}, method interface{}, optionalArgs ...interface{}) {
omit := GetArg(optionalArgs, 0, []interface{}{})
_ = omit
var errors interface{} = map[string]interface{} {
"invalidOrderType": InvalidOrder,
"invalidSide": InvalidOrder,
"invalidSize": InvalidOrder,
"invalidPrice": InvalidOrder,
"insufficientAvailableFunds": InsufficientFunds,
"selfFill": ExchangeError,
"tooManySmallOrders": ExchangeError,
"maxPositionViolation": BadRequest,
"marketSuspended": ExchangeNotAvailable,
"marketInactive": ExchangeNotAvailable,
"clientOrderIdAlreadyExist": DuplicateOrderId,
"clientOrderIdTooLong": BadRequest,
"outsidePriceCollar": InvalidOrder,
"postWouldExecute": OrderImmediatelyFillable,
"iocWouldNotExecute": OrderNotFillable,
"wouldNotReducePosition": ExchangeError,
"orderForEditNotFound": OrderNotFound,
"orderForEditNotAStop": InvalidOrder,
"filled": OrderNotFound,
"notFound": OrderNotFound,
}
if IsTrue(IsTrue((InOp(errors, status))) && !IsTrue(this.InArray(status, omit))) {
throwDynamicException(GetValue(errors, status), Add(Add(Add(Add(this.Id, ": "), method), " failed due to "), status));
}
}
func (this *krakenfutures) ParseOrderStatus(status interface{}) interface{} {
var statuses interface{} = map[string]interface{} {
"placed": "open",
"cancelled": "canceled",
"invalidOrderType": "rejected",
"invalidSide": "rejected",
"invalidSize": "rejected",
"invalidPrice": "rejected",
"insufficientAvailableFunds": "rejected",
"selfFill": "rejected",
"tooManySmallOrders": "rejected",
"maxPositionViolation": "rejected",
"marketSuspended": "rejected",
"marketInactive": "rejected",
"clientOrderIdAlreadyExist": "rejected",
"clientOrderIdTooLong": "rejected",
"outsidePriceCollar": "rejected",
"postWouldExecute": "rejected",
"iocWouldNotExecute": "rejected",
"wouldNotReducePosition": "rejected",
"edited": "open",
"orderForEditNotFound": "rejected",
"orderForEditNotAStop": "rejected",
"filled": "closed",
"notFound": "rejected",
"untouched": "open",
"partiallyFilled": "open",
}
return this.SafeString(statuses, status, status)
}
func (this *krakenfutures) ParseOrder(order interface{}, optionalArgs ...interface{}) interface{} {
//
// LIMIT
//
// {
// "order_id": "179f9af8-e45e-469d-b3e9-2fd4675cb7d0",
// "status": "placed",
// "receivedTime": "2019-09-05T16:33:50.734Z",
// "orderEvents": [
// {
// "uid": "614a5298-0071-450f-83c6-0617ce8c6bc4",
// "order": {
// "orderId": "179f9af8-e45e-469d-b3e9-2fd4675cb7d0",
// "cliOrdId": null,
// "type": "lmt",
// "symbol": "pi_xbtusd",
// "side": "buy",
// "quantity": 10000,
// "filled": 0,
// "limitPrice": 9400,
// "reduceOnly": false,
// "timestamp": "2019-09-05T16:33:50.734Z",
// "lastUpdateTimestamp": "2019-09-05T16:33:50.734Z"
// },
// "reducedQuantity": null,
// "reason": "WOULD_NOT_REDUCE_POSITION", // REJECTED
// "type": "PLACE"
// }
// ]
// }
//
// CONDITIONAL
//
// {
// "order_id": "1abfd3c6-af93-4b30-91cc-e4a93797f3f5",
// "status": "placed",
// "receivedTime": "2019-12-05T10:20:50.701Z",
// "orderEvents": [
// {
// "orderTrigger": {
// "uid": "1abfd3c6-af93-4b30-91cc-e4a93797f3f5",
// "clientId":null,
// "type": "lmt", // "ioc" if stop market
// "symbol": "pi_xbtusd",
// "side": "buy",
// "quantity":10,
// "limitPrice":15000,
// "triggerPrice":9500,
// "triggerSide": "trigger_below",
// "triggerSignal": "mark_price",
// "reduceOnly":false,
// "timestamp": "2019-12-05T10:20:50.701Z",
// "lastUpdateTimestamp": "2019-12-05T10:20:50.701Z"
// },
// "type": "PLACE"
// }
// ]
// }
//
// EXECUTION
//
// {
// "order_id": "61ca5732-3478-42fe-8362-abbfd9465294",
// "status": "placed",
// "receivedTime": "2019-12-11T17:17:33.888Z",
// "orderEvents": [
// {
// "executionId": "e1ec9f63-2338-4c44-b40a-43486c6732d7",
// "price": 7244.5,
// "amount": 10,
// "orderPriorEdit": null,
// "orderPriorExecution": {
// "orderId": "61ca5732-3478-42fe-8362-abbfd9465294",
// "cliOrdId": null,
// "type": "lmt",
// "symbol": "pi_xbtusd",
// "side": "buy",
// "quantity": 10,
// "filled": 0,
// "limitPrice": 7500,
// "reduceOnly": false,
// "timestamp": "2019-12-11T17:17:33.888Z",
// "lastUpdateTimestamp": "2019-12-11T17:17:33.888Z"
// },
// "takerReducedQuantity": null,
// "type": "EXECUTION"
// }
// ]
// }
//
// EDIT ORDER
//
// {
// "status": "edited",
// "orderId": "022774bc-2c4a-4f26-9317-436c8d85746d",
// "receivedTime": "2019-09-05T16:47:47.521Z",
// "orderEvents": [
// {
// "old": {
// "orderId": "022774bc-2c4a-4f26-9317-436c8d85746d",
// "cliOrdId":null,
// "type": "lmt",
// "symbol": "pi_xbtusd",
// "side": "buy",
// "quantity":1000,
// "filled":0,
// "limitPrice":9400.0,
// "reduceOnly":false,
// "timestamp": "2019-09-05T16:41:35.173Z",
// "lastUpdateTimestamp": "2019-09-05T16:41:35.173Z"
// },
// "new": {
// "orderId": "022774bc-2c4a-4f26-9317-436c8d85746d",
// "cliOrdId": null,
// "type": "lmt",
// "symbol": "pi_xbtusd",
// "side": "buy",
// "quantity": 1501,
// "filled": 0,
// "limitPrice": 7200,
// "reduceOnly": false,
// "timestamp": "2019-09-05T16:41:35.173Z",
// "lastUpdateTimestamp": "2019-09-05T16:47:47.519Z"
// },
// "reducedQuantity": null,
// "type": "EDIT"
// }
// ]
// }
//
// CANCEL ORDER
//
// {
// "status": "cancelled",
// "orderEvents": [
// {
// "uid": "85c40002-3f20-4e87-9302-262626c3531b",
// "order": {
// "orderId": "85c40002-3f20-4e87-9302-262626c3531b",
// "cliOrdId": null,
// "type": "lmt",
// "symbol": "pi_xbtusd",
// "side": "buy",
// "quantity": 1000,
// "filled": 0,
// "limitPrice": 10144,
// "stopPrice": null,
// "reduceOnly": false,
// "timestamp": "2019-08-01T15:26:27.790Z"
// },
// "type": "CANCEL"
// }
// ]
// }
//
// cancelAllOrders
//
// {
// "orderId": "85c40002-3f20-4e87-9302-262626c3531b",
// "cliOrdId": null,
// "type": "lmt",
// "symbol": "pi_xbtusd",
// "side": "buy",
// "quantity": 1000,
// "filled": 0,
// "limitPrice": 10144,
// "stopPrice": null,
// "reduceOnly": false,
// "timestamp": "2019-08-01T15:26:27.790Z"
// }
//
// FETCH OPEN ORDERS
//
// {
// "order_id": "59302619-41d2-4f0b-941f-7e7914760ad3",
// "symbol": "pi_xbtusd",
// "side": "sell",
// "orderType": "lmt",
// "limitPrice": 10640,
// "unfilledSize": 304,
// "receivedTime": "2019-09-05T17:01:17.410Z",
// "status": "untouched",
// "filledSize": 0,
// "reduceOnly": true,
// "lastUpdateTime": "2019-09-05T17:01:17.410Z"
// }
//
// createOrders error
// {
// "status": "requiredArgumentMissing",
// "orderEvents": []
// }
// closed orders
// {
// uid: '2f00cd63-e61d-44f8-8569-adabde885941',
// timestamp: '1707258274849',
// event: {
// OrderPlaced: {
// order: {
// uid: '85805e01-9eed-4395-8360-ed1a228237c9',
// accountUid: '406142dd-7c5c-4a8b-acbc-5f16eca30009',
// tradeable: 'PF_LTCUSD',
// direction: 'Buy',
// quantity: '0',
// filled: '0.1',
// timestamp: '1707258274849',
// limitPrice: '69.2200000000',
// orderType: 'IoC',
// clientId: '',
// reduceOnly: false,
// lastUpdateTimestamp: '1707258274849'
// },
// reason: 'new_user_order',
// reducedQuantity: '',
// algoId: ''
// }
// }
// }
//
market := GetArg(optionalArgs, 0, nil)
_ = market
var orderEvents interface{} = this.SafeValue(order, "orderEvents", []interface{}{})
var errorStatus interface{} = this.SafeString(order, "status")
var orderEventsLength interface{} = GetArrayLength(orderEvents)
if IsTrue(IsTrue(IsTrue((InOp(order, "orderEvents"))) && IsTrue((!IsEqual(errorStatus, nil)))) && IsTrue((IsEqual(orderEventsLength, 0)))) {
// creteOrders error response
return this.SafeOrder(map[string]interface{} {
"info": order,
"status": "rejected",
})
}
var details interface{} = nil
var isPrior interface{} = false
var fixed interface{} = false
var statusId interface{} = nil
var price interface{} = nil
var trades interface{} = []interface{}{}
if IsTrue(orderEventsLength) {
var executions interface{} = []interface{}{}
for i := 0; IsLessThan(i, GetArrayLength(orderEvents)); i++ {
var item interface{} = GetValue(orderEvents, i)
if IsTrue(IsEqual(this.SafeString(item, "type"), "EXECUTION")) {
AppendToArray(&executions,item)
}
// Final order (after placement / editing / execution / canceling)
var orderTrigger interface{} = this.SafeValue(item, "orderTrigger")
if IsTrue(IsEqual(details, nil)) {
details = this.SafeValue2(item, "new", "order", orderTrigger)
if IsTrue(!IsEqual(details, nil)) {
isPrior = false
fixed = true
} else if !IsTrue(fixed) {
var orderPriorExecution interface{} = this.SafeValue(item, "orderPriorExecution")
details = this.SafeValue2(item, "orderPriorExecution", "orderPriorEdit")
price = this.SafeString(orderPriorExecution, "limitPrice")
if IsTrue(!IsEqual(details, nil)) {
isPrior = true
}
}
}
}
trades = this.ParseTrades(executions)
statusId = this.SafeString(order, "status")
}
if IsTrue(IsEqual(details, nil)) {
details = order
}
if IsTrue(IsEqual(statusId, nil)) {
statusId = this.SafeString(details, "status")
}
// This may be incorrectly marked as "open" if only execution report is given,
// but will be fixed below
var status interface{} = this.ParseOrderStatus(statusId)
var isClosed interface{} = this.InArray(status, []interface{}{"canceled", "rejected", "closed"})
var marketId interface{} = this.SafeString(details, "symbol")
market = this.SafeMarket(marketId, market)
var timestamp interface{} = this.Parse8601(this.SafeString2(details, "timestamp", "receivedTime"))
var lastUpdateTimestamp interface{} = this.Parse8601(this.SafeString(details, "lastUpdateTime"))
if IsTrue(IsEqual(price, nil)) {
price = this.SafeString(details, "limitPrice")
}
var amount interface{} = this.SafeString(details, "quantity")
var filled interface{} = this.SafeString2(details, "filledSize", "filled", "0.0")
var remaining interface{} = this.SafeString(details, "unfilledSize")
var average interface{} = nil
var filled2 interface{} = "0.0"
var tradesLength interface{} = GetArrayLength(trades)
if IsTrue(IsGreaterThan(tradesLength, 0)) {
var vwapSum interface{} = "0.0"
for i := 0; IsLessThan(i, GetArrayLength(trades)); i++ {
var trade interface{} = GetValue(trades, i)
var tradeAmount interface{} = this.SafeString(trade, "amount")
var tradePrice interface{} = this.SafeString(trade, "price")
filled2 = Precise.StringAdd(filled2, tradeAmount)
vwapSum = Precise.StringAdd(vwapSum, Precise.StringMul(tradeAmount, tradePrice))
}
average = Precise.StringDiv(vwapSum, filled2)
if IsTrue(IsTrue(IsTrue(IsTrue((!IsEqual(amount, nil))) && IsTrue((!IsTrue(isClosed)))) && IsTrue(isPrior)) && IsTrue(Precise.StringGe(filled2, amount))) {
status = "closed"
isClosed = true
}
if IsTrue(isPrior) {
filled = Precise.StringAdd(filled, filled2)
} else {
filled = Precise.StringMax(filled, filled2)
}
}
if IsTrue(IsEqual(remaining, nil)) {
if IsTrue(isPrior) {
if IsTrue(!IsEqual(amount, nil)) {
// remaining amount before execution minus executed amount
remaining = Precise.StringSub(amount, filled2)
}
} else {
remaining = amount
}
}
// if fetchOpenOrders are parsed
if IsTrue(IsTrue(IsTrue((IsEqual(amount, nil))) && IsTrue((!IsTrue(isPrior)))) && IsTrue((!IsEqual(remaining, nil)))) {
amount = Precise.StringAdd(filled, remaining)
}
var cost interface{} = nil
if IsTrue(IsTrue((!IsEqual(filled, nil))) && IsTrue((!IsEqual(market, nil)))) {
var whichPrice interface{} = Ternary(IsTrue((!IsEqual(average, nil))), average, price)
if IsTrue(!IsEqual(whichPrice, nil)) {
if IsTrue(GetValue(market, "linear")) {
cost = Precise.StringMul(filled, whichPrice) // in quote
} else {
cost = Precise.StringDiv(filled, whichPrice) // in base
}
}
}
var id interface{} = this.SafeString2(order, "order_id", "orderId")
if IsTrue(IsEqual(id, nil)) {
id = this.SafeString2(details, "orderId", "uid")
}
var typeVar interface{} = this.SafeStringLower2(details, "type", "orderType")
var timeInForce interface{} = "gtc"
if IsTrue(IsTrue(IsEqual(typeVar, "ioc")) || IsTrue(IsEqual(this.ParseOrderType(typeVar), "market"))) {
timeInForce = "ioc"
}
return this.SafeOrder(map[string]interface{} {
"info": order,
"id": id,
"clientOrderId": this.SafeStringN(details, []interface{}{"clientOrderId", "clientId", "cliOrdId"}),
"timestamp": timestamp,
"datetime": this.Iso8601(timestamp),
"lastTradeTimestamp": nil,
"lastUpdateTimestamp": lastUpdateTimestamp,
"symbol": this.SafeString(market, "symbol"),
"type": this.ParseOrderType(typeVar),
"timeInForce": timeInForce,
"postOnly": IsEqual(typeVar, "post"),
"reduceOnly": this.SafeBool2(details, "reduceOnly", "reduce_only"),
"side": this.SafeString(details, "side"),
"price": price,
"triggerPrice": this.SafeString(details, "triggerPrice"),
"amount": amount,
"cost": cost,
"average": average,
"filled": filled,
"remaining": remaining,
"status": status,
"fee": nil,
"fees": nil,
"trades": trades,
})
}
/**
* @method
* @name krakenfutures#fetchMyTrades
* @description fetch all trades made by the user
* @see https://docs.futures.kraken.com/#http-api-trading-v3-api-historical-data-get-your-fills
* @param {string} symbol unified market symbol
* @param {int} [since] *not used by the api* the earliest time in ms to fetch trades for
* @param {int} [limit] the maximum number of trades structures to retrieve
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @param {int} [params.until] the latest time in ms to fetch entries for
* @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
*/
func (this *krakenfutures) FetchMyTrades(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
symbol := GetArg(optionalArgs, 0, nil)
_ = symbol
since := GetArg(optionalArgs, 1, nil)
_ = since
limit := GetArg(optionalArgs, 2, nil)
_ = limit
params := GetArg(optionalArgs, 3, map[string]interface{} {})
_ = params
retRes20028 := (<-this.LoadMarkets())
PanicOnError(retRes20028)
var market interface{} = nil
if IsTrue(!IsEqual(symbol, nil)) {
market = this.Market(symbol)
}
// todo: lastFillTime: this.iso8601(end)
response:= (<-this.PrivateGetFills(params))
PanicOnError(response)
//
// {
// "result": "success",
// "serverTime": "2016-02-25T09:45:53.818Z",
// "fills": [
// {
// "fillTime": "2016-02-25T09:47:01.000Z",
// "order_id": "c18f0c17-9971-40e6-8e5b-10df05d422f0",
// "fill_id": "522d4e08-96e7-4b44-9694-bfaea8fe215e",
// "cliOrdId": "d427f920-ec55-4c18-ba95-5fe241513b30", // EXTRA
// "symbol": "fi_xbtusd_180615",
// "side": "buy",
// "size": 2000,
// "price": 4255,
// "fillType": "maker"
// },
// ...
// ]
// }
//
ch <- this.ParseTrades(GetValue(response, "fills"), market, since, limit)
return nil
}()
return ch
}
/**
* @method
* @name krakenfutures#fetchBalance
* @see https://docs.futures.kraken.com/#http-api-trading-v3-api-account-information-get-wallets
* @description Fetch the balance for a sub-account, all sub-account balances are inside 'info' in the response
* @param {object} [params] Exchange specific parameters
* @param {string} [params.type] The sub-account type to query the balance of, possible values include 'flex', 'cash'/'main'/'funding', or a market symbol * defaults to 'flex' *
* @param {string} [params.symbol] A unified market symbol, when assigned the balance for a trading market that matches the symbol is returned
* @returns A [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
*/
func (this *krakenfutures) FetchBalance(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
params := GetArg(optionalArgs, 0, map[string]interface{} {})
_ = params
retRes20438 := (<-this.LoadMarkets())
PanicOnError(retRes20438)
var typeVar interface{} = this.SafeString2(params, "type", "account")
var symbol interface{} = this.SafeString(params, "symbol")
params = this.Omit(params, []interface{}{"type", "account", "symbol"})
response:= (<-this.PrivateGetAccounts(params))
PanicOnError(response)
//
// {
// "result": "success",
// "accounts": {
// "fi_xbtusd": {
// "auxiliary": { usd: "0", pv: '0.0', pnl: '0.0', af: '0.0', funding: "0.0" },
// "marginRequirements": { im: '0.0', mm: '0.0', lt: '0.0', tt: "0.0" },
// "triggerEstimates": { im: '0', mm: '0', lt: "0", tt: "0" },
// "balances": { xbt: "0.0" },
// "currency": "xbt",
// "type": "marginAccount"
// },
// "cash": {
// "balances": {
// "eur": "0.0",
// "gbp": "0.0",
// "bch": "0.0",
// "xrp": "2.20188538338",
// "usd": "0.0",
// "eth": "0.0",
// "usdt": "0.0",
// "ltc": "0.0",
// "usdc": "0.0",
// "xbt": "0.0"
// },
// "type": "cashAccount"
// },
// "fv_xrpxbt": {
// "auxiliary": { usd: "0", pv: '0.0', pnl: '0.0', af: '0.0', funding: "0.0" },
// "marginRequirements": { im: '0.0', mm: '0.0', lt: '0.0', tt: "0.0" },
// "triggerEstimates": { im: '0', mm: '0', lt: "0", tt: "0" },
// "balances": { xbt: "0.0" },
// "currency": "xbt",
// "type": "marginAccount"
// },
// "fi_xrpusd": {
// "auxiliary": { usd: "0", pv: '11.0', pnl: '0.0', af: '11.0', funding: "0.0" },
// "marginRequirements": { im: '0.0', mm: '0.0', lt: '0.0', tt: "0.0" },
// "triggerEstimates": { im: '0', mm: '0', lt: "0", tt: "0" },
// "balances": { xrp: "11.0" },
// "currency": "xrp",
// "type": "marginAccount"
// },
// "fi_ethusd": {
// "auxiliary": { usd: "0", pv: '0.0', pnl: '0.0', af: '0.0', funding: "0.0" },
// "marginRequirements": { im: '0.0', mm: '0.0', lt: '0.0', tt: "0.0" },
// "triggerEstimates": { im: '0', mm: '0', lt: "0", tt: "0" },
// "balances": { eth: "0.0" },
// "currency": "eth",
// "type": "marginAccount"
// },
// "fi_ltcusd": {
// "auxiliary": { usd: "0", pv: '0.0', pnl: '0.0', af: '0.0', funding: "0.0" },
// "marginRequirements": { im: '0.0', mm: '0.0', lt: '0.0', tt: "0.0" },
// "triggerEstimates": { im: '0', mm: '0', lt: "0", tt: "0" },
// "balances": { ltc: "0.0" },
// "currency": "ltc",
// "type": "marginAccount"
// },
// "fi_bchusd": {
// "auxiliary": { usd: "0", pv: '0.0', pnl: '0.0', af: '0.0', funding: "0.0" },
// "marginRequirements": { im: '0.0', mm: '0.0', lt: '0.0', tt: "0.0" },
// "triggerEstimates": { im: '0', mm: '0', lt: "0", tt: "0" },
// "balances": { bch: "0.0" },
// "currency": "bch",
// "type": "marginAccount"
// },
// "flex": {
// "currencies": {},
// "initialMargin": "0.0",
// "initialMarginWithOrders": "0.0",
// "maintenanceMargin": "0.0",
// "balanceValue": "0.0",
// "portfolioValue": "0.0",
// "collateralValue": "0.0",
// "pnl": "0.0",
// "unrealizedFunding": "0.0",
// "totalUnrealized": "0.0",
// "totalUnrealizedAsMargin": "0.0",
// "availableMargin": "0.0",
// "marginEquity": "0.0",
// "type": "multiCollateralMarginAccount"
// }
// },
// "serverTime": "2022-04-12T07:48:07.475Z"
// }
//
var datetime interface{} = this.SafeString(response, "serverTime")
if IsTrue(IsTrue(IsEqual(typeVar, "marginAccount")) || IsTrue(IsEqual(typeVar, "margin"))) {
if IsTrue(IsEqual(symbol, nil)) {
panic(ArgumentsRequired(Add(this.Id, " fetchBalance requires symbol argument for margin accounts")))
}
typeVar = symbol
}
if IsTrue(IsEqual(typeVar, nil)) {
typeVar = Ternary(IsTrue((IsEqual(symbol, nil))), "flex", symbol)
}
var accountName interface{} = this.ParseAccount(typeVar)
var accounts interface{} = this.SafeValue(response, "accounts")
var account interface{} = this.SafeValue(accounts, accountName)
if IsTrue(IsEqual(account, nil)) {
typeVar = Ternary(IsTrue((IsEqual(typeVar, nil))), "", typeVar)
symbol = Ternary(IsTrue((IsEqual(symbol, nil))), "", symbol)
panic(BadRequest(Add(Add(this.Id, " fetchBalance has no account for "), typeVar)))
}
var balance interface{} = this.ParseBalance(account)
AddElementToObject(balance, "info", response)
AddElementToObject(balance, "timestamp", this.Parse8601(datetime))
AddElementToObject(balance, "datetime", datetime)
ch <- balance
return nil
}()
return ch
}
func (this *krakenfutures) ParseBalance(response interface{}) interface{} {
//
// cashAccount
//
// {
// "balances": {
// "eur": "0.0",
// "gbp": "0.0",
// "bch": "0.0",
// "xrp": "2.20188538338",
// "usd": "0.0",
// "eth": "0.0",
// "usdt": "0.0",
// "ltc": "0.0",
// "usdc": "0.0",
// "xbt": "0.0"
// },
// "type": "cashAccount"
// }
//
// marginAccount e,g, fi_xrpusd
//
// {
// "auxiliary": {
// "usd": "0",
// "pv": "11.0",
// "pnl": "0.0",
// "af": "11.0",
// "funding": "0.0"
// },
// "marginRequirements": { im: '0.0', mm: '0.0', lt: '0.0', tt: "0.0" },
// "triggerEstimates": { im: '0', mm: '0', lt: "0", tt: "0" },
// "balances": { xrp: "11.0" },
// "currency": "xrp",
// "type": "marginAccount"
// }
//
// flex/multiCollateralMarginAccount
//
// {
// "currencies": {
// "USDT": {
// "quantity": "1",
// "value": "1.0001",
// "collateral": "0.9477197625",
// "available": "1.0"
// }
// },
// "initialMargin": "0.0",
// "initialMarginWithOrders": "0.0",
// "maintenanceMargin": "0.0",
// "balanceValue": "1.0",
// "portfolioValue": "1.0",
// "collateralValue": "0.95",
// "pnl": "0.0",
// "unrealizedFunding": "0.0",
// "totalUnrealized": "0.0",
// "totalUnrealizedAsMargin": "0.0",
// "availableMargin": "0.95",
// "marginEquity": "0.95",
// "type": "multiCollateralMarginAccount"
// }
//
var accountType interface{} = this.SafeString2(response, "accountType", "type")
var isFlex interface{} = (IsEqual(accountType, "multiCollateralMarginAccount"))
var isCash interface{} = (IsEqual(accountType, "cashAccount"))
var balances interface{} = this.SafeValue2(response, "balances", "currencies", map[string]interface{} {})
var result interface{} = map[string]interface{} {}
var currencyIds interface{} = ObjectKeys(balances)
for i := 0; IsLessThan(i, GetArrayLength(currencyIds)); i++ {
var currencyId interface{} = GetValue(currencyIds, i)
var balance interface{} = GetValue(balances, currencyId)
var code interface{} = this.SafeCurrencyCode(currencyId)
var splitCode interface{} = Split(code, "_")
var codeLength interface{} = GetArrayLength(splitCode)
if IsTrue(IsGreaterThan(codeLength, 1)) {
continue
}
var account interface{} = this.Account()
if IsTrue(isFlex) {
AddElementToObject(account, "total", this.SafeString(balance, "quantity"))
AddElementToObject(account, "free", this.SafeString(balance, "available"))
} else if IsTrue(isCash) {
AddElementToObject(account, "used", "0.0")
AddElementToObject(account, "total", balance)
} else {
var auxiliary interface{} = this.SafeValue(response, "auxiliary")
AddElementToObject(account, "free", this.SafeString(auxiliary, "af"))
AddElementToObject(account, "total", this.SafeString(auxiliary, "pv"))
}
AddElementToObject(result, code, account)
}
return this.SafeBalance(result)
}
/**
* @method
* @name krakenfutures#fetchFundingRates
* @description fetch the current funding rates for multiple markets
* @see https://docs.futures.kraken.com/#http-api-trading-v3-api-market-data-get-tickers
* @param {string[]} symbols unified market symbols
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {Order[]} an array of [funding rate structures]{@link https://docs.ccxt.com/#/?id=funding-rate-structure}
*/
func (this *krakenfutures) FetchFundingRates(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
symbols := GetArg(optionalArgs, 0, nil)
_ = symbols
params := GetArg(optionalArgs, 1, map[string]interface{} {})
_ = params
retRes22658 := (<-this.LoadMarkets())
PanicOnError(retRes22658)
var marketIds interface{} = this.MarketIds(symbols)
response:= (<-this.PublicGetTickers(params))
PanicOnError(response)
var tickers interface{} = this.SafeList(response, "tickers", []interface{}{})
var fundingRates interface{} = []interface{}{}
for i := 0; IsLessThan(i, GetArrayLength(tickers)); i++ {
var entry interface{} = GetValue(tickers, i)
var entry_symbol interface{} = this.SafeValue(entry, "symbol")
if IsTrue(!IsEqual(marketIds, nil)) {
if !IsTrue(this.InArray(entry_symbol, marketIds)) {
continue
}
}
var market interface{} = this.SafeMarket(entry_symbol)
var parsed interface{} = this.ParseFundingRate(entry, market)
AppendToArray(&fundingRates,parsed)
}
ch <- this.IndexBy(fundingRates, "symbol")
return nil
}()
return ch
}
func (this *krakenfutures) ParseFundingRate(ticker interface{}, optionalArgs ...interface{}) interface{} {
//
// {"ask": 26.283,
// "askSize": 4.6,
// "bid": 26.201,
// "bidSize": 190,
// "fundingRate": -0.000944642727438883,
// "fundingRatePrediction": -0.000872671532340275,
// "indexPrice": 26.253,
// "last": 26.3,
// "lastSize": 0.1,
// "lastTime": "2023-06-11T18:55:28.958Z",
// "markPrice": 26.239,
// "open24h": 26.3,
// "openInterest": 641.1,
// "pair": "COMP:USD",
// "postOnly": False,
// "suspended": False,
// "symbol": "pf_compusd",
// "tag": "perpetual",
// "vol24h": 0.1,
// "volumeQuote": 2.63}
//
market := GetArg(optionalArgs, 0, nil)
_ = market
var fundingRateMultiplier interface{} = "8" // https://support.kraken.com/hc/en-us/articles/9618146737172-Perpetual-Contracts-Funding-Rate-Method-Prior-to-September-29-2022
var marketId interface{} = this.SafeString(ticker, "symbol")
var symbol interface{} = this.Symbol(marketId)
var timestamp interface{} = this.Parse8601(this.SafeString(ticker, "lastTime"))
var indexPrice interface{} = this.SafeNumber(ticker, "indexPrice")
var markPriceString interface{} = this.SafeString(ticker, "markPrice")
var markPrice interface{} = this.ParseNumber(markPriceString)
var fundingRateString interface{} = this.SafeString(ticker, "fundingRate")
var fundingRateResult interface{} = Precise.StringDiv(Precise.StringMul(fundingRateString, fundingRateMultiplier), markPriceString)
var fundingRate interface{} = this.ParseNumber(fundingRateResult)
var nextFundingRateString interface{} = this.SafeString(ticker, "fundingRatePrediction")
var nextFundingRateResult interface{} = Precise.StringDiv(Precise.StringMul(nextFundingRateString, fundingRateMultiplier), markPriceString)
var nextFundingRate interface{} = this.ParseNumber(nextFundingRateResult)
return map[string]interface{} {
"info": ticker,
"symbol": symbol,
"markPrice": markPrice,
"indexPrice": indexPrice,
"interestRate": nil,
"estimatedSettlePrice": nil,
"timestamp": timestamp,
"datetime": this.Iso8601(timestamp),
"fundingRate": fundingRate,
"fundingTimestamp": nil,
"fundingDatetime": nil,
"nextFundingRate": nextFundingRate,
"nextFundingTimestamp": nil,
"nextFundingDatetime": nil,
"previousFundingRate": nil,
"previousFundingTimestamp": nil,
"previousFundingDatetime": nil,
"interval": nil,
}
}
/**
* @method
* @name krakenfutures#fetchFundingRateHistory
* @description fetches historical funding rate prices
* @see https://docs.futures.kraken.com/#http-api-trading-v3-api-historical-funding-rates-historical-funding-rates
* @param {string} symbol unified symbol of the market to fetch the funding rate history for
* @param {int} [since] timestamp in ms of the earliest funding rate to fetch
* @param {int} [limit] the maximum amount of [funding rate structures]{@link https://docs.ccxt.com/#/?id=funding-rate-history-structure} to fetch
* @param {object} [params] extra parameters specific to the api endpoint
* @returns {object[]} a list of [funding rate structures]{@link https://docs.ccxt.com/#/?id=funding-rate-history-structure}
*/
func (this *krakenfutures) FetchFundingRateHistory(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
symbol := GetArg(optionalArgs, 0, nil)
_ = symbol
since := GetArg(optionalArgs, 1, nil)
_ = since
limit := GetArg(optionalArgs, 2, nil)
_ = limit
params := GetArg(optionalArgs, 3, map[string]interface{} {})
_ = params
if IsTrue(IsEqual(symbol, nil)) {
panic(ArgumentsRequired(Add(this.Id, " fetchFundingRateHistory() requires a symbol argument")))
}
retRes23588 := (<-this.LoadMarkets())
PanicOnError(retRes23588)
var market interface{} = this.Market(symbol)
if !IsTrue(GetValue(market, "swap")) {
panic(BadRequest(Add(this.Id, " fetchFundingRateHistory() supports swap contracts only")))
}
var request interface{} = map[string]interface{} {
"symbol": ToUpper(GetValue(market, "id")),
}
response:= (<-this.PublicGetHistoricalfundingrates(this.Extend(request, params)))
PanicOnError(response)
//
// {
// "rates": [
// {
// "timestamp": '2018-08-31T16:00:00.000Z',
// "fundingRate": '2.18900669884E-7',
// "relativeFundingRate": '0.000060779960000000'
// },
// ...
// ]
// }
//
var rates interface{} = this.SafeValue(response, "rates")
var result interface{} = []interface{}{}
for i := 0; IsLessThan(i, GetArrayLength(rates)); i++ {
var item interface{} = GetValue(rates, i)
var datetime interface{} = this.SafeString(item, "timestamp")
AppendToArray(&result,map[string]interface{} {
"info": item,
"symbol": symbol,
"fundingRate": this.SafeNumber(item, "relativeFundingRate"),
"timestamp": this.Parse8601(datetime),
"datetime": datetime,
})
}
var sorted interface{} = this.SortBy(result, "timestamp")
ch <- this.FilterBySymbolSinceLimit(sorted, symbol, since, limit)
return nil
}()
return ch
}
/**
* @method
* @name krakenfutures#fetchPositions
* @see https://docs.futures.kraken.com/#http-api-trading-v3-api-account-information-get-open-positions
* @description Fetches current contract trading positions
* @param {string[]} symbols List of unified symbols
* @param {object} [params] Not used by krakenfutures
* @returns Parsed exchange response for positions
*/
func (this *krakenfutures) FetchPositions(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
symbols := GetArg(optionalArgs, 0, nil)
_ = symbols
params := GetArg(optionalArgs, 1, map[string]interface{} {})
_ = params
retRes24068 := (<-this.LoadMarkets())
PanicOnError(retRes24068)
var request interface{} = map[string]interface{} {}
response:= (<-this.PrivateGetOpenpositions(request))
PanicOnError(response)
//
// {
// "result": "success",
// "openPositions": [
// {
// "side": "long",
// "symbol": "pi_xrpusd",
// "price": "0.7533",
// "fillTime": "2022-03-03T22:51:16.566Z",
// "size": "230",
// "unrealizedFunding": "-0.001878596918214635"
// }
// ],
// "serverTime": "2022-03-03T22:51:16.566Z"
// }
//
var result interface{} = this.ParsePositions(response)
ch <- this.FilterByArrayPositions(result, "symbol", symbols, false)
return nil
}()
return ch
}
func (this *krakenfutures) ParsePositions(response interface{}, optionalArgs ...interface{}) interface{} {
symbols := GetArg(optionalArgs, 0, nil)
_ = symbols
params := GetArg(optionalArgs, 1, map[string]interface{} {})
_ = params
var result interface{} = []interface{}{}
var positions interface{} = this.SafeValue(response, "openPositions")
for i := 0; IsLessThan(i, GetArrayLength(positions)); i++ {
var position interface{} = this.ParsePosition(GetValue(positions, i))
AppendToArray(&result,position)
}
return result
}
func (this *krakenfutures) ParsePosition(position interface{}, optionalArgs ...interface{}) interface{} {
// cross
// {
// "side": "long",
// "symbol": "pi_xrpusd",
// "price": "0.7533",
// "fillTime": "2022-03-03T22:51:16.566Z",
// "size": "230",
// "unrealizedFunding": "-0.001878596918214635"
// }
//
// isolated
// {
// "side":"long",
// "symbol":"pf_ftmusd",
// "price":"0.4921",
// "fillTime":"2023-02-22T11:37:16.685Z",
// "size":"1",
// "unrealizedFunding":"-8.155240068885155E-8",
// "pnlCurrency":"USD",
// "maxFixedLeverage":"1.0"
// }
//
market := GetArg(optionalArgs, 0, nil)
_ = market
var leverage interface{} = this.SafeNumber(position, "maxFixedLeverage")
var marginType interface{} = "cross"
if IsTrue(!IsEqual(leverage, nil)) {
marginType = "isolated"
}
var datetime interface{} = this.SafeString(position, "fillTime")
var marketId interface{} = this.SafeString(position, "symbol")
market = this.SafeMarket(marketId, market)
return map[string]interface{} {
"info": position,
"symbol": GetValue(market, "symbol"),
"timestamp": this.Parse8601(datetime),
"datetime": datetime,
"initialMargin": nil,
"initialMarginPercentage": nil,
"maintenanceMargin": nil,
"maintenanceMarginPercentage": nil,
"entryPrice": this.SafeNumber(position, "price"),
"notional": nil,
"leverage": leverage,
"unrealizedPnl": nil,
"contracts": this.SafeNumber(position, "size"),
"contractSize": this.SafeNumber(market, "contractSize"),
"marginRatio": nil,
"liquidationPrice": nil,
"markPrice": nil,
"collateral": nil,
"marginType": marginType,
"side": this.SafeString(position, "side"),
"percentage": nil,
}
}
/**
* @method
* @name krakenfutures#fetchLeverageTiers
* @description retrieve information on the maximum leverage, and maintenance margin for trades of varying trade sizes
* @see https://docs.futures.kraken.com/#http-api-trading-v3-api-instrument-details-get-instruments
* @param {string[]|undefined} symbols list of unified market symbols
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a dictionary of [leverage tiers structures]{@link https://docs.ccxt.com/#/?id=leverage-tiers-structure}, indexed by market symbols
*/
func (this *krakenfutures) FetchLeverageTiers(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
symbols := GetArg(optionalArgs, 0, nil)
_ = symbols
params := GetArg(optionalArgs, 1, map[string]interface{} {})
_ = params
retRes25058 := (<-this.LoadMarkets())
PanicOnError(retRes25058)
response:= (<-this.PublicGetInstruments(params))
PanicOnError(response)
//
// {
// "result": "success",
// "instruments": [
// {
// "symbol": "fi_ethusd_180928",
// "type": "futures_inverse", // futures_vanilla // spot index
// "underlying": "rr_ethusd",
// "lastTradingTime": "2018-09-28T15:00:00.000Z",
// "tickSize": 0.1,
// "contractSize": 1,
// "tradeable": true,
// "marginLevels": [
// {
// "contracts":0,
// "initialMargin":0.02,
// "maintenanceMargin":0.01
// },
// {
// "contracts":250000,
// "initialMargin":0.04,
// "maintenanceMargin":0.02
// },
// ...
// ],
// "isin": "GB00JVMLMP88",
// "retailMarginLevels": [
// {
// "contracts": 0,
// "initialMargin": 0.5,
// "maintenanceMargin": 0.25
// }
// ],
// "tags": [],
// },
// {
// "symbol": "in_xbtusd",
// "type": "spot index",
// "tradeable":false
// }
// ]
// "serverTime": "2018-07-19T11:32:39.433Z"
// }
//
var data interface{} = this.SafeList(response, "instruments")
ch <- this.ParseLeverageTiers(data, symbols, "symbol")
return nil
}()
return ch
}
func (this *krakenfutures) ParseMarketLeverageTiers(info interface{}, optionalArgs ...interface{}) interface{} {
/**
* @method
* @ignore
* @param info Exchange market response for 1 market
* @param market CCXT market
*/
//
// {
// "symbol": "fi_ethusd_180928",
// "type": "futures_inverse", // futures_vanilla // spot index
// "underlying": "rr_ethusd",
// "lastTradingTime": "2018-09-28T15:00:00.000Z",
// "tickSize": 0.1,
// "contractSize": 1,
// "tradeable": true,
// "marginLevels": [
// {
// "contracts":0,
// "initialMargin":0.02,
// "maintenanceMargin":0.01
// },
// {
// "contracts":250000,
// "initialMargin":0.04,
// "maintenanceMargin":0.02
// },
// ...
// ],
// "isin": "GB00JVMLMP88",
// "retailMarginLevels": [
// {
// "contracts": 0,
// "initialMargin": 0.5,
// "maintenanceMargin": 0.25
// }
// ],
// "tags": [],
// }
//
market := GetArg(optionalArgs, 0, nil)
_ = market
var marginLevels interface{} = this.SafeValue(info, "marginLevels")
var marketId interface{} = this.SafeString(info, "symbol")
market = this.SafeMarket(marketId, market)
var tiers interface{} = []interface{}{}
if IsTrue(IsEqual(marginLevels, nil)) {
return tiers
}
for i := 0; IsLessThan(i, GetArrayLength(marginLevels)); i++ {
var tier interface{} = GetValue(marginLevels, i)
var initialMargin interface{} = this.SafeString(tier, "initialMargin")
var minNotional interface{} = this.SafeNumber(tier, "numNonContractUnits")
if IsTrue(!IsEqual(i, 0)) {
var tiersLength interface{} = GetArrayLength(tiers)
var previousTier interface{} = GetValue(tiers, Subtract(tiersLength, 1))
AddElementToObject(previousTier, "maxNotional", minNotional)
}
AppendToArray(&tiers,map[string]interface{} {
"tier": this.Sum(i, 1),
"symbol": this.SafeSymbol(marketId, market),
"currency": GetValue(market, "quote"),
"minNotional": minNotional,
"maxNotional": nil,
"maintenanceMarginRate": this.SafeNumber(tier, "maintenanceMargin"),
"maxLeverage": this.ParseNumber(Precise.StringDiv("1", initialMargin)),
"info": tier,
})
}
return tiers
}
func (this *krakenfutures) ParseTransfer(transfer interface{}, optionalArgs ...interface{}) interface{} {
//
// transfer
//
// {
// "result": "success",
// "serverTime": "2022-04-12T01:22:53.420Z"
// }
//
currency := GetArg(optionalArgs, 0, nil)
_ = currency
var datetime interface{} = this.SafeString(transfer, "serverTime")
return map[string]interface{} {
"info": transfer,
"id": nil,
"timestamp": this.Parse8601(datetime),
"datetime": datetime,
"currency": this.SafeString(currency, "code"),
"amount": nil,
"fromAccount": nil,
"toAccount": nil,
"status": this.SafeString(transfer, "result"),
}
}
func (this *krakenfutures) ParseAccount(account interface{}) interface{} {
var accountByType interface{} = map[string]interface{} {
"main": "cash",
"funding": "cash",
"future": "cash",
"futures": "cash",
"cashAccount": "cash",
"multiCollateralMarginAccount": "flex",
"multiCollateral": "flex",
"multiCollateralMargin": "flex",
}
if IsTrue(InOp(accountByType, account)) {
return GetValue(accountByType, account)
} else if IsTrue(InOp(this.Markets, account)) {
var market interface{} = this.Market(account)
var marketId interface{} = GetValue(market, "id")
var splitId interface{} = Split(marketId, "_")
if IsTrue(GetValue(market, "inverse")) {
return Add("fi_", this.SafeString(splitId, 1))
} else {
return Add("fv_", this.SafeString(splitId, 1))
}
} else {
return account
}
}
/**
* @method
* @name krakenfutures#transferOut
* @description transfer from futures wallet to spot wallet
* @param {str} code Unified currency code
* @param {float} amount Size of the transfer
* @param {dict} [params] Exchange specific parameters
* @returns a [transfer structure]{@link https://docs.ccxt.com/#/?id=transfer-structure}
*/
func (this *krakenfutures) TransferOut(code interface{}, amount interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
params := GetArg(optionalArgs, 0, map[string]interface{} {})
_ = params
retRes268515 := (<-this.Transfer(code, amount, "future", "spot", params))
PanicOnError(retRes268515)
ch <- retRes268515
return nil
}()
return ch
}
/**
* @method
* @name krakenfutures#transfer
* @see https://docs.futures.kraken.com/#http-api-trading-v3-api-transfers-initiate-wallet-transfer
* @see https://docs.futures.kraken.com/#http-api-trading-v3-api-transfers-initiate-withdrawal-to-spot-wallet
* @description transfers currencies between sub-accounts
* @param {string} code Unified currency code
* @param {float} amount Size of the transfer
* @param {string} fromAccount 'main'/'funding'/'future', 'flex', or a unified market symbol
* @param {string} toAccount 'main'/'funding', 'flex', 'spot' or a unified market symbol
* @param {object} [params] Exchange specific parameters
* @returns a [transfer structure]{@link https://docs.ccxt.com/#/?id=transfer-structure}
*/
func (this *krakenfutures) Transfer(code interface{}, amount interface{}, fromAccount interface{}, toAccount interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
params := GetArg(optionalArgs, 0, map[string]interface{} {})
_ = params
retRes27028 := (<-this.LoadMarkets())
PanicOnError(retRes27028)
var currency interface{} = this.Currency(code)
if IsTrue(IsEqual(fromAccount, "spot")) {
panic(BadRequest(Add(this.Id, " transfer does not yet support transfers from spot")))
}
var request interface{} = map[string]interface{} {
"amount": amount,
}
var response interface{} = nil
if IsTrue(IsEqual(toAccount, "spot")) {
if IsTrue(!IsEqual(this.ParseAccount(fromAccount), "cash")) {
panic(BadRequest(Add(Add(Add(Add(this.Id, " transfer cannot transfer from "), fromAccount), " to "), toAccount)))
}
AddElementToObject(request, "currency", GetValue(currency, "id"))
response = (<-this.PrivatePostWithdrawal(this.Extend(request, params)))
PanicOnError(response)
} else {
AddElementToObject(request, "fromAccount", this.ParseAccount(fromAccount))
AddElementToObject(request, "toAccount", this.ParseAccount(toAccount))
AddElementToObject(request, "unit", GetValue(currency, "id"))
response = (<-this.PrivatePostTransfer(this.Extend(request, params)))
PanicOnError(response)
}
//
// {
// "result": "success",
// "serverTime": "2022-04-12T01:22:53.420Z"
// }
//
var transfer interface{} = this.ParseTransfer(response, currency)
ch <- this.Extend(transfer, map[string]interface{} {
"amount": amount,
"fromAccount": fromAccount,
"toAccount": toAccount,
})
return nil
}()
return ch
}
/**
* @method
* @name krakenfutures#setLeverage
* @description set the level of leverage for a market
* @see https://docs.futures.kraken.com/#http-api-trading-v3-api-multi-collateral-set-the-leverage-setting-for-a-market
* @param {float} leverage the rate of leverage
* @param {string} symbol unified market symbol
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} response from the exchange
*/
func (this *krakenfutures) SetLeverage(leverage interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
symbol := GetArg(optionalArgs, 0, nil)
_ = symbol
params := GetArg(optionalArgs, 1, map[string]interface{} {})
_ = params
if IsTrue(IsEqual(symbol, nil)) {
panic(ArgumentsRequired(Add(this.Id, " setLeverage() requires a symbol argument")))
}
retRes27518 := (<-this.LoadMarkets())
PanicOnError(retRes27518)
var request interface{} = map[string]interface{} {
"maxLeverage": leverage,
"symbol": ToUpper(this.MarketId(symbol)),
}
retRes275915 := (<-this.PrivatePutLeveragepreferences(this.Extend(request, params)))
PanicOnError(retRes275915)
//
// { result: "success", serverTime: "2023-08-01T09:40:32.345Z" }
//
ch <- retRes275915
return nil
}()
return ch
}
/**
* @method
* @name krakenfutures#fetchLeverages
* @description fetch the set leverage for all contract and margin markets
* @see https://docs.futures.kraken.com/#http-api-trading-v3-api-multi-collateral-get-the-leverage-setting-for-a-market
* @param {string[]} [symbols] a list of unified market symbols
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a list of [leverage structures]{@link https://docs.ccxt.com/#/?id=leverage-structure}
*/
func (this *krakenfutures) FetchLeverages(optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
symbols := GetArg(optionalArgs, 0, nil)
_ = symbols
params := GetArg(optionalArgs, 1, map[string]interface{} {})
_ = params
retRes27728 := (<-this.LoadMarkets())
PanicOnError(retRes27728)
response:= (<-this.PrivateGetLeveragepreferences(params))
PanicOnError(response)
//
// {
// "result": "success",
// "serverTime": "2024-03-06T02:35:46.336Z",
// "leveragePreferences": [
// {
// "symbol": "PF_ETHUSD",
// "maxLeverage": 30.00
// },
// ]
// }
//
var leveragePreferences interface{} = this.SafeList(response, "leveragePreferences", []interface{}{})
ch <- this.ParseLeverages(leveragePreferences, symbols, "symbol")
return nil
}()
return ch
}
/**
* @method
* @name krakenfutures#fetchLeverage
* @description fetch the set leverage for a market
* @see https://docs.futures.kraken.com/#http-api-trading-v3-api-multi-collateral-get-the-leverage-setting-for-a-market
* @param {string} symbol unified market symbol
* @param {object} [params] extra parameters specific to the exchange API endpoint
* @returns {object} a [leverage structure]{@link https://docs.ccxt.com/#/?id=leverage-structure}
*/
func (this *krakenfutures) FetchLeverage(symbol interface{}, optionalArgs ...interface{}) <- chan interface{} {
ch := make(chan interface{})
go func() interface{} {
defer close(ch)
defer ReturnPanicError(ch)
params := GetArg(optionalArgs, 0, map[string]interface{} {})
_ = params
if IsTrue(IsEqual(symbol, nil)) {
panic(ArgumentsRequired(Add(this.Id, " fetchLeverage() requires a symbol argument")))
}
retRes28038 := (<-this.LoadMarkets())
PanicOnError(retRes28038)
var market interface{} = this.Market(symbol)
var request interface{} = map[string]interface{} {
"symbol": ToUpper(this.MarketId(symbol)),
}
response:= (<-this.PrivateGetLeveragepreferences(this.Extend(request, params)))
PanicOnError(response)
//
// {
// "result": "success",
// "serverTime": "2023-08-01T09:54:08.900Z",
// "leveragePreferences": [ { symbol: "PF_LTCUSD", maxLeverage: "5.00" } ]
// }
//
var leveragePreferences interface{} = this.SafeList(response, "leveragePreferences", []interface{}{})
var data interface{} = this.SafeDict(leveragePreferences, 0, map[string]interface{} {})
ch <- this.ParseLeverage(data, market)
return nil
}()
return ch
}
func (this *krakenfutures) ParseLeverage(leverage interface{}, optionalArgs ...interface{}) interface{} {
market := GetArg(optionalArgs, 0, nil)
_ = market
var marketId interface{} = this.SafeString(leverage, "symbol")
var leverageValue interface{} = this.SafeInteger(leverage, "maxLeverage")
return map[string]interface{} {
"info": leverage,
"symbol": this.SafeSymbol(marketId, market),
"marginMode": nil,
"longLeverage": leverageValue,
"shortLeverage": leverageValue,
}
}
func (this *krakenfutures) HandleErrors(code interface{}, reason interface{}, url interface{}, method interface{}, headers interface{}, body interface{}, response interface{}, requestHeaders interface{}, requestBody interface{}) interface{} {
if IsTrue(IsEqual(response, nil)) {
return nil
}
if IsTrue(IsEqual(code, 429)) {
panic(DDoSProtection(Add(Add(this.Id, " "), body)))
}
var errors interface{} = this.SafeValue(response, "errors")
var firstError interface{} = this.SafeValue(errors, 0)
var firtErrorMessage interface{} = this.SafeString(firstError, "message")
var message interface{} = this.SafeString(response, "error", firtErrorMessage)
if IsTrue(IsEqual(message, nil)) {
return nil
}
var feedback interface{} = Add(Add(this.Id, " "), body)
this.ThrowExactlyMatchedException(GetValue(this.Exceptions, "exact"), message, feedback)
this.ThrowBroadlyMatchedException(GetValue(this.Exceptions, "broad"), message, feedback)
if IsTrue(IsEqual(code, 400)) {
panic(BadRequest(feedback))
}
panic(ExchangeError(feedback))
}
func (this *krakenfutures) Sign(path interface{}, optionalArgs ...interface{}) interface{} {
api := GetArg(optionalArgs, 0, "public")
_ = api
method := GetArg(optionalArgs, 1, "GET")
_ = method
params := GetArg(optionalArgs, 2, map[string]interface{} {})
_ = params
headers := GetArg(optionalArgs, 3, nil)
_ = headers
body := GetArg(optionalArgs, 4, nil)
_ = body
var apiVersions interface{} = this.SafeValue(GetValue(this.Options, "versions"), api, map[string]interface{} {})
var methodVersions interface{} = this.SafeValue(apiVersions, method, map[string]interface{} {})
var defaultVersion interface{} = this.SafeString(methodVersions, path, this.Version)
var version interface{} = this.SafeString(params, "version", defaultVersion)
params = this.Omit(params, "version")
var apiAccess interface{} = this.SafeValue(GetValue(this.Options, "access"), api, map[string]interface{} {})
var methodAccess interface{} = this.SafeValue(apiAccess, method, map[string]interface{} {})
var access interface{} = this.SafeString(methodAccess, path, "public")
var endpoint interface{} = Add(Add(version, "/"), this.ImplodeParams(path, params))
params = this.Omit(params, this.ExtractParams(path))
var query interface{} = endpoint
var postData interface{} = ""
if IsTrue(IsEqual(path, "batchorder")) {
postData = Add("json=", this.Json(params))
body = postData
} else if IsTrue(GetArrayLength(ObjectKeys(params))) {
postData = this.Urlencode(params)
query = Add(query, Add("?", postData))
}
var url interface{} = Add(GetValue(GetValue(this.Urls, "api"), api), query)
if IsTrue(IsTrue(IsEqual(api, "private")) || IsTrue(IsEqual(access, "private"))) {
this.CheckRequiredCredentials()
var auth interface{} = Add(postData, "/api/")
if IsTrue(!IsEqual(api, "private")) {
auth = Add(auth, Add(api, "/"))
}
auth = Add(auth, endpoint) // 1
var hash interface{} = this.Hash(this.Encode(auth), sha256, "binary") // 2
var secret interface{} = this.Base64ToBinary(this.Secret) // 3
var signature interface{} = this.Hmac(hash, secret, sha512, "base64") // 4-5
headers = map[string]interface{} {
"Content-Type": "application/x-www-form-urlencoded",
"Accept": "application/json",
"APIKey": this.ApiKey,
"Authent": signature,
}
}
return map[string]interface{} {
"url": url,
"method": method,
"body": body,
"headers": headers,
}
}
func (this *krakenfutures) Init(userConfig map[string]interface{}) {
this.Exchange = Exchange{}
this.Exchange.InitParent(userConfig, this.Describe().(map[string]interface{}), this)
this.Exchange.DerivedExchange = this
}