Skip to content

Commit

Permalink
wip csv source stream mock fees
Browse files Browse the repository at this point in the history
  • Loading branch information
go-dockly committed Nov 3, 2023
1 parent e0ec268 commit b9150e5
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 24 deletions.
3 changes: 3 additions & 0 deletions pkg/datasource/csvsource/csv_tick_decoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,12 @@ func BinanceCSVTickDecoder(row []string, _ int) (*CsvTick, error) {
Side: side,
Size: qty,
Price: price,
IsBuyerMaker: isBuyerMaker,
HomeNotional: price.Mul(qty),
ForeignNotional: price.Mul(baseQty),
Timestamp: types.MustParseMillisecondTimestamp(row[5]),
// Symbol: must be overwritten - info not in csv,
// TickDirection: would need to keep last tick in memory to compare tick direction,
}, nil
}

Expand Down
38 changes: 24 additions & 14 deletions pkg/datasource/csvsource/stream.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,30 @@ import (
type Stream struct {
types.StandardStream
config *CsvStreamConfig
converter ICSVTickConverter
marketTradeEventCallbacks []func(e []CsvTick)
kLineEventCallbacks []func(e []types.KLine)
orderEventCallbacks []func(e []types.Order)
tradeEventCallbacks []func(e []types.Trade)
}

type CsvStreamConfig struct {
Interval types.Interval
RateLimit time.Duration `json:"csvPath"`
CsvPath string `json:"csvPath"`
Symbol string `json:"symbol"`
BaseCoin string `json:"baseCoin"`
QuoteCoin string `json:"quoteCoin"`
TakerFeeRate fixedpoint.Value `json:"takerFeeRate"`
MakerFeeRate fixedpoint.Value `json:"makerFeeRate"`
Interval types.Interval `json:"interval"`
RateLimit time.Duration `json:"rateLimit"`
StrategyID string `json:"strategyID"`
CsvPath string `json:"csvPath"`
Exchange types.ExchangeName `json:"exchange"`
Symbol string `json:"symbol"`
BaseCoin string `json:"baseCoin"`
QuoteCoin string `json:"quoteCoin"`
TakerFeeRate fixedpoint.Value `json:"takerFeeRate"`
MakerFeeRate fixedpoint.Value `json:"makerFeeRate"`
}

func NewStream(cfg *CsvStreamConfig) *Stream {
stream := &Stream{
StandardStream: types.NewStandardStream(),
converter: NewCSVTickConverter(),
config: cfg,
}

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

func (s *Stream) Simulate() error {
var i int
converter := NewCSVTickConverter()

// iterate equity series at csv path and stream
err := filepath.WalkDir(s.config.CsvPath, func(path string, d fs.DirEntry, err error) error {
if err != nil {
Expand All @@ -74,23 +76,31 @@ func (s *Stream) Simulate() error {
return err
}
tick.Symbol = s.config.Symbol // not every csv provides symbol information

trade, err := tick.toGlobalTrade()
if err != nil {
return err
}
trade.Fee = s.config.TakerFeeRate
trade.FeeCurrency = s.config.QuoteCoin
if tick.IsBuyerMaker { // if supported by exchange csv format
trade.Fee = s.config.MakerFeeRate
}
s.StandardStream.EmitMarketTrade(*trade)

kline := converter.LatestKLine()
closesKline := converter.CsvTickToKLine(tick, s.config.Interval)
kline := s.converter.LatestKLine()
closesKline := s.converter.CsvTickToKLine(tick, s.config.Interval)
if closesKline {
s.StandardStream.EmitKLineClosed(*kline)
} else {
kline = converter.LatestKLine()
kline = s.converter.LatestKLine() // overwrite with newer KLine
s.StandardStream.EmitKLine(*kline)
}

// allow for execution time of indicators and strategy
time.Sleep(s.config.RateLimit) // Max execution time for tradingview strategy
time.Sleep(s.config.RateLimit) // Max execution time for tradingview strategy is 250ms
// to optimize exec time consider callback channel once a strategy has finished running another tick is emitted

return nil
})
if err != nil {
Expand Down
30 changes: 30 additions & 0 deletions pkg/datasource/csvsource/stream_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package csvsource

import (
"time"

"github.com/c9s/bbgo/pkg/fixedpoint"
"github.com/c9s/bbgo/pkg/types"
)

func getMockCsvSourceConfig(equityType EquityType) CsvStreamConfig {
cfg := CsvStreamConfig{
Exchange: types.ExchangeBybit,
Interval: types.Interval30m,
RateLimit: time.Millisecond * 100,
CsvPath: "./testdata",
Symbol: "FXSUSDT",
BaseCoin: "FXS",
QuoteCoin: "USDT",
StrategyID: "BOLLMaker",
}
switch equityType {
case Derivatives:
cfg.TakerFeeRate = fixedpoint.NewFromFloat(0.055)
cfg.MakerFeeRate = fixedpoint.NewFromFloat(0.02)
return cfg
}
cfg.TakerFeeRate = fixedpoint.NewFromFloat(0.1)
cfg.MakerFeeRate = fixedpoint.NewFromFloat(0.1)
return cfg
}
27 changes: 17 additions & 10 deletions pkg/datasource/csvsource/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,27 @@ import (
"github.com/c9s/bbgo/pkg/types"
)

type EquityType int

const (
Spot EquityType = 0
Derivatives EquityType = 1
)

type CsvTick struct {
Exchange types.ExchangeName `json:"exchange"`
TradeID uint64 `json:"tradeID"`
Symbol string `json:"symbol"`
TickDirection string `json:"tickDirection"`
Side types.SideType `json:"side"`
Exchange types.ExchangeName `json:"exchange"`
TradeID uint64 `json:"tradeID"`
Symbol string `json:"symbol"`
TickDirection string `json:"tickDirection"`
Side types.SideType `json:"side"`
IsBuyerMaker bool
Size fixedpoint.Value `json:"size"`
Price fixedpoint.Value `json:"price"`
HomeNotional fixedpoint.Value `json:"homeNotional"`
ForeignNotional fixedpoint.Value `json:"foreignNotional"`
Timestamp types.MillisecondTimestamp `json:"timestamp"`
}

// todo
func (c *CsvTick) toGlobalTrade() (*types.Trade, error) {
return &types.Trade{
ID: c.TradeID,
Expand All @@ -30,12 +37,12 @@ func (c *CsvTick) toGlobalTrade() (*types.Trade, error) {
Symbol: c.Symbol,
Side: c.Side,
IsBuyer: c.Side == types.SideTypeBuy,
// IsMaker: isMaker, // todo property isBuyer and isMaker seem to get confused and duplicated
Time: types.Time(c.Timestamp),
// Fee: trade.ExecFee, // todo how to get this info?
IsMaker: c.IsBuyerMaker,
Time: types.Time(c.Timestamp),
// Fee: trade.ExecFee, // info is overwritten by stream?
// FeeCurrency: trade.FeeTokenId,
IsMargin: false,
IsFutures: false, // todo make future dataset source type as config
IsFutures: false, // todo make equity type configurable
IsIsolated: false,
}, nil
}

0 comments on commit b9150e5

Please sign in to comment.