-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #5 from giansalex/notify-improvements
Notifications
- Loading branch information
Showing
15 changed files
with
325 additions
and
136 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,4 +23,4 @@ jobs: | |
uses: actions/checkout@v2 | ||
|
||
- name: Build | ||
run: go build -v . | ||
run: go build -v -o binance ./app |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,26 +30,72 @@ For sell orders with static stoploss | |
./binance -pair=BTC/USDT -price=9400 -amount=0.1 | ||
``` | ||
|
||
Use telegram for notifications. | ||
## Notifications | ||
|
||
- Telegram. | ||
```sh | ||
./binance -pair=BTC/USDT -percent=3 -interval=60 -telegram.chat=<user-id> | ||
``` | ||
> For get user id, talk o the [userinfobot](https://t.me/userinfobot) | ||
![telegram binance bot](https://user-images.githubusercontent.com/14926587/127190283-b7117dd2-dd03-421b-ae49-95997503ae67.png) | ||
|
||
> For get user id, talk to the [userinfobot](https://t.me/userinfobot) | ||
|
||
- Mailing. | ||
```sh | ||
./binance -pair=BTC/USDT -percent=3 \ | ||
-mail.host="smtp.example.com" \ | ||
-mail.port=587 \ | ||
-mail.user="[email protected]" \ | ||
-mail.pass="xxxx" \ | ||
-mail.from="[email protected]" \ | ||
-mail.to="[email protected]" | ||
``` | ||
|
||
> You can notify both: telegram, mail. | ||
## Docker | ||
|
||
You can run in docker container. | ||
```bash | ||
docker pull giansalex/binance-stoploss | ||
# create container | ||
docker run -d --name binance_sell_BTC giansalex/binance-stoploss \ | ||
-type=BUY \ | ||
-pair=BTC/USDT \ | ||
-percent=5 \ | ||
-amount=0.01 | ||
``` | ||
|
||
List available parameters | ||
```sh | ||
-type string | ||
order type: SELL or BUY (default: SELL) | ||
-pair string | ||
market pair, example: BNB/USDT | ||
-amount string | ||
(optional) amount to order (sell or buy) on stoploss | ||
-interval int | ||
interval in seconds to update price, example: 30 (30 sec.) (default 30) | ||
-price float | ||
price (for static stoploss) | ||
-mail.from string | ||
(optional) email sender | ||
-mail.host string | ||
(optional) SMTP Host | ||
-mail.pass string | ||
(optional) SMTP Password | ||
-mail.port int | ||
(optional) SMTP Port (default 587) | ||
-mail.to string | ||
(optional) email receptor | ||
-mail.user string | ||
(optional) SMTP User | ||
-pair string | ||
market pair, example: BNB/USDT | ||
-percent float | ||
percent (for trailing stoploss), example: 3.0 (3%) | ||
-amount float | ||
(optional) amount to order (sell or buy) on stoploss, default all balance | ||
percent (for trailing stop loss), example: 3.0 (3%) | ||
-price float | ||
price (for static stop loss), example: 9200.00 (BTC price) | ||
-stop-change | ||
Notify on stoploss change (default: false) | ||
-telegram.chat int | ||
(optional) telegram User ID for notify | ||
-type string | ||
order type: SELL or BUY (default "SELL") | ||
|
||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
package cmd | ||
|
||
import ( | ||
"context" | ||
"flag" | ||
"log" | ||
"os" | ||
"strings" | ||
"time" | ||
|
||
binance "github.com/adshao/go-binance/v2" | ||
"github.com/giansalex/binance-stoploss/notify" | ||
"github.com/giansalex/binance-stoploss/stoploss" | ||
"github.com/hashicorp/go-retryablehttp" | ||
) | ||
|
||
var ( | ||
typePtr = flag.String("type", "SELL", "order type: SELL or BUY") | ||
pairPtr = flag.String("pair", "", "market pair, example: BNB/USDT") | ||
percentPtr = flag.Float64("percent", 0.00, "percent (for trailing stop loss), example: 3.0 (3%)") | ||
pricePtr = flag.Float64("price", 0.00, "price (for static stop loss), example: 9200.00 (BTC price)") | ||
intervalPtr = flag.Int("interval", 30, "interval in seconds to update price, example: 30 (30 sec.)") | ||
amountPtr = flag.String("amount", "", "(optional) amount to order (sell or buy) on stoploss") | ||
notifyChangesPtr = flag.Bool("stop-change", false, "Notify on stoploss change (default: false)") | ||
chatPtr = flag.Int64("telegram.chat", 0, "(optional) telegram User ID for notify") | ||
mailHostPtr = flag.String("mail.host", "", "(optional) SMTP Host") | ||
mailPortPtr = flag.Int("mail.port", 587, "(optional) SMTP Port") | ||
mailUserPtr = flag.String("mail.user", "", "(optional) SMTP User") | ||
mailPassPtr = flag.String("mail.pass", "", "(optional) SMTP Password") | ||
mailFromPtr = flag.String("mail.from", "", "(optional) email sender") | ||
mailToPtr = flag.String("mail.to", "", "(optional) email receptor") | ||
) | ||
|
||
func Execute() { | ||
flag.Parse() | ||
apiKey := os.Getenv("BINANCE_APIKEY") | ||
secret := os.Getenv("BINANCE_SECRET") | ||
|
||
if apiKey == "" || secret == "" { | ||
log.Fatal("BINANCE_APIKEY, BINANCE_SECRET are required") | ||
} | ||
|
||
if pairPtr == nil || *pairPtr == "" { | ||
log.Fatal("pair market is required") | ||
} | ||
|
||
if (percentPtr == nil || *percentPtr <= 0) && (pricePtr == nil || *pricePtr <= 0) { | ||
log.Fatal("a price or percent parameter is required") | ||
} | ||
|
||
retryClient := retryablehttp.NewClient() | ||
retryClient.Logger = nil | ||
retryClient.RetryMax = 10 | ||
api := binance.NewClient(apiKey, secret) | ||
api.HTTPClient = retryClient.StandardClient() | ||
notifier := buildNotify() | ||
config := &stoploss.Config{ | ||
OrderType: strings.ToUpper(*typePtr), | ||
Market: *pairPtr, | ||
Price: *pricePtr, | ||
Quantity: *amountPtr, | ||
StopFactor: *percentPtr / 100, | ||
NotifyStopChange: *notifyChangesPtr, | ||
} | ||
trailing := stoploss.NewTrailing(stoploss.NewExchange(context.Background(), api), notifier, ¬ify.LogNotify{}, config) | ||
|
||
for { | ||
if trailing.RunStop() { | ||
break | ||
} | ||
|
||
time.Sleep(time.Duration(*intervalPtr) * time.Second) | ||
} | ||
} | ||
|
||
func buildNotify() notify.SingleNotify { | ||
notifiers := []notify.SingleNotify{} | ||
|
||
tgToken := os.Getenv("TELEGRAM_TOKEN") | ||
if *chatPtr != 0 && tgToken != "" { | ||
notifiers = append(notifiers, notify.NewTelegramNotify(tgToken, *chatPtr)) | ||
} | ||
|
||
if *mailHostPtr != "" && *mailUserPtr != "" && *mailPassPtr != "" && *mailFromPtr != "" && *mailToPtr != "" { | ||
subject := "Binance StopLoss Bot" | ||
notifiers = append(notifiers, notify.NewMailNotify(*mailHostPtr, *mailPortPtr, *mailUserPtr, *mailPassPtr, subject, *mailFromPtr, *mailToPtr)) | ||
} | ||
|
||
return stoploss.NewNotify(notifiers) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package main | ||
|
||
import "github.com/giansalex/binance-stoploss/app/cmd" | ||
|
||
func main() { | ||
cmd.Execute() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package notify | ||
|
||
import ( | ||
"log" | ||
"regexp" | ||
) | ||
|
||
const regex = `<.*?>` | ||
|
||
type LogNotify struct { | ||
} | ||
|
||
// Send notify to log | ||
func (lnotify *LogNotify) Send(message string) error { | ||
log.Println(lnotify.clearHtml(message)) | ||
|
||
return nil | ||
} | ||
|
||
// This method uses a regular expresion to remove HTML tags. | ||
func (lnotify *LogNotify) clearHtml(s string) string { | ||
r := regexp.MustCompile(regex) | ||
return r.ReplaceAllString(s, "") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package notify | ||
|
||
import ( | ||
"strings" | ||
|
||
"gopkg.in/gomail.v2" | ||
) | ||
|
||
type MailNotify struct { | ||
sender gomail.SendCloser | ||
subject string | ||
from string | ||
to string | ||
} | ||
|
||
func NewMailNotify(host string, port int, username, password, subject, from, to string) *MailNotify { | ||
d := gomail.NewDialer(host, port, username, password) | ||
s, err := d.Dial() | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
return &MailNotify{s, subject, from, to} | ||
} | ||
|
||
// Send notify to email | ||
func (mailNotify *MailNotify) Send(message string) error { | ||
m := gomail.NewMessage() | ||
m.SetHeader("From", mailNotify.from) | ||
m.SetHeader("To", mailNotify.to) | ||
m.SetHeader("Subject", mailNotify.subject) | ||
m.SetBody("text/html", mailNotify.fixLineEnding(message)) | ||
|
||
return gomail.Send(mailNotify.sender, m) | ||
} | ||
|
||
func (mailNotify *MailNotify) fixLineEnding(msg string) string { | ||
return strings.ReplaceAll(msg, "\n", "<br/>") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package notify | ||
|
||
type SingleNotify interface { | ||
Send(message string) error | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package notify | ||
|
||
import ( | ||
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api" | ||
) | ||
|
||
type TelegramNotify struct { | ||
token string | ||
chatID int64 | ||
} | ||
|
||
func NewTelegramNotify(token string, chatID int64) *TelegramNotify { | ||
return &TelegramNotify{token: token, chatID: chatID} | ||
} | ||
|
||
// Send notify to telegram | ||
func (tgNotify *TelegramNotify) Send(message string) error { | ||
bot, err := tgbotapi.NewBotAPI(tgNotify.token) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
msg := tgbotapi.NewMessage(tgNotify.chatID, message) | ||
msg.ParseMode = "html" | ||
|
||
_, err = bot.Send(msg) | ||
|
||
return err | ||
} |
Oops, something went wrong.