-
Notifications
You must be signed in to change notification settings - Fork 1
/
trade.go
77 lines (69 loc) · 1.85 KB
/
trade.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package simple
import (
"fmt"
"math"
"time"
"github.com/vanillaiice/gocryptobot/pkg/binance"
"github.com/vanillaiice/gocryptobot/pkg/pricews"
)
func trade(botCfg *BotCfg, state *State, client *binance.Client, c <-chan pricews.PriceData) (err error) {
logger.Info().Msgf(
"trading %.5f %s/%s, BUY margin @%.3f%%, SELL margin @%.3f%%",
botCfg.TradingBalance,
botCfg.Base,
botCfg.Quote,
botCfg.PercentChangeBuy,
botCfg.PercentChangeSell,
)
var priceData pricews.PriceData
for {
priceData = <-c
timestampDiff := math.Abs(float64(time.Now().UnixMilli() - priceData.Timestamp))
if timestampDiff > float64(botCfg.MaxPriceTimestampMs) {
logger.Debug().Msgf("price timestamp too old: %.3f (max: %d)", timestampDiff, botCfg.MaxPriceTimestampMs)
continue
}
switch state.Data.LastTx {
case txfirst:
switch botCfg.FirstTx {
case txBuy:
if !botCfg.SkipFirstTx {
if err = tryBuy(botCfg, state, client, -1); err != nil {
return
}
} else {
state.Data.LastTx = txBuy
if err = state.Save(); err != nil {
return
}
}
case txSell:
if !botCfg.SkipFirstTx {
if err = orderMarket(botCfg, state, client, orderSideSell); err != nil {
return
}
} else {
state.Data.LastTx = txSell
if err = state.Save(); err != nil {
return
}
}
default:
return fmt.Errorf("invalid first tx: %s", botCfg.FirstTx)
}
case txBuy:
if err = trySell(botCfg, state, client, priceData.Price*priceMultiplierSell); err != nil {
return
}
case txSell:
if err = tryBuy(botCfg, state, client, priceData.Price*priceMultiplierBuy); err != nil {
return
}
default:
return fmt.Errorf("invalid last tx: %s", state.Data.LastTx)
}
if botCfg.StopAfterTx >= 0 && state.Data.StopAfterTx == 0 {
return fmt.Errorf("stopped bot after %d tx", botCfg.StopAfterTx)
}
}
}