2022-01-13 14:15:05 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
"syscall"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
log "github.com/sirupsen/logrus"
|
2022-01-13 17:58:04 +00:00
|
|
|
prefixed "github.com/x-cray/logrus-prefixed-formatter"
|
2022-01-13 14:15:05 +00:00
|
|
|
tb "gopkg.in/tucnak/telebot.v2"
|
|
|
|
|
|
|
|
"github.com/c9s/bbgo/pkg/cmd/cmdutil"
|
|
|
|
"github.com/c9s/bbgo/pkg/interact"
|
|
|
|
)
|
|
|
|
|
|
|
|
func parseFloatPercent(s string, bitSize int) (f float64, err error) {
|
|
|
|
i := strings.Index(s, "%")
|
|
|
|
if i < 0 {
|
|
|
|
return strconv.ParseFloat(s, bitSize)
|
|
|
|
}
|
|
|
|
|
|
|
|
f, err = strconv.ParseFloat(s[:i], bitSize)
|
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
return f / 100.0, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type closePositionTask struct {
|
|
|
|
symbol string
|
|
|
|
percentage float64
|
|
|
|
confirmed bool
|
|
|
|
}
|
|
|
|
|
2022-08-24 04:53:10 +00:00
|
|
|
type positionInteraction struct {
|
2022-01-13 14:15:05 +00:00
|
|
|
closePositionTask closePositionTask
|
|
|
|
}
|
|
|
|
|
2022-08-24 04:53:10 +00:00
|
|
|
// Commands implements the custom interaction
|
|
|
|
func (m *positionInteraction) Commands(i *interact.Interact) {
|
2022-01-13 18:57:39 +00:00
|
|
|
i.Command("/closePosition", "", func(reply interact.Reply) error {
|
2022-01-13 14:15:05 +00:00
|
|
|
// send symbol options
|
|
|
|
reply.Message("Choose your position")
|
|
|
|
for _, symbol := range []string{"BTCUSDT", "ETHUSDT"} {
|
2022-01-19 05:07:25 +00:00
|
|
|
reply.AddButton(symbol, symbol, symbol)
|
2022-01-13 14:15:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}).Next(func(reply interact.Reply, symbol string) error {
|
|
|
|
// get symbol from user
|
|
|
|
if len(symbol) == 0 {
|
|
|
|
reply.Message("Please enter a symbol")
|
|
|
|
return fmt.Errorf("empty symbol")
|
|
|
|
}
|
|
|
|
switch symbol {
|
|
|
|
case "BTCUSDT", "ETHUSDT":
|
|
|
|
|
|
|
|
default:
|
|
|
|
reply.Message("Invalid symbol")
|
|
|
|
return fmt.Errorf("invalid symbol")
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
m.closePositionTask.symbol = symbol
|
|
|
|
|
|
|
|
reply.Message("Choose or enter the percentage to close")
|
|
|
|
for _, symbol := range []string{"25%", "50%", "100%"} {
|
2022-01-19 05:07:25 +00:00
|
|
|
reply.AddButton(symbol, symbol, symbol)
|
2022-01-13 14:15:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// send percentage options
|
|
|
|
return nil
|
|
|
|
}).Next(func(reply interact.Reply, percentageStr string) error {
|
|
|
|
p, err := parseFloatPercent(percentageStr, 64)
|
|
|
|
if err != nil {
|
|
|
|
reply.Message("Not a valid percentage string")
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// get percentage from user
|
|
|
|
m.closePositionTask.percentage = p
|
|
|
|
|
|
|
|
// send confirmation
|
|
|
|
reply.Message("Are you sure to close the position?")
|
2022-01-19 05:07:25 +00:00
|
|
|
reply.AddButton("Yes", "confirm", "yes")
|
2022-01-13 14:15:05 +00:00
|
|
|
return nil
|
|
|
|
}).Next(func(reply interact.Reply, confirm string) error {
|
|
|
|
switch strings.ToLower(confirm) {
|
|
|
|
case "yes":
|
|
|
|
m.closePositionTask.confirmed = true
|
|
|
|
reply.Message(fmt.Sprintf("Your %s position is closed", m.closePositionTask.symbol))
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
}
|
2022-01-23 06:13:47 +00:00
|
|
|
|
2022-01-13 14:15:05 +00:00
|
|
|
// call position close
|
2022-01-23 06:13:47 +00:00
|
|
|
if kc, ok := reply.(interact.KeyboardController); ok {
|
|
|
|
kc.RemoveKeyboard()
|
|
|
|
}
|
2022-01-13 14:15:05 +00:00
|
|
|
|
|
|
|
// reply result
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func main() {
|
2022-01-13 17:58:04 +00:00
|
|
|
log.SetFormatter(&prefixed.TextFormatter{})
|
|
|
|
|
2022-01-13 14:15:05 +00:00
|
|
|
b, err := tb.NewBot(tb.Settings{
|
|
|
|
// You can also set custom API URL.
|
|
|
|
// If field is empty it equals to "https://api.telegram.org".
|
|
|
|
// URL: "http://195.129.111.17:8012",
|
|
|
|
|
|
|
|
Token: os.Getenv("TELEGRAM_BOT_TOKEN"),
|
|
|
|
Poller: &tb.LongPoller{Timeout: 10 * time.Second},
|
|
|
|
// Synchronous: false,
|
|
|
|
// Verbose: true,
|
|
|
|
// ParseMode: "",
|
|
|
|
// Reporter: nil,
|
|
|
|
// Client: nil,
|
|
|
|
// Offline: false,
|
|
|
|
})
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx := context.Background()
|
2022-01-16 11:06:26 +00:00
|
|
|
interact.AddMessenger(&interact.Telegram{
|
2022-01-13 18:36:06 +00:00
|
|
|
Private: true,
|
|
|
|
Bot: b,
|
2022-01-13 16:26:53 +00:00
|
|
|
})
|
|
|
|
|
2022-01-14 03:57:01 +00:00
|
|
|
interact.AddCustomInteraction(&interact.AuthInteract{
|
2022-01-13 18:13:59 +00:00
|
|
|
Strict: true,
|
2022-01-13 18:36:06 +00:00
|
|
|
Mode: interact.AuthModeToken,
|
|
|
|
Token: "123",
|
2022-01-13 14:15:05 +00:00
|
|
|
})
|
|
|
|
|
2022-08-24 04:53:10 +00:00
|
|
|
interact.AddCustomInteraction(&positionInteraction{})
|
2022-01-14 03:57:01 +00:00
|
|
|
if err := interact.Start(ctx); err != nil {
|
2022-01-13 14:15:05 +00:00
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
cmdutil.WaitForSignal(ctx, syscall.SIGINT, syscall.SIGTERM)
|
|
|
|
}
|