Skip to content

Commit

Permalink
write trades to a sqlite database
Browse files Browse the repository at this point in the history
  • Loading branch information
nikhilsaraf committed Jun 28, 2019
1 parent 1f73b91 commit 0c9db72
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 2 deletions.
9 changes: 9 additions & 0 deletions cmd/trade.go
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,15 @@ func startFillTracking(
fillTracker := plugins.MakeFillTracker(tradingPair, threadTracker, exchangeShim, botConfig.FillTrackerSleepMillis, botConfig.FillTrackerDeleteCyclesThreshold)
fillLogger := plugins.MakeFillLogger()
fillTracker.RegisterHandler(fillLogger)
if botConfig.SqlDbPath != "" {
fillDBWriter, e := plugins.MakeFillDBWriter(botConfig.SqlDbPath)
if e != nil {
l.Info("")
l.Errorf("problem encountered while making the FillDBWriter: %s", e)
deleteAllOffersAndExit(l, botConfig, client, sdex, exchangeShim, threadTracker)
}
fillTracker.RegisterHandler(fillDBWriter)
}
if strategyFillHandlers != nil {
for _, h := range strategyFillHandlers {
fillTracker.RegisterHandler(h)
Expand Down
4 changes: 4 additions & 0 deletions examples/configs/trader/sample_trader.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ MAX_OP_FEE_STROOPS=5000
# minimum values for Kraken: https://support.kraken.com/hc/en-us/articles/205893708-What-is-the-minimum-order-size-volume-
# minimum order value for Binance: https://support.binance.com/hc/en-us/articles/115000594711-Trading-Rule
#MIN_CENTRALIZED_BASE_VOLUME=30.0

# uncomment if you want to track fills in a sql db for sqlite
#SQL_DB_PATH="./mydatabase.db"

# uncomment lines below to use kraken. Can use "sdex" or leave out to trade on the Stellar Decentralized Exchange.
# can alternatively use any of the ccxt-exchanges marked as "Trading" (run `kelp exchanges` for full list)
#TRADING_EXCHANGE="kraken"
Expand Down
6 changes: 4 additions & 2 deletions glide.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions glide.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,5 @@ import:
version: a26df67722de7fcf1a8e22cd934e63e553dd3875
- package: github.com/mitchellh/mapstructure
version: v1.1.2
- package: github.com/mattn/go-sqlite3
version: 1.10.0
100 changes: 100 additions & 0 deletions plugins/fillDBWriter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package plugins

import (
"database/sql"
"fmt"
"log"
"time"

_ "github.com/mattn/go-sqlite3"
"github.com/stellar/kelp/api"
"github.com/stellar/kelp/model"
"github.com/stellar/kelp/support/utils"
)

const dateFormatString = "2006/01/02"
const sqlDbCreate = "CREATE TABLE IF NOT EXISTS trades (txid TEXT PRIMARY KEY, date_utc VARCHAR(10), timestamp_millis INTEGER, base TEXT, quote TEXT, action TEXT, type TEXT, counter_price REAL, base_volume REAL, counter_cost REAL, fee REAL)"
const sqlInsert = "INSERT INTO trades (txid, date_utc, timestamp_millis, base, quote, action, type, counter_price, base_volume, counter_cost, fee) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"

var sqlIndexes = []string{
"CREATE INDEX IF NOT EXISTS date ON trades (date_utc, base, quote)",
}

// FillDBWriter is a FillHandler that writes fills to a SQL database
type FillDBWriter struct {
db *sql.DB
}

var _ api.FillHandler = &FillDBWriter{}

// MakeFillDBWriter is a factory method
func MakeFillDBWriter(sqlDbPath string) (api.FillHandler, error) {
db, e := sql.Open("sqlite3", sqlDbPath)
if e != nil {
return nil, fmt.Errorf("could not open sqlite3 database: %s", e)
}

statement, e := db.Prepare(sqlDbCreate)
if e != nil {
return nil, fmt.Errorf("could not prepare sql statement: %s", e)
}
_, e = statement.Exec()
if e != nil {
return nil, fmt.Errorf("could not execute sql create table statement: %s", e)
}

for i, sqlIndexCreate := range sqlIndexes {
statement, e = db.Prepare(sqlIndexCreate)
if e != nil {
return nil, fmt.Errorf("could not prepare sql statement to create index (i=%d): %s", i, e)
}
_, e = statement.Exec()
if e != nil {
return nil, fmt.Errorf("could not execute sql statement to create index (i=%d): %s", i, e)
}
}

log.Printf("making FillDBWriter with db path: %s\n", sqlDbPath)
return &FillDBWriter{
db: db,
}, nil
}

// HandleFill impl.
func (f *FillDBWriter) HandleFill(trade model.Trade) error {
statement, e := f.db.Prepare(sqlInsert)
if e != nil {
return fmt.Errorf("could not prepare sql insert values statement: %s", e)
}

txid := utils.CheckedString(trade.TransactionID)
timeSeconds := trade.Timestamp.AsInt64() / 1000
date := time.Unix(timeSeconds, 0).UTC()
dateString := date.Format(dateFormatString)

_, e = statement.Exec(
txid,
dateString,
utils.CheckedString(trade.Timestamp),
string(trade.Pair.Base),
string(trade.Pair.Quote),
trade.OrderAction.String(),
trade.OrderType.String(),
f.checkedFloat(trade.Price),
f.checkedFloat(trade.Volume),
f.checkedFloat(trade.Cost),
f.checkedFloat(trade.Fee),
)
if e != nil {
return fmt.Errorf("could not execute sql insert values statement: %s", e)
}
log.Printf("wrote trade (txid=%s) to db\n", txid)
return nil
}

func (f *FillDBWriter) checkedFloat(n *model.Number) interface{} {
if n == nil {
return nil
}
return n.AsFloat()
}
1 change: 1 addition & 0 deletions trader/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ type BotConfig struct {
HorizonURL string `valid:"-" toml:"HORIZON_URL"`
Fee *FeeConfig `valid:"-" toml:"FEE"`
MinCentralizedBaseVolume float64 `valid:"-" toml:"MIN_CENTRALIZED_BASE_VOLUME"`
SqlDbPath string `valid:"-" toml:"SQL_DB_PATH"`
AlertType string `valid:"-" toml:"ALERT_TYPE"`
AlertAPIKey string `valid:"-" toml:"ALERT_API_KEY"`
MonitoringPort uint16 `valid:"-" toml:"MONITORING_PORT"`
Expand Down

0 comments on commit 0c9db72

Please sign in to comment.