// Handle communication for a FOK order func fillOrKill(exg exchange.Interface, action string, amount, price float64, fillChan chan<- float64) { var ( id int64 err error order exchange.Order ) // Send order id, err = exg.SendOrder(action, "limit", amount, price) if isError(err) || id == 0 { fillChan <- 0 return } // Check status and cancel if necessary for { order, err = exg.GetOrderStatus(id) isError(err) if order.Status == "live" { _, err = exg.CancelOrder(id) isError(err) } else if order.Status == "dead" { break } // Continues while order status is empty } filledAmount := order.FilledAmount // Update position if action == "buy" { if exg.HasCryptoFee() { filledAmount = filledAmount * (1 - exg.Fee()) } exg.SetPosition(exg.Position() + filledAmount) } else { exg.SetPosition(exg.Position() - filledAmount) } // Print to log log.Printf("%s trade: %s %.4f at %.4f\n", exg, action, order.FilledAmount, price) fillChan <- filledAmount }
// Calculate arb needed for a trade based on existing positions func calcNeededArb(buyExg, sellExg exchange.Interface) float64 { // Middle between min and max center := (cfg.Sec.MaxArb + cfg.Sec.MinArb) / 2 // Half distance from center to min and max halfDist := (cfg.Sec.MaxArb - center) / 2 // If taking currency risk, add required premium if buyExg.CurrencyCode() != sellExg.CurrencyCode() { center += cfg.Sec.FXPremium } // Percent of max buyExgPct := buyExg.Position() / buyExg.MaxPos() sellExgPct := sellExg.Position() / sellExg.MaxPos() // Return required arb return center + buyExgPct*halfDist - sellExgPct*halfDist }