Skip to content

Commit 145a3d1

Browse files
committed
finalise decoder
1 parent 91aba2e commit 145a3d1

File tree

3 files changed

+72
-23
lines changed

3 files changed

+72
-23
lines changed

pkg/datasource/csvsource/csv_tick_decoder.go

Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ package csvsource
22

33
import (
44
"encoding/csv"
5+
"fmt"
6+
"math/big"
7+
"strconv"
8+
"strings"
59

610
"github.com/c9s/bbgo/pkg/fixedpoint"
711
"github.com/c9s/bbgo/pkg/types"
@@ -23,14 +27,34 @@ func BinanceCSVTickDecoder(row []string, _ int) (*CsvTick, error) {
2327
if len(row) < 7 {
2428
return nil, ErrNotEnoughColumns
2529
}
26-
size := fixedpoint.MustNewFromString(row[2])
30+
// example csv row
31+
// id, price, qty, base_qty, time, is_buyer_maker,
32+
// 11782578,6.00000000,1.00000000,14974844,14974844,1698623884463,True
33+
qty := fixedpoint.MustNewFromString(row[2])
34+
baseQty := fixedpoint.MustNewFromString(row[2])
2735
price := fixedpoint.MustNewFromString(row[1])
28-
hn := price.Mul(size)
36+
// isBuyerMaker=false trade will qualify as BUY.
37+
id, err := strconv.ParseUint(row[0], 10, 64)
38+
if err != nil {
39+
return nil, err
40+
}
41+
isBuyerMaker, err := strconv.ParseBool(row[5])
42+
if err != nil {
43+
return nil, err
44+
}
45+
side := types.SideTypeBuy
46+
if isBuyerMaker {
47+
side = types.SideTypeSell
48+
}
2949
return &CsvTick{
30-
Timestamp: types.MustParseMillisecondTimestamp(row[5]),
31-
Size: size,
32-
Price: price,
33-
HomeNotional: hn,
50+
TradeID: id,
51+
Exchange: types.ExchangeBinance,
52+
Side: side,
53+
Size: qty,
54+
Price: price,
55+
HomeNotional: price.Mul(qty),
56+
ForeignNotional: price.Mul(baseQty),
57+
Timestamp: types.MustParseMillisecondTimestamp(row[5]),
3458
}, nil
3559
}
3660

@@ -44,6 +68,9 @@ func NewBybitCSVTickReader(csv *csv.Reader) *CSVTickReader {
4468

4569
// BybitCSVTickDecoder decodes a CSV record from Bybit into a CsvTick.
4670
func BybitCSVTickDecoder(row []string, index int) (*CsvTick, error) {
71+
// example csv row
72+
// timestamp,symbol,side,size,price,tickDirection,trdMatchID,grossValue,homeNotional,foreignNotional
73+
// 1649054912,FXSUSDT,Buy,0.01,38.32,PlusTick,9c30abaf-80ae-5ebf-9850-58fe7ed4bac8,3.832e+07,0.01,0.3832
4774
if len(row) < 9 {
4875
return nil, ErrNotEnoughColumns
4976
}
@@ -54,14 +81,33 @@ func BybitCSVTickDecoder(row []string, index int) (*CsvTick, error) {
5481
if err != nil {
5582
return nil, ErrInvalidOrderSideFormat
5683
}
84+
id, err := uuidStringToUInt(row[6])
85+
if err != nil {
86+
return nil, ErrInvalidOrderSideFormat
87+
}
5788
return &CsvTick{
58-
Timestamp: types.MustParseMillisecondTimestamp(row[0]),
89+
TradeID: id,
5990
Symbol: row[1],
91+
Exchange: types.ExchangeBybit,
6092
Side: side,
61-
TickDirection: row[5],
6293
Size: fixedpoint.MustNewFromString(row[3]),
6394
Price: fixedpoint.MustNewFromString(row[4]),
6495
HomeNotional: fixedpoint.MustNewFromString(row[8]),
6596
ForeignNotional: fixedpoint.MustNewFromString(row[9]),
97+
TickDirection: row[5], // todo does this seem promising to define for other exchanges too?
98+
Timestamp: types.MustParseMillisecondTimestamp(row[0]),
6699
}, nil
67100
}
101+
102+
func uuidStringToUInt(uuidStr string) (uint64, error) {
103+
// Remove hyphens from the UUID string
104+
uuidStr = strings.Replace(uuidStr, "-", "", -1)
105+
106+
// Parse the hexadecimal string into a big integer
107+
uuidBigInt, success := new(big.Int).SetString(uuidStr, 16)
108+
if !success {
109+
return 0, fmt.Errorf("Failed to parse UUID as a big integer")
110+
}
111+
112+
return uuidBigInt.Uint64(), nil
113+
}

pkg/datasource/csvsource/stream.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ func (s *Stream) simulateEvents() error {
6969
if err != nil {
7070
return err
7171
}
72+
tick.Symbol = s.config.Symbol // not every csv provides symbol information
7273
trade, err := tick.toGlobalTrade()
7374
if err != nil {
7475
return err

pkg/datasource/csvsource/types.go

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import (
66
)
77

88
type CsvTick struct {
9+
Exchange types.ExchangeName `json:"exchange"`
10+
TradeID uint64 `json:"tradeID"`
911
Symbol string `json:"symbol"`
1012
TickDirection string `json:"tickDirection"`
1113
Side types.SideType `json:"side"`
@@ -19,21 +21,21 @@ type CsvTick struct {
1921
// todo
2022
func (c *CsvTick) toGlobalTrade() (*types.Trade, error) {
2123
return &types.Trade{
22-
// ID: tradeIdNum,
23-
// OrderID: orderIdNum,
24-
// Exchange: types.ExchangeBybit,
25-
// Price: trade.OrderPrice,
26-
// Quantity: trade.OrderQty,
27-
// QuoteQuantity: trade.OrderPrice.Mul(trade.OrderQty),
28-
// Symbol: trade.Symbol,
29-
// Side: side,
30-
// IsBuyer: side == types.SideTypeBuy,
31-
// IsMaker: isMaker,
32-
// Time: types.Time(trade.ExecutionTime),
33-
// Fee: trade.ExecFee,
24+
ID: c.TradeID,
25+
// OrderID: // not implemented
26+
Exchange: c.Exchange,
27+
Price: c.Price,
28+
Quantity: c.Size,
29+
QuoteQuantity: c.Price.Mul(c.Size), // todo this does not seem right use of propert.. looses info on foreign notional
30+
Symbol: c.Symbol,
31+
Side: c.Side,
32+
IsBuyer: c.Side == types.SideTypeBuy,
33+
// IsMaker: isMaker, // todo property isBuyer and isMaker seem to get confused and duplicated
34+
Time: types.Time(c.Timestamp),
35+
// Fee: trade.ExecFee, // todo how to get this info?
3436
// FeeCurrency: trade.FeeTokenId,
35-
// IsMargin: false,
36-
// IsFutures: false,
37-
// IsIsolated: false,
37+
IsMargin: false,
38+
IsFutures: false, // todo make future dataset source type as config
39+
IsIsolated: false,
3840
}, nil
3941
}

0 commit comments

Comments
 (0)