forked from decred/dcrdex
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
client/{mm, core}: Simple Arbitrage (decred#2480)
* client/{mm, core}: Simple Arbitrage This implements the simple arbitrage opportunity which only places orders when there is an arbitrage opportunity. - A `libxc` package is added which contains a `CEX` interface used to interact with a centralized exchange's API. It is implemented for Binance. - The new strategy is implemented in `mm_simple_arb.go` and can be run by creating a `BotConfig` with a non-nil `ArbCfg`. - A testbinance command line tool is added which starts a webserver that responds to the requests that the Binance testnet does not support. - A `VWAP` function is added to the client orderbook. - `client/comms/WSConn` is updated with a `SendRaw` function which sends arbitrary byte slices over the websocket connection.
- Loading branch information
Showing
18 changed files
with
3,895 additions
and
90 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 |
---|---|---|
@@ -0,0 +1,150 @@ | ||
package main | ||
|
||
/* | ||
* Starts an http server that responds with a hardcoded result to the binance API's | ||
* "/sapi/v1/capital/config/getall" endpoint. Binance's testnet does not support the | ||
* "sapi" endpoints, and this is the only "sapi" endpoint that we use. | ||
*/ | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"net/http" | ||
"os" | ||
"strconv" | ||
"strings" | ||
"sync" | ||
"time" | ||
|
||
"decred.org/dcrdex/client/websocket" | ||
"decred.org/dcrdex/dex" | ||
) | ||
|
||
const ( | ||
pongWait = 60 * time.Second | ||
pingPeriod = (pongWait * 9) / 10 | ||
) | ||
|
||
var ( | ||
log = dex.StdOutLogger("TBNC", dex.LevelDebug) | ||
) | ||
|
||
func main() { | ||
if err := mainErr(); err != nil { | ||
fmt.Fprint(os.Stderr, err, "\n") | ||
os.Exit(1) | ||
} | ||
os.Exit(0) | ||
} | ||
|
||
func mainErr() error { | ||
f := &fakeBinance{ | ||
wsServer: websocket.New(nil, log.SubLogger("WS")), | ||
balances: map[string]*balance{ | ||
"eth": { | ||
free: 1000.123432, | ||
locked: 0, | ||
}, | ||
"btc": { | ||
free: 1000.21314123, | ||
locked: 0, | ||
}, | ||
"ltc": { | ||
free: 1000.8689444, | ||
locked: 0, | ||
}, | ||
"bch": { | ||
free: 1000.2358249, | ||
locked: 0, | ||
}, | ||
"dcr": { | ||
free: 1000.2358249, | ||
locked: 0, | ||
}, | ||
}, | ||
} | ||
http.HandleFunc("/sapi/v1/capital/config/getall", f.handleWalletCoinsReq) | ||
|
||
return http.ListenAndServe(":37346", nil) | ||
} | ||
|
||
type balance struct { | ||
free float64 | ||
locked float64 | ||
} | ||
|
||
type fakeBinance struct { | ||
wsServer *websocket.Server | ||
|
||
balanceMtx sync.RWMutex | ||
balances map[string]*balance | ||
} | ||
|
||
func (f *fakeBinance) handleWalletCoinsReq(w http.ResponseWriter, r *http.Request) { | ||
ci := f.coinInfo() | ||
writeJSONWithStatus(w, ci, http.StatusOK) | ||
} | ||
|
||
type fakeBinanceNetworkInfo struct { | ||
Coin string `json:"coin"` | ||
MinConfirm int `json:"minConfirm"` | ||
Network string `json:"network"` | ||
UnLockConfirm int `json:"unLockConfirm"` | ||
WithdrawEnable bool `json:"withdrawEnable"` | ||
WithdrawFee string `json:"withdrawFee"` | ||
WithdrawIntegerMultiple string `json:"withdrawIntegerMultiple"` | ||
WithdrawMax string `json:"withdrawMax"` | ||
WithdrawMin string `json:"withdrawMin"` | ||
} | ||
|
||
type fakeBinanceCoinInfo struct { | ||
Coin string `json:"coin"` | ||
Free string `json:"free"` | ||
Locked string `json:"locked"` | ||
Withdrawing string `json:"withdrawing"` | ||
NetworkList []*fakeBinanceNetworkInfo `json:"networkList"` | ||
} | ||
|
||
func (f *fakeBinance) coinInfo() (coins []*fakeBinanceCoinInfo) { | ||
f.balanceMtx.Lock() | ||
for symbol, bal := range f.balances { | ||
bigSymbol := strings.ToUpper(symbol) | ||
coins = append(coins, &fakeBinanceCoinInfo{ | ||
Coin: bigSymbol, | ||
Free: strconv.FormatFloat(bal.free, 'f', 8, 64), | ||
Locked: strconv.FormatFloat(bal.locked, 'f', 8, 64), | ||
Withdrawing: "0", | ||
NetworkList: []*fakeBinanceNetworkInfo{ | ||
{ | ||
Coin: bigSymbol, | ||
Network: bigSymbol, | ||
MinConfirm: 1, | ||
WithdrawEnable: true, | ||
WithdrawFee: strconv.FormatFloat(0.00000800, 'f', 8, 64), | ||
WithdrawIntegerMultiple: strconv.FormatFloat(0.00000001, 'f', 8, 64), | ||
WithdrawMax: strconv.FormatFloat(1000, 'f', 8, 64), | ||
WithdrawMin: strconv.FormatFloat(0.01, 'f', 8, 64), | ||
}, | ||
}, | ||
}) | ||
} | ||
f.balanceMtx.Unlock() | ||
return | ||
} | ||
|
||
// writeJSON marshals the provided interface and writes the bytes to the | ||
// ResponseWriter with the specified response code. | ||
func writeJSONWithStatus(w http.ResponseWriter, thing interface{}, code int) { | ||
w.Header().Set("Content-Type", "application/json; charset=utf-8") | ||
b, err := json.Marshal(thing) | ||
if err != nil { | ||
w.WriteHeader(http.StatusInternalServerError) | ||
log.Errorf("JSON encode error: %v", err) | ||
return | ||
} | ||
w.WriteHeader(code) | ||
_, err = w.Write(append(b, byte('\n'))) | ||
if err != nil { | ||
log.Errorf("Write error: %v", err) | ||
} | ||
} |
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
Oops, something went wrong.