Skip to content

Commit

Permalink
Add support for quarterly futures for Binance Futures
Browse files Browse the repository at this point in the history
  • Loading branch information
tmlee committed Jun 12, 2020
1 parent b540233 commit 2ad9b27
Show file tree
Hide file tree
Showing 10 changed files with 425 additions and 41 deletions.
3 changes: 2 additions & 1 deletion lib/cryptoexchange/exchanges/binance_futures/market.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ module BinanceFutures
class Market < Cryptoexchange::Models::Market
NAME = 'binance_futures'
API_URL = 'https://fapi.binance.com/fapi/v1'
FUTURES_API_URL = "https://dapi.binance.com/dapi/v1"

def self.trade_page_url(args={})
"https://www.binance.com/en/futures/#{args[:inst_id]}"
"https://www.binance.com/en/futuresng/#{args[:inst_id]}"
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,34 +9,60 @@ def supports_individual_ticker_query?
end

def fetch(market_pair)
contract_info = super(contract_info_url(market_pair))
open_interest_info = super(open_interest_url(market_pair))
if market_pair.contract_interval == "perpetual"
root_api_url = Cryptoexchange::Exchanges::BinanceFutures::Market::API_URL
futures_expire_info = nil
elsif market_pair.contract_interval == "futures"
root_api_url = Cryptoexchange::Exchanges::BinanceFutures::Market::FUTURES_API_URL
futures_expire_info = super(futures_expire_url(market_pair))
futures_expire_info = futures_expire_info["symbols"].select { |exchange_info| exchange_info["symbol"] == market_pair.inst_id }.first
end

contract_info = super(contract_info_url(root_api_url, market_pair))
open_interest_info = super(open_interest_url(root_api_url, market_pair))

adapt(contract_info, open_interest_info, futures_expire_info, market_pair)
end

adapt(nil, contract_info, open_interest_info, market_pair)
def open_interest_url(root_api_url, market_pair)
"#{root_api_url}/openInterest?symbol=#{market_pair.inst_id}"
end

def open_interest_url(market_pair)
"#{Cryptoexchange::Exchanges::BinanceFutures::Market::API_URL}/openInterest?symbol=#{market_pair.inst_id}"
def contract_info_url(root_api_url, market_pair)
"#{root_api_url}/premiumIndex?symbol=#{market_pair.inst_id}"
end

def contract_info_url(market_pair)
"#{Cryptoexchange::Exchanges::BinanceFutures::Market::API_URL}/premiumIndex?symbol=#{market_pair.inst_id}"
def futures_expire_url(market_pair)
"#{Cryptoexchange::Exchanges::BinanceFutures::Market::FUTURES_API_URL}/exchangeInfo"
end

def adapt(open_interest, contract_info, open_interest_info, market_pair)
def adapt(contract_info, open_interest_info, futures_expire_info, market_pair)
contract_stat = Cryptoexchange::Models::ContractStat.new
contract_stat.base = market_pair.base
contract_stat.target = market_pair.target
contract_stat.market = BinanceFutures::Market::NAME
contract_stat.index = contract_info['markPrice'].to_f
contract_stat.index_identifier = nil
contract_stat.index_name = nil

contract_stat.open_interest = open_interest_info["openInterest"].to_f
contract_stat.funding_rate_percentage = contract_info['lastFundingRate'].to_f * 100
contract_stat.next_funding_rate_timestamp = contract_info['nextFundingTime']/1000
contract_stat.funding_rate_percentage_predicted = nil
contract_stat.contract_type = "perpetual"
contract_stat.payload = contract_info

if market_pair.contract_interval == "perpetual"
contract_stat.index = contract_info['markPrice'].to_f
contract_stat.funding_rate_percentage = contract_info['lastFundingRate'].to_f * 100
contract_stat.next_funding_rate_timestamp = contract_info['nextFundingTime']/1000
contract_stat.funding_rate_percentage_predicted = nil
contract_stat.contract_type = "perpetual"
contract_stat.payload = contract_info
elsif market_pair.contract_interval == "futures"
contract_stat.index = contract_info[0]['markPrice'].to_f
contract_stat.contract_type = "futures"
contract_stat.payload = contract_info[0]

expire_timestamp = futures_expire_info['deliveryDate'] / 1000
start_timestamp = futures_expire_info['onboardDate'] / 1000
contract_stat.expire_timestamp = expire_timestamp
contract_stat.start_timestamp = start_timestamp
end
contract_stat
end
end
Expand Down
11 changes: 8 additions & 3 deletions lib/cryptoexchange/exchanges/binance_futures/services/market.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,19 @@ def supports_individual_ticker_query?
end

def fetch
output = super(ticker_url)
adapt_all(output)
perpetual_output = super(perpetual_ticker_url)
futures_output = super(futures_ticker_url)
adapt_all(perpetual_output) + adapt_all(futures_output)
end

def ticker_url
def perpetual_ticker_url
"#{Cryptoexchange::Exchanges::BinanceFutures::Market::API_URL}/ticker/24hr"
end

def futures_ticker_url
"#{Cryptoexchange::Exchanges::BinanceFutures::Market::FUTURES_API_URL}/ticker/24hr"
end

def adapt_all(output)
pairs_map = {}
pairs = Cryptoexchange::Exchanges::BinanceFutures::Services::Pairs.new.fetch
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,17 @@ def supports_individual_ticker_query?
end

def fetch(market_pair)
output = super(order_book_url(market_pair))
root_api_url = if market_pair.contract_interval == "perpetual"
Cryptoexchange::Exchanges::BinanceFutures::Market::API_URL
elsif market_pair.contract_interval == "futures"
Cryptoexchange::Exchanges::BinanceFutures::Market::FUTURES_API_URL
end
output = super(order_book_url(root_api_url, market_pair))
adapt(output, market_pair)
end

def order_book_url(market_pair)
"#{Cryptoexchange::Exchanges::BinanceFutures::Market::API_URL}/depth?symbol=#{market_pair.inst_id}&limit=500"
def order_book_url(root_api_url, market_pair)
"#{root_api_url}/depth?symbol=#{market_pair.inst_id}&limit=500"
end

def adapt(output, market_pair)
Expand Down
19 changes: 13 additions & 6 deletions lib/cryptoexchange/exchanges/binance_futures/services/pairs.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,23 @@ module Cryptoexchange::Exchanges
module BinanceFutures
module Services
class Pairs < Cryptoexchange::Services::Pairs
PAIRS_URL = "#{Cryptoexchange::Exchanges::BinanceFutures::Market::API_URL}/exchangeInfo"
PERPETUAL_PAIRS_URL = "#{Cryptoexchange::Exchanges::BinanceFutures::Market::API_URL}/exchangeInfo"
FUTURES_PAIRS_URL = "#{Cryptoexchange::Exchanges::BinanceFutures::Market::FUTURES_API_URL}/exchangeInfo"

def fetch
output = super
adapt(output)
perpetual_output = fetch_via_api(PERPETUAL_PAIRS_URL)
futures_output = fetch_via_api(FUTURES_PAIRS_URL)
adapt(perpetual_output, :perpetual) + adapt(futures_output, :futures)
end

def adapt(output)
def adapt(output, type)
output["symbols"].map do |pair|
next if pair["status"] != "TRADING"

if type == :perpetual
next if pair["status"] != "TRADING"
elsif type == :futures
next if pair["contractStatus"] != "TRADING"
end

base = pair["baseAsset"]
target = pair["quoteAsset"]
Expand All @@ -21,7 +28,7 @@ def adapt(output)
base: base,
target: target,
market: BinanceFutures::Market::NAME,
contract_interval: "perpetual",
contract_interval: type.to_s,
inst_id: pair["symbol"]
)
end.compact
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Large diffs are not rendered by default.

Loading

0 comments on commit 2ad9b27

Please sign in to comment.