Skip to content
This repository has been archived by the owner on Feb 1, 2024. It is now read-only.

New filter system along with new filters (closes #321) #323

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
cfd0cbd
1 - inject submitFilters
nikhilsaraf Dec 19, 2019
a45541c
2 - inject db instance
nikhilsaraf Dec 20, 2019
57f8320
3 - extract filtering infrastructure logic from makerModeFilter for r…
nikhilsaraf Dec 23, 2019
189c68d
4 - separate out TimestampFormatString and DateFormatString
nikhilsaraf Dec 23, 2019
50fe00e
5 - first draft of volumeFilter.go (untested, many TODOs)
nikhilsaraf Dec 23, 2019
b7d662a
6 - fetch marketID in volumeFilter
nikhilsaraf Dec 24, 2019
afbd654
7 - better index for daily trades table query
nikhilsaraf Dec 24, 2019
c15f960
8 - take in volumeFilter config values
nikhilsaraf Dec 25, 2019
a8cc494
9 - update sample_trader.cfg to include sample for volumeFilterConfig
nikhilsaraf Dec 25, 2019
46d4439
10 - StructString displays values in structs in a cleaner way + autom…
nikhilsaraf Dec 25, 2019
2cd2a90
11 - treat values as 0 when there are no recorded trades in the db fo…
nikhilsaraf Dec 25, 2019
3c2810a
12 - fix initialization of dailyTBB to avoid a null pointer dereference
nikhilsaraf Dec 25, 2019
1d49313
13 - fix bug caused by variable shadowing in volumeFilter.go
nikhilsaraf Dec 25, 2019
524b7df
14 - limit check should be lte, not lt check
nikhilsaraf Dec 25, 2019
7ea2f55
15 - update filterOps() to run existing offers through filter function
nikhilsaraf Dec 29, 2019
eb166be
16 - added TODO for simplification of filterOps
nikhilsaraf Dec 29, 2019
cd8d66e
17 - update sample config to denote that volumeFilter only works with…
nikhilsaraf Dec 29, 2019
2dd9e79
18 - minPrice filter
nikhilsaraf Dec 29, 2019
f35253c
19 - add filterName to filterOps log line
nikhilsaraf Dec 29, 2019
234adb8
20 - MAX_PRICE filter
nikhilsaraf Dec 29, 2019
d805101
21 - new format of filters in config file with corresponding filterFa…
nikhilsaraf Dec 29, 2019
04965b8
22 - force fail if any new filters are specified without sell or dele…
nikhilsaraf Dec 30, 2019
f98f6b1
23 - extract logic that never drops delete operations into filterOps()
nikhilsaraf Dec 30, 2019
e1e1a57
24 - included additional explanation in FILTERS section of sample con…
nikhilsaraf Dec 30, 2019
eca836a
25 - fix Errorf statement
nikhilsaraf Dec 30, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 68 additions & 22 deletions cmd/trade.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cmd

import (
"database/sql"
"fmt"
"io"
"log"
Expand Down Expand Up @@ -329,7 +330,9 @@ func makeBot(
exchangeShim api.ExchangeShim,
ieif *plugins.IEIF,
tradingPair *model.TradingPair,
db *sql.DB,
strategy api.Strategy,
assetDisplayFn model.AssetDisplayFn,
threadTracker *multithreading.ThreadTracker,
options inputs,
) *trader.Trader {
Expand All @@ -344,30 +347,67 @@ func makeBot(
// we want to delete all the offers and exit here since there is something wrong with our setup
deleteAllOffersAndExit(l, botConfig, client, sdex, exchangeShim, threadTracker)
}
dataKey := model.MakeSortedBotKey(botConfig.AssetBase(), botConfig.AssetQuote())

assetBase := botConfig.AssetBase()
assetQuote := botConfig.AssetQuote()
dataKey := model.MakeSortedBotKey(assetBase, assetQuote)
alert, e := monitoring.MakeAlert(botConfig.AlertType, botConfig.AlertAPIKey)
if e != nil {
l.Infof("Unable to set up monitoring for alert type '%s' with the given API key\n", botConfig.AlertType)
}
bot := trader.MakeBot(

// start make filters
submitFilters := []plugins.SubmitFilter{
plugins.MakeFilterOrderConstraints(exchangeShim.GetOrderConstraints(tradingPair), assetBase, assetQuote),
}
if submitMode == api.SubmitModeMakerOnly {
submitFilters = append(submitFilters,
plugins.MakeFilterMakerMode(exchangeShim, sdex, tradingPair),
)
}
if len(botConfig.Filters) > 0 && *options.strategy != "sell" && *options.strategy != "delete" {
log.Println()
utils.PrintErrorHintf("FILTERS currently only supported on 'sell' and 'delete' strategies, remove FILTERS from the trader config file")
// we want to delete all the offers and exit here since there is something wrong with our setup
deleteAllOffersAndExit(l, botConfig, client, sdex, exchangeShim, threadTracker)
}
filterFactory := plugins.FilterFactory{
ExchangeName: botConfig.TradingExchangeName(),
TradingPair: tradingPair,
AssetDisplayFn: assetDisplayFn,
BaseAsset: assetBase,
QuoteAsset: assetQuote,
DB: db,
}
for _, filterString := range botConfig.Filters {
filter, e := filterFactory.MakeFilter(filterString)
if e != nil {
log.Println()
log.Println(e)
// we want to delete all the offers and exit here since there is something wrong with our setup
deleteAllOffersAndExit(l, botConfig, client, sdex, exchangeShim, threadTracker)
}
submitFilters = append(submitFilters, filter)
}
// end make filters

return trader.MakeTrader(
client,
ieif,
botConfig.AssetBase(),
botConfig.AssetQuote(),
tradingPair,
assetBase,
assetQuote,
botConfig.TradingAccount(),
sdex,
exchangeShim,
strategy,
timeController,
botConfig.DeleteCyclesThreshold,
submitMode,
submitFilters,
threadTracker,
options.fixedIterations,
dataKey,
alert,
)
return bot
}

func convertDeprecatedBotConfigValues(l logger.Logger, botConfig trader.BotConfig) trader.BotConfig {
Expand Down Expand Up @@ -434,6 +474,20 @@ func runTradeCmd(options inputs) {
tradingPair.Base: botConfig.AssetBase(),
tradingPair.Quote: botConfig.AssetQuote(),
}
assetDisplayFn := model.MakePassthroughAssetDisplayFn()
if botConfig.IsTradingSdex() {
assetDisplayFn = model.MakeSdexMappedAssetDisplayFn(sdexAssetMap)
}

var db *sql.DB
if botConfig.PostgresDbConfig != nil {
var e error
db, e = database.ConnectInitializedDatabase(botConfig.PostgresDbConfig)
if e != nil {
logger.Fatal(l, fmt.Errorf("problem encountered while initializing the db: %s", e))
}
log.Printf("made db instance with config: %s\n", botConfig.PostgresDbConfig.MakeConnectString())
}
exchangeShim, sdex := makeExchangeShimSdex(
l,
botConfig,
Expand Down Expand Up @@ -467,7 +521,9 @@ func runTradeCmd(options inputs) {
exchangeShim,
ieif,
tradingPair,
db,
strategy,
assetDisplayFn,
threadTracker,
options,
)
Expand Down Expand Up @@ -496,7 +552,8 @@ func runTradeCmd(options inputs) {
sdex,
exchangeShim,
tradingPair,
sdexAssetMap,
assetDisplayFn,
db,
threadTracker,
)
startQueryServer(
Expand Down Expand Up @@ -565,7 +622,8 @@ func startFillTracking(
sdex *plugins.SDEX,
exchangeShim api.ExchangeShim,
tradingPair *model.TradingPair,
sdexAssetMap map[model.Asset]hProtocol.Asset,
assetDisplayFn model.AssetDisplayFn,
db *sql.DB,
threadTracker *multithreading.ThreadTracker,
) {
strategyFillHandlers, e := strategy.GetFillHandlers()
Expand All @@ -580,19 +638,7 @@ func startFillTracking(
fillTracker := plugins.MakeFillTracker(tradingPair, threadTracker, exchangeShim, botConfig.FillTrackerSleepMillis, botConfig.FillTrackerDeleteCyclesThreshold)
fillLogger := plugins.MakeFillLogger()
fillTracker.RegisterHandler(fillLogger)
if botConfig.PostgresDbConfig != nil {
db, e := database.ConnectInitializedDatabase(botConfig.PostgresDbConfig)
if e != nil {
l.Info("")
l.Errorf("problem encountered while initializing the db: %s", e)
deleteAllOffersAndExit(l, botConfig, client, sdex, exchangeShim, threadTracker)
}
log.Printf("made db instance with config: %s\n", botConfig.PostgresDbConfig.MakeConnectString())

assetDisplayFn := model.MakePassthroughAssetDisplayFn()
if botConfig.IsTradingSdex() {
assetDisplayFn = model.MakeSdexMappedAssetDisplayFn(sdexAssetMap)
}
if db != nil {
fillDBWriter := plugins.MakeFillDBWriter(db, assetDisplayFn, botConfig.TradingExchangeName())
fillTracker.RegisterHandler(fillDBWriter)
}
Expand Down
5 changes: 5 additions & 0 deletions database/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ const sqlTradesTableCreate = "CREATE TABLE IF NOT EXISTS trades (market_id TEXT
indexes
*/
const sqlTradesIndexCreate = "CREATE INDEX IF NOT EXISTS date ON trades (market_id, date_utc)"
const sqlTradesIndexDrop = "DROP INDEX IF EXISTS date"
const sqlTradesIndexCreate2 = "CREATE INDEX IF NOT EXISTS trades_mdd ON trades (market_id, DATE(date_utc), date_utc)"

/*
insert statements
Expand All @@ -39,6 +41,9 @@ const SqlQueryMarketsById = "SELECT market_id, exchange_name, base, quote FROM m
// sqlQueryDbVersion queries the db_version table
const sqlQueryDbVersion = "SELECT version FROM db_version ORDER BY version desc LIMIT 1"

// SqlQueryDailyValues queries the trades table to get the values for a given day
const SqlQueryDailyValues = "SELECT SUM(base_volume) as total_base_volume, SUM(counter_cost) as total_counter_volume FROM trades WHERE market_id = $1 AND DATE(date_utc) = $2 and action = $3 group by DATE(date_utc)"

/*
query helper functions
*/
Expand Down
6 changes: 5 additions & 1 deletion database/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ var upgradeScripts = []*UpgradeScript{
sqlTradesTableCreate,
sqlTradesIndexCreate,
),
makeUpgradeScript(3,
sqlTradesIndexDrop,
sqlTradesIndexCreate2,
),
}

// UpgradeScript encapsulates a script to be run to upgrade the database from one version to the next
Expand Down Expand Up @@ -104,7 +108,7 @@ func runUpgradeScripts(db *sql.DB, scripts []*UpgradeScript) error {
// add entry to db_version table
sqlInsertDbVersion := fmt.Sprintf(sqlDbVersionTableInsertTemplate,
script.version,
startTime.Format(postgresdb.DateFormatString),
startTime.Format(postgresdb.TimestampFormatString),
len(script.commands),
elapsedMillis,
)
Expand Down
36 changes: 27 additions & 9 deletions examples/configs/trader/sample_trader.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,6 @@ HORIZON_URL="https://horizon-testnet.stellar.org"
# the URL to use for your CCXT-rest instance. Defaults to http://localhost:3000 if unset
#CCXT_REST_URL="http://localhost:3000"

# specify parameters for how we compute the operation fee from the /fee_stats endpoint
[FEE]
# trigger when "ledger_capacity_usage" in /fee_stats is >= this value
CAPACITY_TRIGGER=0.8
# percentile computation to use from /fee_stats (10, 20, ..., 90, 95, 99)
PERCENTILE=90
# max fee in stroops per operation to use
MAX_OP_FEE_STROOPS=5000

# uncomment below to add support for monitoring.
# type of alerting system to use, currently only "PagerDuty" is supported.
#ALERT_TYPE="PagerDuty"
Expand Down Expand Up @@ -99,6 +90,33 @@ MAX_OP_FEE_STROOPS=5000
# (optional) minimum volume of quote units needed to place an order on the non-sdex (centralized) exchange
#CENTRALIZED_MIN_QUOTE_VOLUME_OVERRIDE=10.0

# uncomment to include these filters in order (these filters only work with sell strategy for now)
# these are the only four filters available for now via this new filtration method and any new filters added will include a
# corresponding sample entry with an explanation.
# the best way to use these filters is to uncomment the one you want to use and update the price (last param) accordingly.
#FILTERS = [
# # limit the amount of the base asset that is sold every day, denominated in units of the base asset (needs POSTGRES_DB)
# "volume/sell/base/3500.0",
#
# # limit the amount of the base asset that is sold every day, denominated in units of the quote asset (needs POSTGRES_DB)
# "volume/sell/quote/1000.0",
#
# # limit offers based on a minimim price requirement
# "price/min/0.04",
#
# # limit offers based on a maximum price requirement
# "price/max/1.00",
#]

# specify parameters for how we compute the operation fee from the /fee_stats endpoint
[FEE]
# trigger when "ledger_capacity_usage" in /fee_stats is >= this value
CAPACITY_TRIGGER=0.8
# percentile computation to use from /fee_stats (10, 20, ..., 90, 95, 99)
PERCENTILE=90
# max fee in stroops per operation to use
MAX_OP_FEE_STROOPS=5000

# uncomment if you want to track fills in a postgres db
#[POSTGRES_DB]
#HOST="localhost"
Expand Down
2 changes: 1 addition & 1 deletion plugins/balancedStrategy.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ type balancedConfig struct {

// String impl.
func (c balancedConfig) String() string {
return utils.StructString(c, nil)
return utils.StructString(c, 0, nil)
}

// makeBalancedStrategy is a factory method for balancedStrategy
Expand Down
2 changes: 1 addition & 1 deletion plugins/buysellStrategy.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func MakeBuysellConfig(

// String impl.
func (c BuySellConfig) String() string {
return utils.StructString(c, nil)
return utils.StructString(c, 0, nil)
}

// makeBuySellStrategy is a factory method
Expand Down
11 changes: 7 additions & 4 deletions plugins/fillDBWriter.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,17 @@ type FillDBWriter struct {
market *tradingMarket
}

// makeTradingMarket makes a market along with the ID field
func makeTradingMarket(exchangeName string, baseAsset string, quoteAsset string) *tradingMarket {
func makeMarketID(exchangeName string, baseAsset string, quoteAsset string) string {
idString := fmt.Sprintf("%s_%s_%s", exchangeName, baseAsset, quoteAsset)
h := sha256.New()
h.Write([]byte(idString))
sha256Hash := fmt.Sprintf("%x", h.Sum(nil))
sha256HashPrefix := sha256Hash[0:marketIdHashLength]
return sha256Hash[0:marketIdHashLength]
}

// makeTradingMarket makes a market along with the ID field
func makeTradingMarket(exchangeName string, baseAsset string, quoteAsset string) *tradingMarket {
sha256HashPrefix := makeMarketID(exchangeName, baseAsset, quoteAsset)
return &tradingMarket{
ID: sha256HashPrefix,
ExchangeName: exchangeName,
Expand Down Expand Up @@ -156,7 +159,7 @@ func (f *FillDBWriter) HandleFill(trade model.Trade) error {
txid := utils.CheckedString(trade.TransactionID)
timeSeconds := trade.Timestamp.AsInt64() / 1000
date := time.Unix(timeSeconds, 0).UTC()
dateString := date.Format(postgresdb.DateFormatString)
dateString := date.Format(postgresdb.TimestampFormatString)

market, e := f.fetchOrRegisterMarket(trade)
if e != nil {
Expand Down
Loading