Skip to content

Commit b9150e5

Browse files
committed
wip csv source stream mock fees
1 parent e0ec268 commit b9150e5

File tree

4 files changed

+74
-24
lines changed

4 files changed

+74
-24
lines changed

pkg/datasource/csvsource/csv_tick_decoder.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,12 @@ func BinanceCSVTickDecoder(row []string, _ int) (*CsvTick, error) {
5252
Side: side,
5353
Size: qty,
5454
Price: price,
55+
IsBuyerMaker: isBuyerMaker,
5556
HomeNotional: price.Mul(qty),
5657
ForeignNotional: price.Mul(baseQty),
5758
Timestamp: types.MustParseMillisecondTimestamp(row[5]),
59+
// Symbol: must be overwritten - info not in csv,
60+
// TickDirection: would need to keep last tick in memory to compare tick direction,
5861
}, nil
5962
}
6063

pkg/datasource/csvsource/stream.go

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,26 +15,30 @@ import (
1515
type Stream struct {
1616
types.StandardStream
1717
config *CsvStreamConfig
18+
converter ICSVTickConverter
1819
marketTradeEventCallbacks []func(e []CsvTick)
1920
kLineEventCallbacks []func(e []types.KLine)
2021
orderEventCallbacks []func(e []types.Order)
2122
tradeEventCallbacks []func(e []types.Trade)
2223
}
2324

2425
type CsvStreamConfig struct {
25-
Interval types.Interval
26-
RateLimit time.Duration `json:"csvPath"`
27-
CsvPath string `json:"csvPath"`
28-
Symbol string `json:"symbol"`
29-
BaseCoin string `json:"baseCoin"`
30-
QuoteCoin string `json:"quoteCoin"`
31-
TakerFeeRate fixedpoint.Value `json:"takerFeeRate"`
32-
MakerFeeRate fixedpoint.Value `json:"makerFeeRate"`
26+
Interval types.Interval `json:"interval"`
27+
RateLimit time.Duration `json:"rateLimit"`
28+
StrategyID string `json:"strategyID"`
29+
CsvPath string `json:"csvPath"`
30+
Exchange types.ExchangeName `json:"exchange"`
31+
Symbol string `json:"symbol"`
32+
BaseCoin string `json:"baseCoin"`
33+
QuoteCoin string `json:"quoteCoin"`
34+
TakerFeeRate fixedpoint.Value `json:"takerFeeRate"`
35+
MakerFeeRate fixedpoint.Value `json:"makerFeeRate"`
3336
}
3437

3538
func NewStream(cfg *CsvStreamConfig) *Stream {
3639
stream := &Stream{
3740
StandardStream: types.NewStandardStream(),
41+
converter: NewCSVTickConverter(),
3842
config: cfg,
3943
}
4044

@@ -49,8 +53,6 @@ func NewStream(cfg *CsvStreamConfig) *Stream {
4953

5054
func (s *Stream) Simulate() error {
5155
var i int
52-
converter := NewCSVTickConverter()
53-
5456
// iterate equity series at csv path and stream
5557
err := filepath.WalkDir(s.config.CsvPath, func(path string, d fs.DirEntry, err error) error {
5658
if err != nil {
@@ -74,23 +76,31 @@ func (s *Stream) Simulate() error {
7476
return err
7577
}
7678
tick.Symbol = s.config.Symbol // not every csv provides symbol information
79+
7780
trade, err := tick.toGlobalTrade()
7881
if err != nil {
7982
return err
8083
}
84+
trade.Fee = s.config.TakerFeeRate
85+
trade.FeeCurrency = s.config.QuoteCoin
86+
if tick.IsBuyerMaker { // if supported by exchange csv format
87+
trade.Fee = s.config.MakerFeeRate
88+
}
8189
s.StandardStream.EmitMarketTrade(*trade)
8290

83-
kline := converter.LatestKLine()
84-
closesKline := converter.CsvTickToKLine(tick, s.config.Interval)
91+
kline := s.converter.LatestKLine()
92+
closesKline := s.converter.CsvTickToKLine(tick, s.config.Interval)
8593
if closesKline {
8694
s.StandardStream.EmitKLineClosed(*kline)
8795
} else {
88-
kline = converter.LatestKLine()
96+
kline = s.converter.LatestKLine() // overwrite with newer KLine
8997
s.StandardStream.EmitKLine(*kline)
9098
}
99+
91100
// allow for execution time of indicators and strategy
92-
time.Sleep(s.config.RateLimit) // Max execution time for tradingview strategy
101+
time.Sleep(s.config.RateLimit) // Max execution time for tradingview strategy is 250ms
93102
// to optimize exec time consider callback channel once a strategy has finished running another tick is emitted
103+
94104
return nil
95105
})
96106
if err != nil {
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package csvsource
2+
3+
import (
4+
"time"
5+
6+
"github.com/c9s/bbgo/pkg/fixedpoint"
7+
"github.com/c9s/bbgo/pkg/types"
8+
)
9+
10+
func getMockCsvSourceConfig(equityType EquityType) CsvStreamConfig {
11+
cfg := CsvStreamConfig{
12+
Exchange: types.ExchangeBybit,
13+
Interval: types.Interval30m,
14+
RateLimit: time.Millisecond * 100,
15+
CsvPath: "./testdata",
16+
Symbol: "FXSUSDT",
17+
BaseCoin: "FXS",
18+
QuoteCoin: "USDT",
19+
StrategyID: "BOLLMaker",
20+
}
21+
switch equityType {
22+
case Derivatives:
23+
cfg.TakerFeeRate = fixedpoint.NewFromFloat(0.055)
24+
cfg.MakerFeeRate = fixedpoint.NewFromFloat(0.02)
25+
return cfg
26+
}
27+
cfg.TakerFeeRate = fixedpoint.NewFromFloat(0.1)
28+
cfg.MakerFeeRate = fixedpoint.NewFromFloat(0.1)
29+
return cfg
30+
}

pkg/datasource/csvsource/types.go

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,27 @@ import (
55
"github.com/c9s/bbgo/pkg/types"
66
)
77

8+
type EquityType int
9+
10+
const (
11+
Spot EquityType = 0
12+
Derivatives EquityType = 1
13+
)
14+
815
type CsvTick struct {
9-
Exchange types.ExchangeName `json:"exchange"`
10-
TradeID uint64 `json:"tradeID"`
11-
Symbol string `json:"symbol"`
12-
TickDirection string `json:"tickDirection"`
13-
Side types.SideType `json:"side"`
16+
Exchange types.ExchangeName `json:"exchange"`
17+
TradeID uint64 `json:"tradeID"`
18+
Symbol string `json:"symbol"`
19+
TickDirection string `json:"tickDirection"`
20+
Side types.SideType `json:"side"`
21+
IsBuyerMaker bool
1422
Size fixedpoint.Value `json:"size"`
1523
Price fixedpoint.Value `json:"price"`
1624
HomeNotional fixedpoint.Value `json:"homeNotional"`
1725
ForeignNotional fixedpoint.Value `json:"foreignNotional"`
1826
Timestamp types.MillisecondTimestamp `json:"timestamp"`
1927
}
2028

21-
// todo
2229
func (c *CsvTick) toGlobalTrade() (*types.Trade, error) {
2330
return &types.Trade{
2431
ID: c.TradeID,
@@ -30,12 +37,12 @@ func (c *CsvTick) toGlobalTrade() (*types.Trade, error) {
3037
Symbol: c.Symbol,
3138
Side: c.Side,
3239
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?
40+
IsMaker: c.IsBuyerMaker,
41+
Time: types.Time(c.Timestamp),
42+
// Fee: trade.ExecFee, // info is overwritten by stream?
3643
// FeeCurrency: trade.FeeTokenId,
3744
IsMargin: false,
38-
IsFutures: false, // todo make future dataset source type as config
45+
IsFutures: false, // todo make equity type configurable
3946
IsIsolated: false,
4047
}, nil
4148
}

0 commit comments

Comments
 (0)