Commit 3ffe72e7 authored by harrylee's avatar harrylee Committed by vipwzw

ajust code for exchange

parent f28a7e39
...@@ -28,3 +28,23 @@ QueryOrderList|根据用户地址和订单状态(ordered,completed,revoked), ...@@ -28,3 +28,23 @@ QueryOrderList|根据用户地址和订单状态(ordered,completed,revoked),
4|价格相同按先进先出的原则进行撮合 4|价格相同按先进先出的原则进行撮合
5|出于系统安全考虑,最大撮合深度为100单,单笔挂单最小为1e8,就是一个bty 5|出于系统安全考虑,最大撮合深度为100单,单笔挂单最小为1e8,就是一个bty
**表结构说明**
表名|主键|索引|用途|说明
---|---|---|---|---
depth|price|nil|动态记录市场深度|主键price是复合主键由{leftAsset}:{rightAsset}:{op}:{price}构成
order|orderID|market_order,addr_status|实时动态维护更新市场上的挂单|market_order是复合索引由{leftAsset}:{rightAsset}:{op}:{price}:{orderID},addr_status是复合索引由{addr}:{status},当订单成交或者撤回时,该条订单记录和索引会从order表中自动删除
history|index|name,addr_status|实时记录某资产交易对下面最新完成的订单信息(revoked状态的交易也会记录)|name是复合索引由{leftAsset}:{rightAsset}构成, addr_status是复合索引由{addr}:{status}
**表中相关参数说明**
参数名|说明
----|----
leftAsset|交易对左边资产名称
rightAsset|交易对右边资产名称
op|买卖操作 1为买,2为卖
status|挂单状态,0 ordered, 1 completed,2 revoked
price|挂单价格,占位16 %016d,为了兼容不同架构的系统,这里设计为整型,由原有浮点型乘以1e8。 比如某交易对在中心化交易所上面是0.25,这里就变成25000000,price取值范围为1<=price<=1e16的整数
orderID|单号,由系统自动生成,整型,占位22 %022d
index|系统自动生成的index,占位22 %022d
...@@ -60,7 +60,7 @@ func (e *exchange) CheckTx(tx *types.Transaction, index int) error { ...@@ -60,7 +60,7 @@ func (e *exchange) CheckTx(tx *types.Transaction, index int) error {
limitOrder := exchange.GetLimitOrder() limitOrder := exchange.GetLimitOrder()
left := limitOrder.GetLeftAsset() left := limitOrder.GetLeftAsset()
right := limitOrder.GetRightAsset() right := limitOrder.GetRightAsset()
price := Truncate(limitOrder.GetPrice()) price := limitOrder.GetPrice()
amount := limitOrder.GetAmount() amount := limitOrder.GetAmount()
op := limitOrder.GetOp() op := limitOrder.GetOp()
if !CheckExchangeAsset(left, right) { if !CheckExchangeAsset(left, right) {
......
...@@ -105,7 +105,7 @@ func TestExchange(t *testing.T) { ...@@ -105,7 +105,7 @@ func TestExchange(t *testing.T) {
tx, err = types.FormatTx(cfg, et.ExchangeX, tx) tx, err = types.FormatTx(cfg, et.ExchangeX, tx)
assert.Nil(t, err) assert.Nil(t, err)
tx, err = signTx(tx, PrivKeyA) tx, err = signTx(tx, PrivKeyA)
t.Log(tx) //t.Log(tx)
assert.Nil(t, err) assert.Nil(t, err)
exec := newExchange() exec := newExchange()
e := exec.(*exchange) e := exec.(*exchange)
...@@ -317,7 +317,7 @@ func TestExchange(t *testing.T) { ...@@ -317,7 +317,7 @@ func TestExchange(t *testing.T) {
//反向测试 //反向测试
// orderlimit bty:CCNY 卖bty // orderlimit bty:CCNY 卖bty
tx, err = ety.Create("LimitOrder", &et.LimitOrder{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"}, tx, err = ety.Create("LimitOrder", &et.LimitOrder{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"},
RightAsset: &et.Asset{Execer: "paracross", Symbol: "coins.bty"}, Price: 0.5, Amount: 10 * types.Coin, Op: et.OpSell}) RightAsset: &et.Asset{Execer: "paracross", Symbol: "coins.bty"}, Price: 50000000, Amount: 10 * types.Coin, Op: et.OpSell})
assert.Nil(t, err) assert.Nil(t, err)
tx, err = types.FormatTx(cfg, et.ExchangeX, tx) tx, err = types.FormatTx(cfg, et.ExchangeX, tx)
assert.Nil(t, err) assert.Nil(t, err)
...@@ -365,7 +365,7 @@ func TestExchange(t *testing.T) { ...@@ -365,7 +365,7 @@ func TestExchange(t *testing.T) {
t.Log(reply) t.Log(reply)
tx, err = ety.Create("LimitOrder", &et.LimitOrder{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"}, tx, err = ety.Create("LimitOrder", &et.LimitOrder{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"},
RightAsset: &et.Asset{Execer: "paracross", Symbol: "coins.bty"}, Price: 0.5, Amount: 10 * types.Coin, Op: et.OpSell}) RightAsset: &et.Asset{Execer: "paracross", Symbol: "coins.bty"}, Price: 50000000, Amount: 10 * types.Coin, Op: et.OpSell})
assert.Nil(t, err) assert.Nil(t, err)
tx, err = types.FormatTx(cfg, et.ExchangeX, tx) tx, err = types.FormatTx(cfg, et.ExchangeX, tx)
assert.Nil(t, err) assert.Nil(t, err)
...@@ -434,7 +434,7 @@ func TestExchange(t *testing.T) { ...@@ -434,7 +434,7 @@ func TestExchange(t *testing.T) {
assert.Equal(t, orderID4, reply2.List[0].OrderID) assert.Equal(t, orderID4, reply2.List[0].OrderID)
tx, err = ety.Create("LimitOrder", &et.LimitOrder{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"}, tx, err = ety.Create("LimitOrder", &et.LimitOrder{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"},
RightAsset: &et.Asset{Execer: "paracross", Symbol: "coins.bty"}, Price: 0.5, Amount: 20 * types.Coin, Op: et.OpBuy}) RightAsset: &et.Asset{Execer: "paracross", Symbol: "coins.bty"}, Price: 50000000, Amount: 20 * types.Coin, Op: et.OpBuy})
assert.Nil(t, err) assert.Nil(t, err)
tx, err = types.FormatTx(cfg, et.ExchangeX, tx) tx, err = types.FormatTx(cfg, et.ExchangeX, tx)
assert.Nil(t, err) assert.Nil(t, err)
...@@ -504,7 +504,7 @@ func TestExchange(t *testing.T) { ...@@ -504,7 +504,7 @@ func TestExchange(t *testing.T) {
// orderlimit bty:CCNY ,先挂买单,然后低于市场价格卖出 // orderlimit bty:CCNY ,先挂买单,然后低于市场价格卖出
tx, err = ety.Create("LimitOrder", &et.LimitOrder{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"}, tx, err = ety.Create("LimitOrder", &et.LimitOrder{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"},
RightAsset: &et.Asset{Execer: "token", Symbol: "CCNY"}, Price: 4, Amount: 5 * types.Coin, Op: et.OpBuy}) RightAsset: &et.Asset{Execer: "token", Symbol: "CCNY"}, Price: 400000000, Amount: 5 * types.Coin, Op: et.OpBuy})
assert.Nil(t, err) assert.Nil(t, err)
tx, err = types.FormatTx(cfg, et.ExchangeX, tx) tx, err = types.FormatTx(cfg, et.ExchangeX, tx)
assert.Nil(t, err) assert.Nil(t, err)
...@@ -555,7 +555,7 @@ func TestExchange(t *testing.T) { ...@@ -555,7 +555,7 @@ func TestExchange(t *testing.T) {
} }
tx, err = ety.Create("LimitOrder", &et.LimitOrder{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"}, tx, err = ety.Create("LimitOrder", &et.LimitOrder{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"},
RightAsset: &et.Asset{Execer: "token", Symbol: "CCNY"}, Price: 3, Amount: 10 * types.Coin, Op: et.OpSell}) RightAsset: &et.Asset{Execer: "token", Symbol: "CCNY"}, Price: 300000000, Amount: 10 * types.Coin, Op: et.OpSell})
assert.Nil(t, err) assert.Nil(t, err)
tx, err = types.FormatTx(cfg, et.ExchangeX, tx) tx, err = types.FormatTx(cfg, et.ExchangeX, tx)
assert.Nil(t, err) assert.Nil(t, err)
...@@ -638,7 +638,7 @@ func TestExchange(t *testing.T) { ...@@ -638,7 +638,7 @@ func TestExchange(t *testing.T) {
// orderlimit bty:CCNY ,先挂卖单,然后高于市场价格买入, 买家获利原则 // orderlimit bty:CCNY ,先挂卖单,然后高于市场价格买入, 买家获利原则
tx, err = ety.Create("LimitOrder", &et.LimitOrder{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"}, tx, err = ety.Create("LimitOrder", &et.LimitOrder{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"},
RightAsset: &et.Asset{Execer: "token", Symbol: "CCNY"}, Price: 4, Amount: 5 * types.Coin, Op: et.OpSell}) RightAsset: &et.Asset{Execer: "token", Symbol: "CCNY"}, Price: 400000000, Amount: 5 * types.Coin, Op: et.OpSell})
assert.Nil(t, err) assert.Nil(t, err)
tx, err = types.FormatTx(cfg, et.ExchangeX, tx) tx, err = types.FormatTx(cfg, et.ExchangeX, tx)
assert.Nil(t, err) assert.Nil(t, err)
...@@ -678,7 +678,7 @@ func TestExchange(t *testing.T) { ...@@ -678,7 +678,7 @@ func TestExchange(t *testing.T) {
orderID8 := orderList.List[0].OrderID orderID8 := orderList.List[0].OrderID
tx, err = ety.Create("LimitOrder", &et.LimitOrder{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"}, tx, err = ety.Create("LimitOrder", &et.LimitOrder{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"},
RightAsset: &et.Asset{Execer: "token", Symbol: "CCNY"}, Price: 5, Amount: 5 * types.Coin, Op: et.OpSell}) RightAsset: &et.Asset{Execer: "token", Symbol: "CCNY"}, Price: 500000000, Amount: 5 * types.Coin, Op: et.OpSell})
assert.Nil(t, err) assert.Nil(t, err)
tx, err = types.FormatTx(cfg, et.ExchangeX, tx) tx, err = types.FormatTx(cfg, et.ExchangeX, tx)
assert.Nil(t, err) assert.Nil(t, err)
...@@ -717,7 +717,7 @@ func TestExchange(t *testing.T) { ...@@ -717,7 +717,7 @@ func TestExchange(t *testing.T) {
orderList = msg.(*et.OrderList) orderList = msg.(*et.OrderList)
orderID9 := orderList.List[0].OrderID orderID9 := orderList.List[0].OrderID
tx, err = ety.Create("LimitOrder", &et.LimitOrder{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"}, tx, err = ety.Create("LimitOrder", &et.LimitOrder{LeftAsset: &et.Asset{Symbol: "bty", Execer: "coins"},
RightAsset: &et.Asset{Execer: "token", Symbol: "CCNY"}, Price: 4.5, Amount: 15 * types.Coin, Op: et.OpBuy}) RightAsset: &et.Asset{Execer: "token", Symbol: "CCNY"}, Price: 450000000, Amount: 15 * types.Coin, Op: et.OpBuy})
assert.Nil(t, err) assert.Nil(t, err)
tx, err = types.FormatTx(cfg, et.ExchangeX, tx) tx, err = types.FormatTx(cfg, et.ExchangeX, tx)
assert.Nil(t, err) assert.Nil(t, err)
...@@ -812,22 +812,11 @@ func signTx(tx *types.Transaction, hexPrivKey string) (*types.Transaction, error ...@@ -812,22 +812,11 @@ func signTx(tx *types.Transaction, hexPrivKey string) (*types.Transaction, error
return tx, nil return tx, nil
} }
func TestTruncate(t *testing.T) {
a := float64(1.00000212000000000001)
b := float64(0.34567)
c := float64(1234567)
t.Log(Truncate(a))
t.Log(Truncate(b))
t.Log(Truncate(c))
t.Log(float64(1.00000212000000000001))
t.Logf("%f", Truncate(float64(1e8)))
t.Log(Truncate(float64(1e-8)))
}
func TestCheckPrice(t *testing.T) { func TestCheckPrice(t *testing.T) {
t.Log(CheckPrice(Truncate(float64(1e8)))) t.Log(CheckPrice(1e8))
t.Log(CheckPrice(Truncate(float64(1e-8)))) t.Log(CheckPrice(-1))
t.Log(CheckPrice(Truncate(float64(1e-9)))) t.Log(CheckPrice(1e17))
t.Log(CheckPrice(0))
} }
func TestRawMeta(t *testing.T) { func TestRawMeta(t *testing.T) {
...@@ -843,3 +832,9 @@ func TestKV(t *testing.T) { ...@@ -843,3 +832,9 @@ func TestKV(t *testing.T) {
a := &types.KeyValue{Key: []byte("1111111"), Value: nil} a := &types.KeyValue{Key: []byte("1111111"), Value: nil}
t.Log(a.Key, a.Value) t.Log(a.Key, a.Value)
} }
func TestSafeMul(t *testing.T) {
t.Log(SafeMul(1e8, 1e7))
t.Log(SafeMul(1e10, 1e16))
t.Log(SafeMul(1e7, 1e6))
}
This diff is collapsed.
This diff is collapsed.
...@@ -10,9 +10,6 @@ func (s *exchange) Query_QueryMarketDepth(in *et.QueryMarketDepth) (types.Messag ...@@ -10,9 +10,6 @@ func (s *exchange) Query_QueryMarketDepth(in *et.QueryMarketDepth) (types.Messag
if !CheckCount(in.Count) { if !CheckCount(in.Count) {
return nil, et.ErrCount return nil, et.ErrCount
} }
if in.Count == 0 {
in.Count = 10
}
if !CheckExchangeAsset(in.LeftAsset, in.RightAsset) { if !CheckExchangeAsset(in.LeftAsset, in.RightAsset) {
return nil, et.ErrAsset return nil, et.ErrAsset
} }
...@@ -28,7 +25,7 @@ func (s *exchange) Query_QueryHistoryOrderList(in *et.QueryHistoryOrderList) (ty ...@@ -28,7 +25,7 @@ func (s *exchange) Query_QueryHistoryOrderList(in *et.QueryHistoryOrderList) (ty
if !CheckExchangeAsset(in.LeftAsset, in.RightAsset) { if !CheckExchangeAsset(in.LeftAsset, in.RightAsset) {
return nil, et.ErrAsset return nil, et.ErrAsset
} }
if in.Count > 20 { if !CheckCount(in.Count) {
return nil, et.ErrCount return nil, et.ErrCount
} }
...@@ -62,5 +59,5 @@ func (s *exchange) Query_QueryOrderList(in *et.QueryOrderList) (types.Message, e ...@@ -62,5 +59,5 @@ func (s *exchange) Query_QueryOrderList(in *et.QueryOrderList) (types.Message, e
if in.Address == "" { if in.Address == "" {
return nil, et.ErrAddr return nil, et.ErrAddr
} }
return QueryOrderList(s.GetLocalDB(), s.GetStateDB(), in.Address, in.Status, in.Count, in.Direction, in.PrimaryKey) return QueryOrderList(s.GetLocalDB(), in.Address, in.Status, in.Count, in.Direction, in.PrimaryKey)
} }
...@@ -107,7 +107,7 @@ func (r *OrderRow) Get(key string) ([]byte, error) { ...@@ -107,7 +107,7 @@ func (r *OrderRow) Get(key string) ([]byte, error) {
if key == "orderID" { if key == "orderID" {
return []byte(fmt.Sprintf("%022d", r.OrderID)), nil return []byte(fmt.Sprintf("%022d", r.OrderID)), nil
} else if key == "market_order" { } else if key == "market_order" {
return []byte(fmt.Sprintf("%s:%s:%d:%016d", r.GetLimitOrder().LeftAsset.GetSymbol(), r.GetLimitOrder().RightAsset.GetSymbol(), r.GetLimitOrder().Op, int64(Truncate(r.GetLimitOrder().Price*float64(1e8))))), nil return []byte(fmt.Sprintf("%s:%s:%d:%016d", r.GetLimitOrder().LeftAsset.GetSymbol(), r.GetLimitOrder().RightAsset.GetSymbol(), r.GetLimitOrder().Op, r.GetLimitOrder().Price)), nil
} else if key == "addr_status" { } else if key == "addr_status" {
return []byte(fmt.Sprintf("%s:%d", r.Addr, r.Status)), nil return []byte(fmt.Sprintf("%s:%d", r.Addr, r.Status)), nil
} }
...@@ -175,7 +175,7 @@ func (m *MarketDepthRow) SetPayload(data types.Message) error { ...@@ -175,7 +175,7 @@ func (m *MarketDepthRow) SetPayload(data types.Message) error {
//Get 按照indexName 查询 indexValue //Get 按照indexName 查询 indexValue
func (m *MarketDepthRow) Get(key string) ([]byte, error) { func (m *MarketDepthRow) Get(key string) ([]byte, error) {
if key == "price" { if key == "price" {
return []byte(fmt.Sprintf("%s:%s:%d:%016d", m.LeftAsset.GetSymbol(), m.RightAsset.GetSymbol(), m.Op, int64(Truncate(m.Price)*float64(1e8)))), nil return []byte(fmt.Sprintf("%s:%s:%d:%016d", m.LeftAsset.GetSymbol(), m.RightAsset.GetSymbol(), m.Op, m.Price)), nil
} }
return nil, types.ErrNotFound return nil, types.ErrNotFound
} }
...@@ -19,7 +19,7 @@ message LimitOrder { ...@@ -19,7 +19,7 @@ message LimitOrder {
//交易对 //交易对
asset rightAsset = 2; asset rightAsset = 2;
//价格 //价格
double price = 3; int64 price = 3;
//总量 //总量
int64 amount = 4; int64 amount = 4;
//操作, 1为买,2为卖 //操作, 1为买,2为卖
...@@ -60,16 +60,18 @@ message Order { ...@@ -60,16 +60,18 @@ message Order {
int32 ty = 4; int32 ty = 4;
//已经成交的数量 //已经成交的数量
int64 executed = 5; int64 executed = 5;
//成交均价
int64 AVG_price = 6;
//余额 //余额
int64 balance = 6; int64 balance = 7;
//状态,0 挂单中ordered, 1 完成completed, 2撤回 revoked //状态,0 挂单中ordered, 1 完成completed, 2撤回 revoked
int32 status = 7; int32 status = 8;
//用户地址 //用户地址
string addr = 8; string addr = 9;
//更新时间 //更新时间
int64 updateTime = 9; int64 updateTime = 10;
//索引 //索引
int64 index = 10; int64 index = 11;
} }
//查询接口 //查询接口
...@@ -92,7 +94,7 @@ message MarketDepth { ...@@ -92,7 +94,7 @@ message MarketDepth {
//资产2 //资产2
asset rightAsset = 2; asset rightAsset = 2;
//价格 //价格
double price = 3; int64 price = 3;
//总量 //总量
int64 amount = 4; int64 amount = 4;
//操作, 1为买,2为卖 //操作, 1为买,2为卖
......
...@@ -59,9 +59,9 @@ const ( ...@@ -59,9 +59,9 @@ const (
const ( const (
//单次list还回条数 //单次list还回条数
Count = int32(5) Count = int32(10)
//系统最大撮合深度 //系统最大撮合深度
MaxCount = 100 MaxMatchCount = 100
) )
var ( var (
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment