Example #1
0
func DecimalToString(res decimal.Decimal, min int32, max int32) string {
	if res.Cmp(decimal.New(10, min)) <= 0 || res.Cmp(decimal.New(10, max)) >= 0 {
		f, _ := res.Float64()
		return strconv.FormatFloat(f, 'G', -1, 64)
	}
	return res.String()
}
Example #2
0
func (ex *CaVirtex) PlaceOrder(mode OrderMode, amount decimal.Decimal, price decimal.Decimal, base, counter string) (status, id string, err error) {
	textMode := "sell"
	if mode == ORDER_BUY {
		textMode = "buy"
	}

	resp, err := ex.AuthenticatedPost("order", map[string]string{
		"currencypair": fmt.Sprintf("%s%s", base, counter),
		"mode":         textMode,
		"amount":       amount.String(),
		"price":        price.String(),
	})
	if err != nil {
		return "", "", err
	}

	result := struct {
		Status  string
		Message string
		ApiRate int
		Order   struct {
			Status string
			ID     int
		}
	}{}

	cnt, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", "", err
	}

	err = json.Unmarshal(cnt, &result)
	if err != nil {
		return "", "", err
	}

	if result.Status != "ok" {
		return "", "", fmt.Errorf("status=%s: %s", result.Status, result.Message)
	}

	return result.Order.Status, fmt.Sprintf("%d", result.Order.ID), nil
}
Example #3
0
func handleConnection(conn net.Conn) {
	var found bool
	var QuoteItem QuoteCacheItem
	if err != nil {
		// do stuff
		return
	}
	status := make([]byte, 100)
	_, err = conn.Read(status)
	if err != nil {
		// do stuff
		println("ERROR READ: " + err.Error())
		return
	}

	status = bytes.Trim(status, "\x00")

	inputs := strings.Split(string(status), ",")

	var price decimal.Decimal

	_, err := strconv.ParseBool(strings.ToLower(inputs[0]))
	APIUserId := inputs[1]
	stockSymbol := inputs[2]
	TransId := "1"
	GGuid := getNewGuid()
	Guid := GGuid.String()
	if len(inputs) > 3 {
		TransId = inputs[3]
		Guid = inputs[4]
	}

	QuoteItem, found = memCache[stockSymbol]
	if found {
		if QuoteItem.Expiration.After(time.Now()) {
			fmt.Fprintf(conn, string(QuoteItem.Value)+","+QuoteItem.Expiration.String())
			conn.Close()
			hit = hit + 1
			return
		} else {
			found = false
		}
	}
	miss = miss + 1
	if !found {
		messages := make(chan string)
		var returned bool = false
		num_threads := 0

		go func() {
			for returned == false {
				num_threads = num_threads + 1
				go func() {
					sendString := stockSymbol + "," + APIUserId + "\n"
					addr, err := net.ResolveTCPAddr("tcp", "quoteserve.seng.uvic.ca:"+quotePort)
					if err != nil {
						return
					}
					qconn, err := net.DialTCP("tcp", nil, addr)
					if err != nil {
						//error
						println("ERROR qconn: " + err.Error())
						return
					}
					defer qconn.Close()
					_, err = fmt.Fprintf(qconn, sendString)
					if err != nil {
						failOnError(err, "Error with fprintf")
					}
					response := make([]byte, 100)
					_, err = qconn.Read(response)
					returned = true
					messages <- string(response)
				}()
				time.Sleep(time.Duration(thread_wait) * time.Millisecond)
			}
		}()

		QuoteReturn := <-messages
		ParsedQuoteReturn := strings.Split(QuoteReturn, ",")
		price, err = decimal.NewFromString(ParsedQuoteReturn[0])
		if err != nil {
			//error
			println("ERROR PARSING")
		}

		backoff := 50 + rand.Intn(5)
		QuoteExpiration := time.Now().Add(time.Duration(backoff) * time.Second)

		_, err = conn.Write([]byte(price.String() + "," + QuoteExpiration.String()))
		conn.Close()
		stockSymbol = ParsedQuoteReturn[1]
		ReturnUserId := ParsedQuoteReturn[2]
		msTimeStamp, err := msToTime(ParsedQuoteReturn[3])
		if err != nil {
			//error

		}
		cryptoKey := stripCtlAndExtFromUTF8(ParsedQuoteReturn[4])
		cryptoKey = strings.TrimSpace(cryptoKey)

		if ReturnUserId != APIUserId {
			// system error

		}

		QuoteEvent := QuoteServerEvent{
			EventType:       "QuoteServerEvent",
			Guid:            Guid,
			OccuredAt:       time.Now(),
			TransactionId:   TransId,
			UserId:          APIUserId,
			Service:         "QUOTE",
			Server:          "QuoteCache",
			Price:           price.String(),
			StockSymbol:     stockSymbol,
			QuoteServerTime: msTimeStamp,
			Cryptokey:       cryptoKey,
		}
		SendRabbitMessage(QuoteEvent, QuoteEvent.EventType)

		tmpQuoteItem := QuoteCacheItem{
			Expiration: QuoteExpiration,
			Value:      price.String(),
		}
		memCache[stockSymbol] = tmpQuoteItem
		if err != nil {
			// system error
		}

		for i := 0; i < num_threads-1; i++ {
			<-messages
		}
		close(messages)
		return
	}
}
Example #4
0
func Buy(w http.ResponseWriter, r *http.Request) {
	zero, _ := decimal.NewFromString("0")
	type buy_struct struct {
		Amount string
		Symbol string
	}

	type return_struct struct {
		Error      bool
		SaleId     int
		Price      string
		NumShares  int64
		Expiration time.Duration
	}

	vars := mux.Vars(r)
	UserId := vars["id"]
	TransId := r.Header.Get("X-TransNo")
	if TransId == "" {
		TransId = "0"
	}

	decoder := json.NewDecoder(r.Body)
	var t buy_struct
	err := decoder.Decode(&t)

	//Audit UserCommand
	Guid := getNewGuid()
	CommandEvent := UserCommandEvent{
		EventType:     "UserCommandEvent",
		Guid:          Guid.String(),
		OccuredAt:     time.Now(),
		TransactionId: TransId,
		UserId:        UserId,
		Service:       "Command",
		Server:        Hostname,
		Command:       "BUY",
		StockSymbol:   t.Symbol,
		Funds:         t.Amount,
	}
	SendRabbitMessage(CommandEvent, CommandEvent.EventType)

	//Decode Request Body
	if err != nil {
		writeResponse(w, http.StatusBadRequest, "Request Body Is Invalid")
		return
	}

	//Validate Request Body
	AmountDec, err := decimal.NewFromString(t.Amount)
	if err != nil {
		writeResponse(w, http.StatusBadRequest, "Request Body Is Invalid")
		return
	}

	//Validate amount to buy
	if AmountDec.Cmp(zero) != 1 {
		writeResponse(w, http.StatusBadRequest, "Amount to buy is not a valid number")
		return
	}

	StockId := t.Symbol
	//Validate Stock Symbol
	if len(StockId) == 0 || len(StockId) > 3 {
		writeResponse(w, http.StatusBadRequest, "Symbol is Not Valid")
		return
	}

	//Get and Validate Quote
	var strPrice string
	var strExpiration string
	strPrice, strExpiration = getStockPrice(TransId, "true", UserId, StockId, Guid.String())
	var quotePrice decimal.Decimal
	quotePrice, err = decimal.NewFromString(strPrice)
	if err != nil {
		writeResponse(w, http.StatusInternalServerError, "Quote Return is not Valid")
		return
	}
	if quotePrice.Cmp(zero) != 1 {
		writeResponse(w, http.StatusBadRequest, "Amount to buy is not a valid number: "+quotePrice.String())
		return
	}

	//Verify Expiration Time
	ExpirationTime, err := time.Parse("2006-01-02 15:04:05 -0700 MST", strExpiration)
	if err != nil {
		writeResponse(w, http.StatusOK, "Expiration Conversion Error")
		return
	}

	//Check If User Exists
	db, uid, found, _ := getDatabaseUserId(UserId)
	if found == false {
		writeResponse(w, http.StatusBadRequest, "User Does Not Exist")
		return
	}

	//Calculate Stock To Buy
	toBuy := (AmountDec.Div(quotePrice)).IntPart()

	//Validate Buy Amount
	if toBuy < 1 {
		writeResponse(w, http.StatusBadRequest, "Cannot Buy less than 1 stock")
		return
	}

	strBuy := strconv.Itoa(int(toBuy))

	//Add Pending Purchase for Amount
	var PurchaseId int
	rows, err := db.Query(addPendingPurchase, uid, t.Symbol, strBuy, strPrice, time.Now(), ExpirationTime)
	defer rows.Close()
	if err != nil {
		writeResponse(w, http.StatusInternalServerError, "Failed to Create Purchase")
		return
	}
	rows.Next()
	err = rows.Scan(&PurchaseId)
	if err != nil {
		writeResponse(w, http.StatusBadRequest, "Sale Id Request Failed")
		return
	}
	TimeToExpiration := (ExpirationTime.Sub(time.Now())) / time.Millisecond
	//Build Response
	rtnStruct := return_struct{false, PurchaseId, strPrice, toBuy, TimeToExpiration}
	strRtnStruct, err := json.Marshal(rtnStruct)

	//success
	writeResponse(w, http.StatusOK, string(strRtnStruct))
	return
}
Example #5
0
func Quote(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	StockId := vars["symbol"]
	UserId := vars["id"]
	TransId := r.Header.Get("X-TransNo")
	if TransId == "" {
		TransId = "0"
	}

	//Audit UserCommand
	Guid := getNewGuid()
	CommandEvent := UserCommandEvent{
		EventType:     "UserCommandEvent",
		Guid:          Guid.String(),
		OccuredAt:     time.Now(),
		TransactionId: TransId,
		UserId:        UserId,
		Service:       "Command",
		Server:        "B134",
		Command:       "QUOTE",
		StockSymbol:   StockId,
		Funds:         "",
	}
	SendRabbitMessage(CommandEvent, CommandEvent.EventType)

	//Check Stock Symbol
	if len(StockId) == 0 || len(StockId) > 3 {
		writeResponse(w, http.StatusBadRequest, "Symbol is Not Valid")
		return
	}

	//Get Stock Price
	var strPrice string
	strPrice, _ = getStockPrice(TransId, "false", UserId, StockId, Guid.String())

	//Verify Return Price
	var price decimal.Decimal
	price, err := decimal.NewFromString(strPrice)
	if err != nil {
		writeResponse(w, http.StatusBadRequest, "Quote Return: "+err.Error())
		return
	}

	//Success
	var Output string = "The Quote For UserId " + UserId + " and StockId " + StockId + " returned " + price.String()
	writeResponse(w, http.StatusOK, Output)
}