diff --git a/broker.go b/broker.go index 6ea2be9..61a64e8 100644 --- a/broker.go +++ b/broker.go @@ -11,10 +11,12 @@ type Broker interface { GetOrderBook(symbol string, depth int) (result OrderBook, err error) // 设置合约类型 - SetContractType(contractType string) (err error) + // pair: 交易对,如: BTC-USD(OKEX) BTC(HBDM) + // contractType: W1,W2,Q1,Q2 + SetContractType(pair string, contractType string) (err error) // 获取当前设置的合约ID - GetContractType() (symbol string, err error) + GetContractID() (symbol string, err error) // 设置杠杆大小 SetLeverRate(value float64) (err error) diff --git a/brokers/bitmex-broker/broker.go b/brokers/bitmex-broker/broker.go index d2fb39c..f3a997f 100644 --- a/brokers/bitmex-broker/broker.go +++ b/brokers/bitmex-broker/broker.go @@ -50,11 +50,11 @@ func (b *BitMEXBroker) GetOrderBook(symbol string, depth int) (result OrderBook, return } -func (b *BitMEXBroker) SetContractType(contractType string) (err error) { +func (b *BitMEXBroker) SetContractType(pair string, contractType string) (err error) { return } -func (b *BitMEXBroker) GetContractType() (symbol string, err error) { +func (b *BitMEXBroker) GetContractID() (symbol string, err error) { return } diff --git a/brokers/bitmex-sim-broker/simbroker.go b/brokers/bitmex-sim-broker/broker.go similarity index 98% rename from brokers/bitmex-sim-broker/simbroker.go rename to brokers/bitmex-sim-broker/broker.go index b981617..cf5294b 100644 --- a/brokers/bitmex-sim-broker/simbroker.go +++ b/brokers/bitmex-sim-broker/broker.go @@ -64,11 +64,11 @@ func (b *BitMEXSimBroker) GetOrderBook(symbol string, depth int) (result OrderBo return } -func (b *BitMEXSimBroker) SetContractType(contractType string) (err error) { +func (b *BitMEXSimBroker) SetContractType(pair string, contractType string) (err error) { return } -func (b *BitMEXSimBroker) GetContractType() (symbol string, err error) { +func (b *BitMEXSimBroker) GetContractID() (symbol string, err error) { return } @@ -337,7 +337,7 @@ func (b *BitMEXSimBroker) getPosition(symbol string) *Position { } else { position = &Position{ Symbol: symbol, - OpenI: time.Time{}, + OpenTime: time.Time{}, OpenPrice: 0, Size: 0, AvgPrice: 0, diff --git a/brokers/bybit-broker/broker.go b/brokers/bybit-broker/broker.go index 7505102..be15ec2 100644 --- a/brokers/bybit-broker/broker.go +++ b/brokers/bybit-broker/broker.go @@ -55,11 +55,11 @@ func (b *BybitBroker) GetOrderBook(symbol string, depth int) (result OrderBook, return } -func (b *BybitBroker) SetContractType(contractType string) (err error) { +func (b *BybitBroker) SetContractType(pair string, contractType string) (err error) { return } -func (b *BybitBroker) GetContractType() (symbol string, err error) { +func (b *BybitBroker) GetContractID() (symbol string, err error) { return } diff --git a/brokers/deribit-broker/broker.go b/brokers/deribit-broker/broker.go index 0ce8587..3881ee3 100644 --- a/brokers/deribit-broker/broker.go +++ b/brokers/deribit-broker/broker.go @@ -94,11 +94,11 @@ func (b *DiribitBroker) GetOrderBook(symbol string, depth int) (result OrderBook return } -func (b *DiribitBroker) SetContractType(contractType string) (err error) { +func (b *DiribitBroker) SetContractType(pair string, contractType string) (err error) { return } -func (b *DiribitBroker) GetContractType() (symbol string, err error) { +func (b *DiribitBroker) GetContractID() (symbol string, err error) { return } diff --git a/brokers/deribit-sim-broker/simbroker.go b/brokers/deribit-sim-broker/broker.go similarity index 98% rename from brokers/deribit-sim-broker/simbroker.go rename to brokers/deribit-sim-broker/broker.go index f8cd5fc..5f35a17 100644 --- a/brokers/deribit-sim-broker/simbroker.go +++ b/brokers/deribit-sim-broker/broker.go @@ -66,11 +66,11 @@ func (b *DiribitSimBroker) GetOrderBook(symbol string, depth int) (result OrderB return } -func (b *DiribitSimBroker) SetContractType(contractType string) (err error) { +func (b *DiribitSimBroker) SetContractType(pair string, contractType string) (err error) { return } -func (b *DiribitSimBroker) GetContractType() (symbol string, err error) { +func (b *DiribitSimBroker) GetContractID() (symbol string, err error) { return } @@ -345,7 +345,7 @@ func (b *DiribitSimBroker) getPosition(symbol string) *Position { } else { position = &Position{ Symbol: symbol, - OpenI: time.Time{}, + OpenTime: time.Time{}, OpenPrice: 0, Size: 0, AvgPrice: 0, diff --git a/brokers/deribit-sim-broker/simbroker_test.go b/brokers/deribit-sim-broker/broker_test.go similarity index 100% rename from brokers/deribit-sim-broker/simbroker_test.go rename to brokers/deribit-sim-broker/broker_test.go diff --git a/brokers/hbdm-broker/broker.go b/brokers/hbdm-broker/broker.go index 3afb79e..538b745 100644 --- a/brokers/hbdm-broker/broker.go +++ b/brokers/hbdm-broker/broker.go @@ -11,18 +11,20 @@ import ( const StatusOK = "ok" -// HuobiBroker the Huobi broker -type HuobiBroker struct { - client *hbdm.Client - contractType string // 合约类型 - leverRate int // 杠杆倍数 +// HBDMBroker the Huobi DM broker +type HBDMBroker struct { + client *hbdm.Client + pair string // 交易对 BTC/ETH/... + _contractType string // 合约类型 + contractType string // 合约类型(HBDM) + leverRate int // 杠杆倍数 } -func (b *HuobiBroker) Subscribe(event string, param string, listener interface{}) { +func (b *HBDMBroker) Subscribe(event string, param string, listener interface{}) { } -func (b *HuobiBroker) GetAccountSummary(currency string) (result AccountSummary, err error) { +func (b *HBDMBroker) GetAccountSummary(currency string) (result AccountSummary, err error) { var account hbdm.AccountInfoResult account, err = b.client.GetAccountInfo(currency) if err != nil { @@ -46,7 +48,7 @@ func (b *HuobiBroker) GetAccountSummary(currency string) (result AccountSummary, return } -func (b *HuobiBroker) GetOrderBook(symbol string, depth int) (result OrderBook, err error) { +func (b *HBDMBroker) GetOrderBook(symbol string, depth int) (result OrderBook, err error) { var ret hbdm.MarketDepthResult ret, err = b.client.GetMarketDepth(b.contractType, "step0") @@ -74,23 +76,49 @@ func (b *HuobiBroker) GetOrderBook(symbol string, depth int) (result OrderBook, } // 设置合约类型 -// 如"BTC_CW"表示BTC当周合约,"BTC_NW"表示BTC次周合约,"BTC_CQ"表示BTC季度合约 -func (b *HuobiBroker) SetContractType(contractType string) (err error) { - b.contractType = contractType +// pair: BTC/ETH/... +func (b *HBDMBroker) SetContractType(pair string, contractType string) (err error) { + // // 如"BTC_CW"表示BTC当周合约,"BTC_NW"表示BTC次周合约,"BTC_CQ"表示BTC季度合约 + b.pair = pair + b._contractType = contractType + var contractAlias string + switch contractType { + case ContractTypeNone: + case ContractTypeW1: + contractAlias = "this_week" + case ContractTypeW2: + contractAlias = "next_week" + case ContractTypeQ1: + contractAlias = "quarter" + } + b.contractType = contractAlias return } -func (b *HuobiBroker) GetContractType() (symbol string, err error) { - return +func (b *HBDMBroker) GetContractID() (symbol string, err error) { + var ret hbdm.ContractInfoResult + ret, err = b.client.GetContractInfo(b.pair, b.contractType, "") + if err != nil { + return + } + for _, v := range ret.Data { + // log.Printf("%#v", v) + if v.Symbol == b.pair && + v.ContractType == b.contractType { + symbol = v.ContractCode + return + } + } + return "", fmt.Errorf("not found") } // 设置杠杆大小 -func (b *HuobiBroker) SetLeverRate(value float64) (err error) { +func (b *HBDMBroker) SetLeverRate(value float64) (err error) { b.leverRate = int(value) return } -func (b *HuobiBroker) PlaceOrder(symbol string, direction Direction, orderType OrderType, price float64, +func (b *HBDMBroker) PlaceOrder(symbol string, direction Direction, orderType OrderType, price float64, stopPx float64, size float64, postOnly bool, reduceOnly bool) (result Order, err error) { var orderResult hbdm.OrderResult var _direction string @@ -154,7 +182,7 @@ func (b *HuobiBroker) PlaceOrder(symbol string, direction Direction, orderType O return } -func (b *HuobiBroker) GetOpenOrders(symbol string) (result []Order, err error) { +func (b *HBDMBroker) GetOpenOrders(symbol string) (result []Order, err error) { var ret hbdm.OpenOrdersResult ret, err = b.client.GetOpenOrders( symbol, @@ -174,7 +202,7 @@ func (b *HuobiBroker) GetOpenOrders(symbol string) (result []Order, err error) { return } -func (b *HuobiBroker) GetOrder(symbol string, id string) (result Order, err error) { +func (b *HBDMBroker) GetOrder(symbol string, id string) (result Order, err error) { var ret hbdm.OrderInfoResult var _id, _ = strconv.ParseInt(id, 10, 64) ret, err = b.client.OrderInfo(symbol, _id, 0) @@ -193,7 +221,7 @@ func (b *HuobiBroker) GetOrder(symbol string, id string) (result Order, err erro return } -func (b *HuobiBroker) CancelOrder(symbol string, id string) (result Order, err error) { +func (b *HBDMBroker) CancelOrder(symbol string, id string) (result Order, err error) { var ret hbdm.CancelResult var _id, _ = strconv.ParseInt(id, 10, 64) ret, err = b.client.Cancel(symbol, _id, 0) @@ -209,15 +237,15 @@ func (b *HuobiBroker) CancelOrder(symbol string, id string) (result Order, err e return } -func (b *HuobiBroker) CancelAllOrders(symbol string) (err error) { +func (b *HBDMBroker) CancelAllOrders(symbol string) (err error) { return } -func (b *HuobiBroker) AmendOrder(symbol string, id string, price float64, size float64) (result Order, err error) { +func (b *HBDMBroker) AmendOrder(symbol string, id string, price float64, size float64) (result Order, err error) { return } -func (b *HuobiBroker) GetPosition(symbol string) (result Position, err error) { +func (b *HBDMBroker) GetPosition(symbol string) (result Position, err error) { result.Symbol = symbol var ret hbdm.PositionInfoResult @@ -235,19 +263,18 @@ func (b *HuobiBroker) GetPosition(symbol string) (result Position, err error) { return } - //position := ret.Data[0] - - //if position > 0 { - // result.Size = position.BuyAmount - // result.AvgPrice = position.BuyPriceAvg - //} else if position.SellAmount > 0 { - // result.Size = -position.SellAmount - // result.AvgPrice = position.SellPriceAvg - //} + position := ret.Data[0] + if position.Direction == "buy" { + result.Size = position.Volume + } else if position.Direction == "sell" { + result.Size = -position.Volume + } + result.AvgPrice = position.CostHold + result.OpenPrice = position.CostOpen return } -func (b *HuobiBroker) convertOrder(symbol string, order *hbdm.Order) (result Order) { +func (b *HBDMBroker) convertOrder(symbol string, order *hbdm.Order) (result Order) { result.ID = order.OrderIDStr result.Symbol = symbol result.Price = order.Price @@ -267,7 +294,7 @@ func (b *HuobiBroker) convertOrder(symbol string, order *hbdm.Order) (result Ord return } -func (b *HuobiBroker) orderDirection(order *hbdm.Order) Direction { +func (b *HBDMBroker) orderDirection(order *hbdm.Order) Direction { if order.Direction == "buy" { return Buy } else if order.Direction == "sell" { @@ -276,7 +303,7 @@ func (b *HuobiBroker) orderDirection(order *hbdm.Order) Direction { return Buy } -func (b *HuobiBroker) orderType(order *hbdm.Order) OrderType { +func (b *HBDMBroker) orderType(order *hbdm.Order) OrderType { /* order_price_type 订单报价类型 订单报价类型 订单报价类型 "limit":限价 "opponent":对手价 "post_only":只做maker单,post only下单只受用户持仓数量限制,optimal_5:最优5档、optimal_10:最优10档、optimal_20:最优20档,ioc:IOC订单,fok:FOK订单 */ @@ -293,7 +320,7 @@ func (b *HuobiBroker) orderType(order *hbdm.Order) OrderType { return OrderTypeLimit } -func (b *HuobiBroker) orderStatus(order *hbdm.Order) OrderStatus { +func (b *HBDMBroker) orderStatus(order *hbdm.Order) OrderStatus { /* 订单状态 (1准备提交 2准备提交 3已提交 4部分成交 5部分成交已撤单 6全部成交 7已撤单 11撤单中) @@ -316,11 +343,11 @@ func (b *HuobiBroker) orderStatus(order *hbdm.Order) OrderStatus { } } -func (b *HuobiBroker) RunEventLoopOnce() (err error) { +func (b *HBDMBroker) RunEventLoopOnce() (err error) { return } -func NewBroker(addr string, accessKey string, secretKey string) *HuobiBroker { +func NewBroker(addr string, accessKey string, secretKey string) *HBDMBroker { //baseURL := "https://api.hbdm.com" apiParams := &hbdm.ApiParameter{ Debug: false, @@ -331,7 +358,7 @@ func NewBroker(addr string, accessKey string, secretKey string) *HuobiBroker { PrivateKeyPrime256: "", } client := hbdm.NewClient(apiParams) - return &HuobiBroker{ + return &HBDMBroker{ client: client, } } diff --git a/brokers/hbdm-broker/broker_test.go b/brokers/hbdm-broker/broker_test.go index 2f9d1d8..6734517 100644 --- a/brokers/hbdm-broker/broker_test.go +++ b/brokers/hbdm-broker/broker_test.go @@ -21,7 +21,7 @@ func newTestBroker() Broker { return NewBroker(baseURL, accessKey, secretKey) } -func TestHuobiBroker_GetAccountSummary(t *testing.T) { +func TestHBDMBroker_GetAccountSummary(t *testing.T) { b := newTestBroker() accountSummary, err := b.GetAccountSummary("BTC") if err != nil { @@ -30,3 +30,14 @@ func TestHuobiBroker_GetAccountSummary(t *testing.T) { } t.Logf("%#v", accountSummary) } + +func TestHBDMBroker_GetContractID(t *testing.T) { + b := newTestBroker() + b.SetContractType("BTC", ContractTypeW1) + symbol, err := b.GetContractID() + if err != nil { + t.Error(err) + return + } + t.Logf("%v", symbol) +} diff --git a/brokers/okex-broker/broker.go b/brokers/okex-broker/broker.go index c749aab..1957d68 100644 --- a/brokers/okex-broker/broker.go +++ b/brokers/okex-broker/broker.go @@ -11,9 +11,11 @@ import ( // OKEXBroker the OKEX broker type OKEXBroker struct { - client *okex.Client - contractType string // 合约类型 - leverRate int // 杠杆倍数 + client *okex.Client + pair string // contract pair 合约交易对 + contractType string // contract type 合约类型 + contractAlias string // okex contract type 合约类型 + leverRate int // lever rate 杠杆倍数 } func (b *OKEXBroker) Subscribe(event string, param string, listener interface{}) { @@ -66,13 +68,42 @@ func (b *OKEXBroker) GetOrderBook(symbol string, depth int) (result OrderBook, e } // 设置合约类型 -func (b *OKEXBroker) SetContractType(contractType string) (err error) { +// pair: BTC-USD +// contractType: W1,W2,Q1,Q2,... +func (b *OKEXBroker) SetContractType(pair string, contractType string) (err error) { + b.pair = pair b.contractType = contractType + var contractAlias string + switch contractType { + case ContractTypeNone: + case ContractTypeW1: + contractAlias = "this_week" + case ContractTypeW2: + contractAlias = "next_week" + case ContractTypeQ1: + contractAlias = "quarter" + case ContractTypeQ2: + contractAlias = "bi_quarter" + } + b.contractAlias = contractAlias return } -func (b *OKEXBroker) GetContractType() (symbol string, err error) { - return +func (b *OKEXBroker) GetContractID() (symbol string, err error) { + var ret []okex.FuturesInstrumentsResult + ret, err = b.client.GetFuturesInstruments() + if err != nil { + return + } + for _, v := range ret { + //log.Printf("%v %v %#v", v.Alias, v.InstrumentId, v) + if v.Underlying == b.pair && + v.Alias == b.contractAlias { + symbol = v.InstrumentId + return + } + } + return "", fmt.Errorf("not found") } // 设置杠杆大小 @@ -134,7 +165,7 @@ func (b *OKEXBroker) PlaceOrder(symbol string, direction Direction, orderType Or func (b *OKEXBroker) GetOpenOrders(symbol string) (result []Order, err error) { // 6: 未完成(等待成交+部分成交) - // 7:已完成(撤单成功+完全成交) + // 7: 已完成(撤单成功+完全成交) var ret okex.FuturesGetOrdersResult ret, err = b.client.GetFuturesOrders(symbol, 6, "", "", 100) if err != nil { @@ -206,11 +237,11 @@ func (b *OKEXBroker) GetPosition(symbol string) (result Position, err error) { if v.LongQty > 0 { result.Size = v.LongQty result.AvgPrice = v.LongAvgCost - result.OpenI = createAt + result.OpenTime = createAt } else if v.ShortQty > 0 { result.Size = -v.ShortQty result.AvgPrice = v.ShortAvgCost - result.OpenI = createAt + result.OpenTime = createAt } break } @@ -225,11 +256,11 @@ func (b *OKEXBroker) GetPosition(symbol string) (result Position, err error) { if v.LongQty > 0 { result.Size = v.LongQty result.AvgPrice = v.LongAvgCost - result.OpenI = createAt + result.OpenTime = createAt } else if v.ShortQty > 0 { result.Size = -v.ShortQty result.AvgPrice = v.ShortAvgCost - result.OpenI = createAt + result.OpenTime = createAt } break } diff --git a/brokers/okex-broker/broker_test.go b/brokers/okex-broker/broker_test.go index 42682a2..336f976 100644 --- a/brokers/okex-broker/broker_test.go +++ b/brokers/okex-broker/broker_test.go @@ -59,6 +59,17 @@ func TestGetOrderBook(t *testing.T) { //t.Logf("Time: %v", ob.Time) } +func TestOKEXBroker_GetContractID(t *testing.T) { + b := newTestBroker() + b.SetContractType("BTC-USD", ContractTypeW1) + symbol, err := b.GetContractID() + if err != nil { + t.Error(err) + return + } + t.Logf("%v", symbol) +} + func TestOKEXBroker_PlaceOrder(t *testing.T) { b := newTestBroker() symbol := "BTC-USD-200327" diff --git a/consts.go b/consts.go index 57ddab8..776aa81 100644 --- a/consts.go +++ b/consts.go @@ -105,3 +105,13 @@ func (s OrderStatus) String() string { return "None" } } + +// ContractType 合约类型 +const ( + ContractTypeNone = "" // Non-delivery contract 非交割合约 + ContractTypeW1 = "W1" // week 当周合约 + ContractTypeW2 = "W2" // two week 次周合约 + ContractTypeM1 = "M1" // month 月合约 + ContractTypeQ1 = "Q1" // quarter 季度合约 + ContractTypeQ2 = "Q2" // two quarter 次季度合约 +) diff --git a/position.go b/position.go index c23b800..8a1a859 100644 --- a/position.go +++ b/position.go @@ -5,7 +5,7 @@ import "time" // Position 持仓 type Position struct { Symbol string `json:"symbol"` // 标 - OpenI time.Time `json:"open_i"` // 开仓时间 + OpenTime time.Time `json:"open_time"` // 开仓时间 OpenPrice float64 `json:"open_price"` // 开仓价 Size float64 `json:"size"` // 仓位大小 AvgPrice float64 `json:"avg_price"` // 平均价