NuBotTrading / src / main / java / com / nubits / nubot / ALPClient / TestALP.java

/*
 * Copyright (c) 2015. Nu Development Team
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

package com.nubits.nubot.ALPClient;


import com.nubits.nubot.bot.Global;
import com.nubits.nubot.bot.SessionManager;
import com.nubits.nubot.global.Settings;
import com.nubits.nubot.models.ApiResponse;
import com.nubits.nubot.models.CurrencyList;
import com.nubits.nubot.models.SignedRequest;
import com.nubits.nubot.options.NuBotConfigException;
import com.nubits.nubot.options.NuBotOptions;
import com.nubits.nubot.testsmanual.WrapperTestUtils;
import com.nubits.nubot.trading.TradeUtils;
import com.nubits.nubot.utils.InitTests;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.rmi.runtime.Log;

public class TestALP {
    NuBotOptions opt;
    String unit;

    //define Logging by using predefined Settings which points to an XML
    static {
        System.setProperty("logback.configurationFile", Settings.TEST_LOGXML);
    }

    private static final Logger LOG = LoggerFactory.getLogger(TestALP.class.getName());

    private static final String TEST_OPTIONS_PATH = "config/myconfig/latest/bittrex.json";


    public static void main(String[] args) {
        InitTests.setLoggingFilename(TestALP.class.getSimpleName());
        InitTests.loadConfig(TEST_OPTIONS_PATH);

        TestALP test = new TestALP();
        test.init(Global.options); //Pass an empty string to avoid placing the orders, or exchange name
        test.exec();
    }

    private void exec() {

        //Setup the ALPService object
        ALPService alpService = new ALPService(opt.poolURI);

        //Try to register --------------------------------------------
        ApiResponse registerResponse = alpService.register(opt.apiKey, opt.poolPayoutAddress, "test_exchange", unit); //TODO change to a real exchange name opt.exchangeName

        if (registerResponse.isPositive()) {
            LOG.info("Positive answer from alpService.register: " + registerResponse.getResponseObject().toString());
        } else {
            LOG.error("Error from alpService.register: " + registerResponse.getError().toString());
        }


        //Generate the signed request with list of orders ------------


        if (Global.trade.isFree()) {
            Global.trade.setBusy();
            executeGenerateAndSubmitRequest(alpService);
            Global.trade.setFree();
        } else {
            String method = "ALP createRequest";
            //Another thread is probably executing a query. Init the retry procedure
            long sleeptime = Settings.RETRY_SLEEP_INCREMENT * 1;
            int counter = 0;
            long startTimeStamp = System.currentTimeMillis();
            LOG.debug(method + " has been blocked, another call is being processed ");
            boolean exit = false;
            do {
                counter++;
                sleeptime = counter * Settings.RETRY_SLEEP_INCREMENT; //Increase sleep time
                sleeptime += (int) (Math.random() * 200) - 100;// Add +- 100 ms random to facilitate competition
                LOG.debug("Retrying for the " + counter + " time. Sleep for " + sleeptime + "; Method=" + method);
                try {
                    Thread.sleep(sleeptime);
                } catch (InterruptedException e) {
                    LOG.error(e.toString());
                }

                //Try executing the call
                if (Global.trade.isFree()) {
                    LOG.debug("Finally the exchange is free, executing query after " + counter + " attempt. Method=" + method);
                    Global.trade.setBusy();
                    executeGenerateAndSubmitRequest(alpService);
                    Global.trade.setFree();
                    break; //Exit loop
                } else {
                    LOG.debug("Exchange still busy : " + counter + " .Will retry soon; Method=" + method);
                    exit = false;
                }
                if (System.currentTimeMillis() - startTimeStamp >= Settings.TIMEOUT_QUERY_RETRY) {
                    exit = true;
                    LOG.error("Method=" + method + " failed too many times and timed out. attempts = " + counter);
                }
            } while (!exit);
        }

        //Try to get user stats
        ApiResponse userStatsResponse = alpService.getUserStats(opt.apiKey);

        if (userStatsResponse.isPositive()) {
            LOG.info("Positive answer from alpService.getUserStats: " + userStatsResponse.getResponseObject().toString());
        } else {
            LOG.error("Error from alpService.getUserStats: " + userStatsResponse.getError().toString());
        }


        //Try to get user orders
        ApiResponse userOrdersResponse = alpService.getUserOrders(opt.apiKey);

        if (userOrdersResponse.isPositive()) {
            LOG.info("Positive answer from alpService.getUserOrders: " + userOrdersResponse.getResponseObject().toString());
        } else {
            LOG.error("Error from alpService.getUserOrders: " + userOrdersResponse.getError().toString());
        }


        //Try to get server status
        ApiResponse serverStatusResponse = alpService.getServerStatus();

        if (serverStatusResponse.isPositive()) {
            LOG.info("Positive answer from alpService.getServerStatus: " + serverStatusResponse.getResponseObject().toString());
        } else {
            LOG.error("Error from alpService.getServerStatus: " + serverStatusResponse.getError().toString());
        }


        //Try to get exchanges
        ApiResponse exchangesResponse = alpService.getExchanges();

        if (exchangesResponse.isPositive()) {
            LOG.info("Positive answer from alpService.getExchanges: " + exchangesResponse.getResponseObject().toString());
        } else {
            LOG.error("Error from alpService.getExchanges: " + exchangesResponse.getError().toString());
        }
    }


    private void executeGenerateAndSubmitRequest(ALPService alpService) {
        SignedRequest openOrdersRequest = Global.trade.getOpenOrdersRequest(opt.getPair());
        LOG.debug("req:" + openOrdersRequest.getReqJSON() + " \n sign:" + openOrdersRequest.getSign());
        ApiResponse signedOrderResponse = alpService.submitOpenOrdersRequest(opt.apiKey, openOrdersRequest.getReqJSON(), openOrdersRequest.getSign(), "test_exchange", unit); //TODO change to a real exchange name opt.exchangeName

        if (signedOrderResponse.isPositive()) {
            LOG.info("Positive answer from alpService.submitOpenOrdersRequest: " + signedOrderResponse.getResponseObject().toString());
        } else {
            LOG.error("Error from alpService.submitOpenOrdersRequest: " + signedOrderResponse.getError().toString());
        }
    }

    private void init(NuBotOptions options) {
        opt = options;
        unit = opt.getPair().getPaymentCurrency().getCode().toLowerCase();

        SessionManager.setModeRunning();

        //Setup the exchange
        try {
            WrapperTestUtils.configureExchange(opt.exchangeName);
        } catch (NuBotConfigException e) {
            LOG.error(e.getMessage());
        }

        LOG.info("Executing ALP test on exchange: " + opt.exchangeName + "\n" +
                "poolURI: " + opt.poolURI + "\n" +
                "apiKey: " + opt.apiKey + "\n" +
                "poolPayoutAddress: " + opt.poolPayoutAddress + "\n" +
                "unit: " + unit);

        LOG.info("Deleting existing orders");

        //Delete all orders
        WrapperTestUtils.testClearAllOrders(opt.getPair());

        LOG.info("Placing some random orders");

        //Place some random orders for the sake of it
        //TradeUtils.placeSomeRandomOrders();

    }


}