Skip to content

Commit

Permalink
Merge pull request #3 from zarbanio/fix-order-qty
Browse files Browse the repository at this point in the history
fix(strategy): remove end qty
  • Loading branch information
amintalebi authored Oct 9, 2024
2 parents bd1dfa3 + 9740b5e commit 0191884
Show file tree
Hide file tree
Showing 8 changed files with 215 additions and 294 deletions.
1 change: 0 additions & 1 deletion configs/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ type General struct {
type MarketMaker struct {
StartQty float64 `yaml:"StartQty"`
StepQty float64 `yaml:"StepQty"`
EndQty int64 `yaml:"EndQty"`
ProfitThreshold int64 `yaml:"ProfitThreshold"`
Interval time.Duration `yaml:"Interval"`
Slippage float64 `yaml:"Slippage"`
Expand Down
9 changes: 4 additions & 5 deletions configs/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,9 @@ func DefaultConfig() Config {
LogLevel: "info",
},
MarketMaker: MarketMaker{
StartQty: 10.0,
StepQty: 20.0,
EndQty: 400, // max trade DAI in strategy0 and strategy1
ProfitThreshold: 50000, // 50_000 TMN
StartQty: 1,
StepQty: 1,
ProfitThreshold: 5_000, // 50_000 TMN
Interval: time.Minute * 10,
Slippage: 0.001,
},
Expand All @@ -39,7 +38,7 @@ func DefaultConfig() Config {
Nobitex: Nobitex{
Url: "https://api.nobitex.ir",
Key: "", // Assuming no default value for Key
MinimumOrderToman: 300000,
MinimumOrderToman: 300_000,
Timeout: time.Second * 60, // 60s
OrderStatusInterval: time.Second * 2, // 2s
RetryTimeOut: time.Second * 360, // 360s
Expand Down
93 changes: 67 additions & 26 deletions internal/cmd/run/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/rs/zerolog"
"github.com/shopspring/decimal"
"github.com/spf13/cobra"

Expand All @@ -27,44 +28,50 @@ import (
"github.com/zarbanio/market-maker-keeper/internal/nobitex"
"github.com/zarbanio/market-maker-keeper/internal/strategy"
"github.com/zarbanio/market-maker-keeper/internal/uniswapv3"
"github.com/zarbanio/market-maker-keeper/pkg/logger"
"github.com/zarbanio/market-maker-keeper/store"
)

var (
Logger zerolog.Logger
)

func main(cfg configs.Config) {
postgresStore := store.NewPostgres(cfg.Postgres.Host, cfg.Postgres.Port, cfg.Postgres.User, cfg.Postgres.Password, cfg.Postgres.DB)
err := postgresStore.Migrate(cfg.Postgres.MigrationsPath)
lvl, err := zerolog.ParseLevel(cfg.General.LogLevel)
if err != nil {
log.Panic(err)
lvl = zerolog.InfoLevel
}
err = logger.InitLogger(context.Background(), postgresStore, cfg.General.LogLevel)

Logger = zerolog.New(os.Stdout).With().Timestamp().Caller().Logger().Level(lvl)

postgresStore := store.NewPostgres(cfg.Postgres.Host, cfg.Postgres.Port, cfg.Postgres.User, cfg.Postgres.Password, cfg.Postgres.DB)
err = postgresStore.Migrate(cfg.Postgres.MigrationsPath)
if err != nil {
log.Panic(err)
}

blockPtr := blockptr.NewDBBlockPointer(postgresStore, cfg.Indexer.StartBlock)
if !blockPtr.Exists() {
logger.Logger.Debug().Msg("block pointer doest not exits. creating a new one")
Logger.Debug().Msg("block pointer doest not exits. creating a new one")
err := blockPtr.Create()
if err != nil {
logger.Logger.Fatal().Err(err).Msg("error creating block pointer")
Logger.Fatal().Err(err).Msg("error creating block pointer")

}
logger.Logger.Debug().Uint64("start block", cfg.Indexer.StartBlock).Msg("new block pointer created.")
Logger.Debug().Uint64("start block", cfg.Indexer.StartBlock).Msg("new block pointer created.")
}

privateKey := os.Getenv("PRIVATE_KEY")
if privateKey == "" {
logger.Logger.Fatal().Msg("PRIVATE_KEY environment variable is not set")
Logger.Fatal().Msg("PRIVATE_KEY environment variable is not set")
}

executorWallet, err := keystore.New(privateKey)
if err != nil {
logger.Logger.Fatal().Err(err).Msg("error while initializing new executor wallet")
Logger.Fatal().Err(err).Msg("error while initializing new executor wallet")
}
eth, err := ethclient.Dial(cfg.Chain.Url)
if err != nil {
logger.Logger.Fatal().Err(err).Msg("error while dialing eth client")
Logger.Fatal().Err(err).Msg("error while dialing eth client")
}

tokenStore := mstore.NewMemoryTokenStore()
Expand All @@ -80,13 +87,13 @@ func main(cfg configs.Config) {
for _, t := range cfg.Tokens {
sym, err := symbol.FromString(t.Symbol)
if err != nil {
logger.Logger.Panic().Err(err).Msg("error while converting symbol type")
Logger.Panic().Err(err).Msg("error while converting symbol type")
}
token := erc20.NewToken(common.HexToAddress(t.Address), sym, int64(t.Decimals))
erc20Client := erc20.New(eth, token)
err = tokenStore.AddToken(token)
if err != nil {
logger.Logger.Panic().Err(err).Msg("error while adding new token in token store")
Logger.Panic().Err(err).Msg("error while adding new token in token store")
}
dexTrader.AddERC20Client(erc20Client)
}
Expand All @@ -95,25 +102,25 @@ func main(cfg configs.Config) {

dai, err := tokenStore.GetTokenBySymbol(symbol.DAI)
if err != nil {
logger.Logger.Panic().Err(err).Msg("error while getting token by symbol")
Logger.Panic().Err(err).Msg("error while getting token by symbol")
}
zar, err := tokenStore.GetTokenBySymbol(symbol.ZAR)
if err != nil {
logger.Logger.Panic().Err(err).Msg("error while getting token by symbol")
Logger.Panic().Err(err).Msg("error while getting token by symbol")
}

// crate pair in database if not exist
botPair := pair.Pair{QuoteAsset: dai.Symbol(), BaseAsset: zar.Symbol()}
pairId, err := postgresStore.CreatePairIfNotExist(context.Background(), &botPair)
if err != nil {
logger.Logger.Panic().Err(err).Msg("error while creating pair")
Logger.Panic().Err(err).Msg("error while creating pair")
}
botPair.Id = pairId

poolFee := domain.ParseUniswapFee(cfg.Uniswap.PoolFee)
_, err = uniswapV3Factory.GetPool(context.Background(), dai.Address(), zar.Address(), poolFee)
if err != nil {
logger.Logger.Panic().Err(err).Msg("error while getting pool from uniswapV3")
Logger.Panic().Err(err).Msg("error while getting pool from uniswapV3")
}
quoter := uniswapv3.NewQuoter(eth, common.HexToAddress(cfg.Contracts.UniswapV3Quoter))

Expand Down Expand Up @@ -154,19 +161,53 @@ func main(cfg configs.Config) {
strategyConfig := strategy.Config{
StartQty: decimal.NewFromFloat(cfg.MarketMaker.StartQty),
StepQty: decimal.NewFromFloat(cfg.MarketMaker.StepQty),
EndQty: decimal.NewFromInt(cfg.MarketMaker.EndQty),
ProfitThreshold: decimal.NewFromInt(cfg.MarketMaker.ProfitThreshold),
Slippage: decimal.NewFromFloat(cfg.MarketMaker.Slippage),
}

buyDaiInUniswapSellTetherInNobitex := strategy.NewBuyDaiUniswapSellTetherNobitex(postgresStore, nobitexExchange, dexTrader, quoter, tokens, strategyConfig)
buyTetherInNobitexSellDaiInUniswap := strategy.NewSellDaiUniswapBuyTetherNobitex(postgresStore, nobitexExchange, dexTrader, quoter, tokens, strategyConfig)
Logger.Info().
Str("startQty", strategyConfig.StartQty.String()).
Str("stepQty", strategyConfig.StepQty.String()).
Str("profitThreshold", strategyConfig.ProfitThreshold.String()).
Str("slippage", strategyConfig.Slippage.String()).
Msg("market maker started")

buyDaiInUniswapSellTetherInNobitex := &strategy.BuyDaiUniswapSellTetherNobitex{
Store: postgresStore,
Nobitex: nobitexExchange,
DexQuoter: quoter,
DexTrader: dexTrader,
Tokens: tokens,
UniswapFee: domain.UniswapFeeFee01,
Marketsdata: make(map[strategy.Market]strategy.MarketData),
Config: strategyConfig,
}
buyTetherInNobitexSellDaiInUniswap := &strategy.SellDaiUniswapBuyTetherNobitex{
Store: postgresStore,
Nobitex: nobitexExchange,
UniswapQuoter: quoter,
DexTrader: dexTrader,
Tokens: tokens,
UniswapFee: domain.UniswapFeeFee01,
Marketsdata: make(map[strategy.Market]strategy.MarketData),
Config: strategyConfig,
}

ctx := context.Background()

strategies := []strategy.ArbitrageStrategy{buyTetherInNobitexSellDaiInUniswap, buyDaiInUniswapSellTetherInNobitex}

exec := executor.NewExecutor(postgresStore, pairId, strategies, nobitexExchange, *dexTrader, *indexer, cfg.Nobitex.RetryTimeOut, cfg.Nobitex.RetrySleepDuration)
exec := &executor.Executor{
Store: postgresStore,
Strategies: strategies,
PairId: pairId,
Nobitex: nobitexExchange,
DexTrader: *dexTrader,
Indxer: *indexer,
Logger: Logger,
NobitexRetryTimeOut: cfg.Nobitex.RetryTimeOut,
NobitexSleepDuration: cfg.Nobitex.RetrySleepDuration,
}

ticker := time.NewTicker(cfg.MarketMaker.Interval)
done := make(chan bool)
Expand All @@ -177,23 +218,23 @@ func main(cfg configs.Config) {
for {
lastCycleId, err := postgresStore.GetLastCycleId(ctx)
if err != nil {
logger.Logger.Fatal().Err(err).Msg("error while getting last cycle Id")
Logger.Fatal().Err(err).Msg("error while getting last cycle Id")
}
cycleId := lastCycleId + 1
err = postgresStore.CreateCycle(ctx, time.Now(), domain.CycleStatusRunning)
if err != nil {
logger.Logger.Fatal().Err(err).Msg("error while creating new cycle")
Logger.Fatal().Err(err).Msg("error while creating new cycle")
}
exec.SetCycleId(cycleId)
logger.Logger.Info().Int64("cycleId", cycleId).Msg("new cycle started")
Logger.Info().Int64("cycleId", cycleId).Msg("new cycle started")
exec.RunAll()
status := domain.CycleStatusSuccess

err = postgresStore.UpdateCycle(ctx, cycleId, time.Now(), status)
if err != nil {
logger.Logger.Fatal().Err(err).Msg("error while updating cycle")
Logger.Fatal().Err(err).Msg("error while updating cycle")
}
logger.Logger.Info().Int64("cycleId", cycleId).Msg("cycle finished")
Logger.Info().Int64("cycleId", cycleId).Msg("cycle finished")
select {
case <-done:
return
Expand Down
Loading

0 comments on commit 0191884

Please sign in to comment.