Exemplo n.º 1
0
void Exchange_BitCurex::dataReceivedAuth(QByteArray data, int reqType)
{
    if(debugLevel)logThread->writeLog("RCV: "+data);
    if(data.size()<4)return;
    if(data.at(0)==QLatin1Char('<'))return;

    bool success=true;

	switch(reqType)
	{
    case 103: //ticker
        if(data.startsWith("{\"lowest_tx_price_h\": \""))
        {
            QByteArray tickerHigh=getMidData("\"highest_tx_price_h\": \"","\", \"",&data);
			if(!tickerHigh.isEmpty())
			{
                double newTickerHigh=tickerHigh.toDouble();
                if(newTickerHigh!=lastTickerHigh)
                    IndicatorEngine::setValue(baseValues.exchangeName,baseValues.currentPair.symbol,"High",newTickerHigh);
				lastTickerHigh=newTickerHigh;
			}

            QByteArray tickerLow=getMidData("\"lowest_tx_price_h\": \"","\", \"",&data);
			if(!tickerLow.isEmpty())
			{
                double newTickerLow=tickerLow.toDouble();
                if(newTickerLow!=lastTickerLow)
                    IndicatorEngine::setValue(baseValues.exchangeName,baseValues.currentPair.symbol,"Low",newTickerLow);
				lastTickerLow=newTickerLow;
			}

            QByteArray tickerSell=getMidData("\"best_bid_h\": \"","\", \"",&data);
			if(!tickerSell.isEmpty())
            {
                double newTickerSell=tickerSell.toDouble();
                if(newTickerSell!=lastTickerSell)
                    IndicatorEngine::setValue(baseValues.exchangeName,baseValues.currentPair.symbol,"Sell",newTickerSell);
				lastTickerSell=newTickerSell;
			}

            QByteArray tickerBuy=getMidData("\"best_ask_h\": \"","\", \"",&data);
			if(!tickerBuy.isEmpty())
            {
                double newTickerBuy=tickerBuy.toDouble();
                if(newTickerBuy!=lastTickerBuy)
                    IndicatorEngine::setValue(baseValues.exchangeName,baseValues.currentPair.symbol,"Buy",newTickerBuy);
				lastTickerBuy=newTickerBuy;
			}

            QByteArray tickerVolume=getMidData("\"total_volume_h\": \"","\", \"",&data);
			if(!tickerVolume.isEmpty())
			{
                double newTickerVolume=tickerVolume.toDouble();
                if(newTickerVolume!=lastTickerVolume)
                    IndicatorEngine::setValue(baseValues.exchangeName,baseValues.currentPair.symbol,"Volume",newTickerVolume);
				lastTickerVolume=newTickerVolume;
			}

            QByteArray tickerLast=getMidData("\"last_tx_price_h\": \"","\", \"",&data);
            if(!tickerLast.isEmpty())
            {
                double newTickerLast=tickerLast.toDouble();
                if(newTickerLast!=lastTickerLast)
                    IndicatorEngine::setValue(baseValues.exchangeName,baseValues.currentPair.symbol,"Last",newTickerLast);
                lastTickerLast=newTickerLast;
            }
        }
        else success=false;
		break;//ticker
    case 109: //trades
        if(data.startsWith("{\"status\": \"ok\", \"data\": {\"symbol\": \""+baseValues.currentPair.symbol.toLower().toLatin1()+"\", \"trades\": [{\""))
		{
            QStringList tradeList=QString(data).split("}, {");
			QList<TradesItem> *newTradesItems=new QList<TradesItem>;

            TradesItem newItem;
            for(int n=tradeList.count()-1;n>=0;n--)
			{
				QByteArray tradeData=tradeList.at(n).toLatin1()+"}";

                newItem.date=getMidData("\"ts\": ",", \"",&tradeData).toUInt();
                if(newItem.date<startTradesDate)continue;

                quint32 currentTid=getMidData("\"txid\": ",", \"",&tradeData).toUInt();
                if(lastFetchTid>=currentTid)continue;
                lastFetchTid=currentTid;

                newItem.price=getMidData("\"price\": ",", \"",&tradeData).toDouble();
                newItem.amount=getMidData("\"amount\": ",", \"",&tradeData).toDouble();
                newItem.orderType=getMidData("\"type\": \"","\"}",&tradeData)=="ask"?-1:1;
                newItem.symbol=baseValues.currentPair.symbol;

				if(newItem.isValid())(*newTradesItems)<<newItem;
				else if(debugLevel)logThread->writeLog("Invalid trades fetch data line:"+tradeData,2);
			}

            if(newItem.price>0&&lastTradesDate<newItem.date)
            {
                lastTradesDate=newItem.date;
                IndicatorEngine::setValue(baseValues.exchangeName,baseValues.currentPair.symbol,"Last",newItem.price);
                lastTickerLast=newItem.price;
            }
            if(newTradesItems->count())emit addLastTrades(baseValues.currentPair.symbol,newTradesItems);
			else delete newTradesItems;
        }
        else if(!data.startsWith("{\"status\": \"ok\", \"data\": {\"symbol\": \""))success=false;
		break;//trades
	case 111: //depth
        if(data.startsWith("{\"symbol\": \""+baseValues.currentPair.symbol.toLower().toLatin1()+"\", \"bids\": ["))
		{
            emit depthRequestReceived();

			if(lastDepthData!=data)
			{
				lastDepthData=data;
				depthAsks=new QList<DepthItem>;
				depthBids=new QList<DepthItem>;

                QMap<double,double> currentAsksMap;
                QStringList asksList=QString(getMidData("asks\": [[","]]",&data)).split("], [");
                double groupedPrice=0.0;
                double groupedVolume=0.0;
				int rowCounter=0;

				for(int n=0;n<asksList.count();n++)
				{
					if(baseValues.depthCountLimit&&rowCounter>=baseValues.depthCountLimit)break;
                    QStringList currentPair=asksList.at(n).split(", ");
					if(currentPair.count()!=2)continue;
                    double priceDouble=currentPair.first().toDouble();
                    double amount=currentPair.last().toDouble();

					if(baseValues.groupPriceValue>0.0)
					{
						if(n==0)
						{
                            emit depthFirstOrder(baseValues.currentPair.symbol,priceDouble,amount,true);
							groupedPrice=baseValues.groupPriceValue*(int)(priceDouble/baseValues.groupPriceValue);
							groupedVolume=amount;
						}
						else
						{
							bool matchCurrentGroup=priceDouble<groupedPrice+baseValues.groupPriceValue;
							if(matchCurrentGroup)groupedVolume+=amount;
							if(!matchCurrentGroup||n==asksList.count()-1)
							{
                                depthSubmitOrder(baseValues.currentPair.symbol,
                                                 &currentAsksMap,groupedPrice+baseValues.groupPriceValue,groupedVolume,true);
								rowCounter++;
								groupedVolume=amount;
								groupedPrice+=baseValues.groupPriceValue;
							}
						}
					}
					else
					{
                        depthSubmitOrder(baseValues.currentPair.symbol,
                                         &currentAsksMap,priceDouble,amount,true);
						rowCounter++;
					}
				}
                QList<double> currentAsksList=lastDepthAsksMap.keys();
				for(int n=0;n<currentAsksList.count();n++)
                    if(currentAsksMap.value(currentAsksList.at(n),0)==0)depthUpdateOrder(baseValues.currentPair.symbol,
                                                                                         currentAsksList.at(n),0.0,true);
				lastDepthAsksMap=currentAsksMap;

                QMap<double,double> currentBidsMap;
                QStringList bidsList=QString(getMidData("bids\": [[","]]",&data)).split("], [");
				groupedPrice=0.0;
				groupedVolume=0.0;
				rowCounter=0;

				for(int n=0;n<bidsList.count();n++)
				{
					if(baseValues.depthCountLimit&&rowCounter>=baseValues.depthCountLimit)break;
                    QStringList currentPair=bidsList.at(n).split(", ");
					if(currentPair.count()!=2)continue;
                    double priceDouble=currentPair.first().toDouble();
                    double amount=currentPair.last().toDouble();
					if(baseValues.groupPriceValue>0.0)
					{
						if(n==0)
						{
                            emit depthFirstOrder(baseValues.currentPair.symbol,priceDouble,amount,false);
							groupedPrice=baseValues.groupPriceValue*(int)(priceDouble/baseValues.groupPriceValue);
							groupedVolume=amount;
						}
						else
						{
							bool matchCurrentGroup=priceDouble>groupedPrice-baseValues.groupPriceValue;
							if(matchCurrentGroup)groupedVolume+=amount;
							if(!matchCurrentGroup||n==asksList.count()-1)
							{
                                depthSubmitOrder(baseValues.currentPair.symbol,
                                                 &currentBidsMap,groupedPrice-baseValues.groupPriceValue,groupedVolume,false);
								rowCounter++;
								groupedVolume=amount;
								groupedPrice-=baseValues.groupPriceValue;
							}
						}
					}
					else
					{
                        depthSubmitOrder(baseValues.currentPair.symbol,
                                         &currentBidsMap,priceDouble,amount,false);
						rowCounter++;
					}
				}
                QList<double> currentBidsList=lastDepthBidsMap.keys();
				for(int n=0;n<currentBidsList.count();n++)
                    if(currentBidsMap.value(currentBidsList.at(n),0)==0)depthUpdateOrder(baseValues.currentPair.symbol,
                                                                                         currentBidsList.at(n),0.0,false);
				lastDepthBidsMap=currentBidsMap;

                emit depthSubmitOrders(baseValues.currentPair.symbol,depthAsks, depthBids);
				depthAsks=0;
				depthBids=0;
			}
		}
        else if(!data.startsWith("{\"symbol\": \""))
        {
            if(debugLevel)logThread->writeLog("Invalid depth data:"+data,2);
            success=false;
        }
		break;
	case 202: //info
        if(data.startsWith("{\"status\": \"ok\", \"data\": {\""))
        {
            QByteArray fundsData=getMidData("data\": {","}",&data);
            QByteArray btcBalance=getMidData(baseValues.currentPair.currAStrLow+"\": \"","\"",&fundsData);
			if(!btcBalance.isEmpty())
			{
                double newBtcBalance=btcBalance.toDouble();
                if(lastBtcBalance!=newBtcBalance)emit accBtcBalanceChanged(baseValues.currentPair.symbol,newBtcBalance);
				lastBtcBalance=newBtcBalance;
			}

            QByteArray usdBalance=getMidData("\""+baseValues.currentPair.currBStrLow+"\": \"","\"",&fundsData);
			if(!usdBalance.isEmpty())
			{
                double newUsdBalance=usdBalance.toDouble();
                if(newUsdBalance!=lastUsdBalance)emit accUsdBalanceChanged(baseValues.currentPair.symbol,newUsdBalance);
				lastUsdBalance=newUsdBalance;
			}

            QByteArray fee=getMidData("\"fee\": ",",",&data);
            if(!fee.isEmpty())
            {
                double newFee=fee.toDouble();
                if(newFee!=lastFee)emit accFeeChanged(baseValues.currentPair.symbol,newFee);
                lastFee=newFee;
            }
        }
        else success=false;
		break;//info
	case 204://orders
        if(data.startsWith("{\"status\": \"ok\", \"data\": [{\""))
        {
            if(lastOrders!=data)
            {
                lastOrders=data;

                QStringList ordersList=QString(data).split("}, {");
                QList<OrderItem> *orders=new QList<OrderItem>;
                for(int n=0;n<ordersList.count();n++)
                {
                    OrderItem currentOrder;
                    QByteArray currentOrderData=ordersList.at(n).toLatin1()+"}";

                    currentOrder.oid=getMidData("id\": \"","\"}",&currentOrderData);
                    QByteArray tempDate=getMidData("issued\": ",", \"",&currentOrderData);
                    tempDate.chop(3);
                    currentOrder.date=tempDate.toUInt();
                    currentOrder.type=getMidData("type\": \"","\", \"",&currentOrderData)=="ask";
                    currentOrder.amount=getMidData("volume\": \"","\", \"",&currentOrderData).toDouble();
                    currentOrder.price=getMidData("limit\": \"","\", \"",&currentOrderData).toDouble();
                    currentOrder.symbol="BTC"+getMidData("currency\": \"","\", \"",&currentOrderData).toUpper();
                    currentOrder.status=1;

                    if(currentOrder.isValid())(*orders)<<currentOrder;
                }
                emit orderBookChanged(baseValues.currentPair.symbol,orders);
            }
        }
        else if(data.startsWith("{\"status\": \"ok\", \"data\": ["))
            emit ordersIsEmpty();
        else
            success=false;
        break;//orders
	case 305: //order/cancel
        if(data.startsWith("{\"status\": \"ok\", \"data\": [{\""))
        {
            QByteArray oid=getMidData("id\": \"","\"",&data);
            if(!oid.isEmpty())emit orderCanceled(baseValues.currentPair.symbol,oid);
		}
        else success=false;
		break;//order/cancel
    case 306: if(debugLevel)logThread->writeLog("Buy OK: "+data,2);break;//order/buy
    case 307: if(debugLevel)logThread->writeLog("Sell OK: "+data,2);break;//order/sell
    case 208: ///history
        if(data.startsWith("{\"status\": \"ok\", \"data\": {\"symbol\": \""+baseValues.currentPair.symbol.toLower().toLatin1()+"\", \"trades\": ["))
        {
            if(lastHistory!=data)
            {
                lastHistory=data;

                QStringList dataList=QString(data).split("}, {");
                QList<HistoryItem> *historyItems=new QList<HistoryItem>;
                quint32 currentId;
                quint32 maxId=0;
                for(int n=dataList.count()-1;n>=0;n--)
                {
                    QByteArray curLog=dataList.at(n).toLatin1()+"}";

                    currentId=getMidData("txid\": ",", \"",&curLog).toUInt();
                    if(currentId<=lastHistoryId)break;
                    if(n==dataList.count()-1)maxId=currentId;

                    HistoryItem currentHistoryItem;
                    QByteArray logType=getMidData("type\": \"","\"}",&curLog);
                    if(logType=="ask")currentHistoryItem.type=2;
                    else if(logType=="bid")currentHistoryItem.type=1;
				
                    if(currentHistoryItem.type)
                    {
                        currentHistoryItem.symbol=baseValues.currentPair.symbol;
                        currentHistoryItem.dateTimeInt=getMidData("ts\": ",", \"",&curLog).toUInt();
                        currentHistoryItem.price=getMidData("price\": ",", \"",&curLog).toDouble();
                        currentHistoryItem.volume=getMidData("amount\": ",", \"",&curLog).toDouble();
                        if(currentHistoryItem.isValid())(*historyItems)<<currentHistoryItem;
                    }
                }
                if(maxId>lastHistoryId)lastHistoryId=maxId;
                emit historyChanged(historyItems);
            }
        }
        else success=false;
		break;//money/wallet/history
	default: break;
	}

    static int authErrorCount=0;
    if(reqType>=200 && reqType<300)
    {
        if(!success)
        {
            authErrorCount++;
            if(authErrorCount>2)
            {
                QString authErrorString=getMidData("data\": \"","\"",&data);
                if(debugLevel)logThread->writeLog("API error: "+authErrorString.toLatin1()+" ReqType: "+QByteArray::number(reqType),2);

                if(authErrorString=="auth_error")authErrorString=julyTr("TRUNAUTHORIZED","Invalid API key.");
                else if(authErrorString=="nonce_error")authErrorString=julyTr("THIS_PROFILE_ALREADY_USED","Invalid nonce parameter.");
                if(!authErrorString.isEmpty())emit showErrorMessage(authErrorString);
            }
        }
        else authErrorCount=0;
    }

	static int errorCount=0;
	if(!success)
	{
        QString errorString;
        errorString=getMidData("{\"status\": \"error\", \"data\": \"","\"",&data);

        errorCount++;
		if(errorCount<3)return;
		if(debugLevel)logThread->writeLog("API error: "+errorString.toLatin1()+" ReqType:"+QByteArray::number(reqType),2);
		if(errorString.isEmpty())return;
		if(errorString==QLatin1String("no orders"))return;
		if(reqType<300)emit showErrorMessage("I:>"+errorString);
	}
	else errorCount=0;
}
Exemplo n.º 2
0
	tickerOnly=tickOnly;
	if(!tickerOnly)
	{
        connect(mainClass,SIGNAL(apiBuy(QString, double, double)),this,SLOT(buy(QString, double, double)));
        connect(mainClass,SIGNAL(apiSell(QString, double, double)),this,SLOT(sell(QString, double, double)));
        connect(mainClass,SIGNAL(cancelOrderByOid(QString, QByteArray)),this,SLOT(cancelOrder(QString, QByteArray)));
        connect(mainClass,SIGNAL(getHistory(bool)),this,SLOT(getHistory(bool)));

        connect(this,SIGNAL(orderBookChanged(QString, QList<OrderItem> *)),mainClass,SLOT(orderBookChanged(QString, QList<OrderItem> *)));
		connect(this,SIGNAL(historyChanged(QList<HistoryItem>*)),mainClass,SLOT(historyChanged(QList<HistoryItem>*)));
        connect(this,SIGNAL(orderCanceled(QString, QByteArray)),mainClass,SLOT(orderCanceled(QString, QByteArray)));
		connect(this,SIGNAL(ordersIsEmpty()),mainClass,SLOT(ordersIsEmpty()));
	}

	connect(this,SIGNAL(depthRequested()),mainClass,SLOT(depthRequested()));
	connect(this,SIGNAL(depthRequestReceived()),mainClass,SLOT(depthRequestReceived()));
    connect(this,SIGNAL(depthSubmitOrders(QString, QList<DepthItem> *, QList<DepthItem> *)),mainClass,SLOT(depthSubmitOrders(QString, QList<DepthItem> *, QList<DepthItem> *)));
    connect(this,SIGNAL(depthFirstOrder(QString, double,double,bool)),mainClass,SLOT(depthFirstOrder(QString, double,double,bool)));
	connect(this,SIGNAL(showErrorMessage(QString)),mainClass,SLOT(showErrorMessage(QString)));

    connect(this,SIGNAL(availableAmountChanged(QString, double)),mainClass,SLOT(availableAmountChanged(QString, double)));
	connect(mainClass,SIGNAL(clearValues()),this,SLOT(clearValues()));
	connect(mainClass,SIGNAL(reloadDepth()),this,SLOT(reloadDepth()));

    connect(this,SIGNAL(accVolumeChanged(double)),mainClass->ui.accountVolume,SLOT(setValue(double)));
    connect(this,SIGNAL(accFeeChanged(QString, double)),mainClass,SLOT(accFeeChanged(QString,double)));
    connect(this,SIGNAL(accBtcBalanceChanged(QString, double)),mainClass,SLOT(accBtcBalanceChanged(QString, double)));
    connect(this,SIGNAL(accUsdBalanceChanged(QString, double)),mainClass,SLOT(accUsdBalanceChanged(QString, double)));

    connect(this,SIGNAL(loginChanged(QString)),mainClass,SLOT(loginChanged(QString)));
void Exchange_BitMarket::dataReceivedAuth(QByteArray data, int reqType)
{
    if(debugLevel)logThread->writeLog("RCV: "+data);
    if(data.size()&&data.at(0)==QLatin1Char('<'))return;

    bool success=true;
    QString errorString="";

	switch(reqType)
	{
	case 103: //ticker
        if(data.startsWith("{\"ask\":"))
        {
            QByteArray tickerHigh=getMidData("\"high\":",",\"",&data);
			if(!tickerHigh.isEmpty())
			{
                double newTickerHigh=tickerHigh.toDouble();
                if(newTickerHigh!=lastTickerHigh)
                    IndicatorEngine::setValue(baseValues.exchangeName,baseValues.currentPair.symbol,"High",newTickerHigh);
				lastTickerHigh=newTickerHigh;
			}

			QByteArray tickerLow=getMidData("\"low\":",",\"",&data);
			if(!tickerLow.isEmpty())
			{
                double newTickerLow=tickerLow.toDouble();
                if(newTickerLow!=lastTickerLow)
                    IndicatorEngine::setValue(baseValues.exchangeName,baseValues.currentPair.symbol,"Low",newTickerLow);
				lastTickerLow=newTickerLow;
			}

            QByteArray tickerSell=getMidData("\"bid\":",",\"",&data);
			if(!tickerSell.isEmpty())
			{
                double newTickerSell=tickerSell.toDouble();
                if(newTickerSell!=lastTickerSell)
                    IndicatorEngine::setValue(baseValues.exchangeName,baseValues.currentPair.symbol,"Sell",newTickerSell);
				lastTickerSell=newTickerSell;
			}

            QByteArray tickerBuy=getMidData("\"ask\":",",\"",&data);
			if(!tickerBuy.isEmpty())
			{
                double newTickerBuy=tickerBuy.toDouble();
                if(newTickerBuy!=lastTickerBuy)
                    IndicatorEngine::setValue(baseValues.exchangeName,baseValues.currentPair.symbol,"Buy",newTickerBuy);
				lastTickerBuy=newTickerBuy;
			}

            QByteArray tickerVolume=getMidData("\"volume\":","}",&data);
			if(!tickerVolume.isEmpty())
			{
                double newTickerVolume=tickerVolume.toDouble();
                if(newTickerVolume!=lastTickerVolume)
                    IndicatorEngine::setValue(baseValues.exchangeName,baseValues.currentPair.symbol,"Volume",newTickerVolume);
				lastTickerVolume=newTickerVolume;
			}

            QByteArray tickerLast=getMidData("\"last\":",",\"",&data);
            if(!tickerLast.isEmpty())
            {
                double newTickerLast=tickerLast.toDouble();
                if(newTickerLast!=lastTickerLast)
                    IndicatorEngine::setValue(baseValues.exchangeName,baseValues.currentPair.symbol,"Last",newTickerLast);
                lastTickerLast=newTickerLast;
            }

			if(isFirstTicker)
			{
				emit firstTicker();
				isFirstTicker=false;
			}
		}
        else {
            success=false;
            errorString+="Invalid ticker data. ";
        }
		break;//ticker
    case 109: //trades
        if(data.startsWith("[{\"amount\":"))
		{
			QStringList tradeList=QString(data).split("},{");
			QList<TradesItem> *newTradesItems=new QList<TradesItem>;

            quint32 currentTid=0;
			for(int n=tradeList.count()-1;n>=0;n--)
			{
				QByteArray tradeData=tradeList.at(n).toLatin1()+"}";
				TradesItem newItem;

                newItem.date=getMidData("\"date\":",",\"",&tradeData).toUInt();
                currentTid=getMidData("\"tid\":",",\"",&tradeData).toUInt();
                if(lastFetchTid<0&&newItem.date<-lastFetchTid)continue;
                if(currentTid<1000||lastFetchTid>=currentTid)continue;
                lastFetchTid=currentTid;
                newItem.price=getMidData("\"price\":",",\"",&tradeData).toDouble();
                newItem.amount=getMidData("\"amount\":",",\"",&tradeData).toDouble();
                newItem.orderType=getMidData("\"type\":\"","\"",&tradeData)=="ask"?1:-1;
                newItem.symbol=baseValues.currentPair.symbol;

				if(newItem.isValid())(*newTradesItems)<<newItem;
				else if(debugLevel)logThread->writeLog("Invalid trades fetch data line:"+tradeData,2);

                if(n==0&&lastTickerDate<newItem.date)
                {
                    lastTickerDate=newItem.date;
                    IndicatorEngine::setValue(baseValues.exchangeName,baseValues.currentPair.symbol,"Last",newItem.price);
                }
            }
            if(newTradesItems->count())emit addLastTrades(baseValues.currentPair.symbol,newTradesItems);
			else delete newTradesItems;
            if(currentTid>1000)lastTradesTid=QByteArray::number(currentTid);
		}
        else if(data!="[]"){
            success=false;
            errorString+="Invalid trades data. ";
        }
		break;//trades
	case 111: //depth
        if(data.startsWith("{\"asks\":[["))
		{
			emit depthRequestReceived();

			if(lastDepthData!=data)
			{
				lastDepthData=data;
				depthAsks=new QList<DepthItem>;
				depthBids=new QList<DepthItem>;

                QMap<double,double> currentAsksMap;
				QStringList asksList=QString(getMidData("asks\":[[","]]",&data)).split("],[");
                double groupedPrice=0.0;
                double groupedVolume=0.0;
				int rowCounter=0;

				for(int n=0;n<asksList.count();n++)
				{
					if(baseValues.depthCountLimit&&rowCounter>=baseValues.depthCountLimit)break;
					QStringList currentPair=asksList.at(n).split(",");
					if(currentPair.count()!=2)continue;
                    double priceDouble=currentPair.first().toDouble();
                    double amount=currentPair.last().toDouble();

					if(baseValues.groupPriceValue>0.0)
					{
						if(n==0)
						{
                            emit depthFirstOrder(baseValues.currentPair.symbol,priceDouble,amount,true);
							groupedPrice=baseValues.groupPriceValue*(int)(priceDouble/baseValues.groupPriceValue);
							groupedVolume=amount;
						}
						else
						{
							bool matchCurrentGroup=priceDouble<groupedPrice+baseValues.groupPriceValue;
							if(matchCurrentGroup)groupedVolume+=amount;
							if(!matchCurrentGroup||n==asksList.count()-1)
							{
                                depthSubmitOrder(baseValues.currentPair.symbol,
                                                 &currentAsksMap,groupedPrice+baseValues.groupPriceValue,groupedVolume,true);
								rowCounter++;
								groupedVolume=amount;
								groupedPrice+=baseValues.groupPriceValue;
							}
						}
					}
					else
					{
                        depthSubmitOrder(baseValues.currentPair.symbol,
                                         &currentAsksMap,priceDouble,amount,true);
						rowCounter++;
					}
				}
                QList<double> currentAsksList=lastDepthAsksMap.keys();
				for(int n=0;n<currentAsksList.count();n++)
                    if(currentAsksMap.value(currentAsksList.at(n),0)==0)depthUpdateOrder(baseValues.currentPair.symbol,
                                                                                         currentAsksList.at(n),0.0,true);
				lastDepthAsksMap=currentAsksMap;

                QMap<double,double> currentBidsMap;
				QStringList bidsList=QString(getMidData("bids\":[[","]]",&data)).split("],[");
				groupedPrice=0.0;
				groupedVolume=0.0;
				rowCounter=0;

				for(int n=0;n<bidsList.count();n++)
				{
					if(baseValues.depthCountLimit&&rowCounter>=baseValues.depthCountLimit)break;
					QStringList currentPair=bidsList.at(n).split(",");
					if(currentPair.count()!=2)continue;
                    double priceDouble=currentPair.first().toDouble();
                    double amount=currentPair.last().toDouble();
					if(baseValues.groupPriceValue>0.0)
					{
						if(n==0)
						{
                            emit depthFirstOrder(baseValues.currentPair.symbol,priceDouble,amount,false);
							groupedPrice=baseValues.groupPriceValue*(int)(priceDouble/baseValues.groupPriceValue);
							groupedVolume=amount;
						}
						else
						{
							bool matchCurrentGroup=priceDouble>groupedPrice-baseValues.groupPriceValue;
							if(matchCurrentGroup)groupedVolume+=amount;
							if(!matchCurrentGroup||n==asksList.count()-1)
							{
                                depthSubmitOrder(baseValues.currentPair.symbol,
                                                 &currentBidsMap,groupedPrice-baseValues.groupPriceValue,groupedVolume,false);
								rowCounter++;
								groupedVolume=amount;
								groupedPrice-=baseValues.groupPriceValue;
							}
						}
					}
					else
					{
                        depthSubmitOrder(baseValues.currentPair.symbol,
                                         &currentBidsMap,priceDouble,amount,false);
						rowCounter++;
					}
				}
                QList<double> currentBidsList=lastDepthBidsMap.keys();
				for(int n=0;n<currentBidsList.count();n++)
                    if(currentBidsMap.value(currentBidsList.at(n),0)==0)depthUpdateOrder(baseValues.currentPair.symbol,
                                                                                         currentBidsList.at(n),0.0,false);
				lastDepthBidsMap=currentBidsMap;

                emit depthSubmitOrders(baseValues.currentPair.symbol,depthAsks, depthBids);
				depthAsks=0;
				depthBids=0;
			}
		}
        else {
            success=false;
            errorString+="Invalid depth data. ";
            if(debugLevel)logThread->writeLog("Invalid depth data:"+data,2);
        }
		break;
	case 202: //info
        if(data.startsWith("{\"success\":true,\"data\":{\"balances\":{\"available\":"))
        {
            QByteArray fundsData=getMidData("available\":{","}",&data)+",";
            QByteArray btcBalance=getMidData("\""+baseValues.currentPair.currAStr+"\":",",",&fundsData);
			if(!btcBalance.isEmpty())
            {
                double newBtcBalance=btcBalance.toDouble();
                if(lastBtcBalance!=newBtcBalance)emit accBtcBalanceChanged(baseValues.currentPair.symbol,newBtcBalance);
				lastBtcBalance=newBtcBalance;
			}

            QByteArray usdBalance=getMidData("\""+baseValues.currentPair.currBStr+"\":",",",&fundsData);
			if(!usdBalance.isEmpty())
			{
                double newUsdBalance=usdBalance.toDouble();
                if(newUsdBalance!=lastUsdBalance)emit accUsdBalanceChanged(baseValues.currentPair.symbol,newUsdBalance);
				lastUsdBalance=newUsdBalance;
			}
		}
        else {
            success=false;
            errorString+="Invalid info data. ";
        }
		break;//info
	case 204://orders
        if(data.startsWith("{\"success\":true,\"data\":{\"buy\":["))
		{
          if(lastOrders!=data){
            lastOrders=data;
            if(data.startsWith("{\"success\":true,\"data\":{\"buy\":[],\"sell\":[]}"))
            {
				emit ordersIsEmpty();
				break;
			}

            QByteArray dataBuy=getMidData("\"buy\":[{","}],",&data)+"},{"+getMidData("\"sell\":[{","}]",&data);
            QStringList ordersList=QString(dataBuy).split("},{");
            if(ordersList.count()==0)return;
            QList<OrderItem> *orders=new QList<OrderItem>;

			for(int n=0;n<ordersList.count();n++)
			{
				OrderItem currentOrder;
                QByteArray currentOrderData=ordersList.at(n).toLatin1()+"}";

                currentOrder.oid=getMidData("\"id\":",",",&currentOrderData);
                currentOrder.date=getMidData("\"time\":","}",&currentOrderData).toUInt();
                currentOrder.type=getMidData("\"type\":\"","\"",&currentOrderData)=="sell";
                currentOrder.amount=getMidData("\"amount\":",",",&currentOrderData).toDouble();
                currentOrder.price=getMidData("\"rate\":",",",&currentOrderData).toDouble();
                currentOrder.symbol=getMidData("\"market\":\"","\"",&currentOrderData);
                currentOrder.status=1;
				if(currentOrder.isValid())(*orders)<<currentOrder;
			}
            emit orderBookChanged(baseValues.currentPair.symbol,orders);
          }
		}
        else {
            success=false;
            errorString+="Invalid orders data. ";
        }
		break;//orders
	case 305: //order/cancel
		{
            if(!cancelingOrderIDs.isEmpty())
            {
                if(data.startsWith("{\"success\":true"))emit orderCanceled(baseValues.currentPair.symbol,cancelingOrderIDs.first());
                if(debugLevel)logThread->writeLog("Order canceled:"+cancelingOrderIDs.first(),2);
                cancelingOrderIDs.removeFirst();
            }

            dataReceivedAuth(data,202);
        }
		break;//order/cancel
    case 306:
        {
            if(debugLevel)logThread->writeLog("Buy OK: "+data,2);
            if(data.startsWith("{\"error\"")){
                success=false;
                errorString+="Invalid order/buy data. ";
            }
        }
        break;//order/buy
    case 307:
        {
            if(debugLevel)logThread->writeLog("Sell OK: "+data,2);
            if(data.startsWith("{\"error\"")){
                success=false;
                errorString+="Invalid order/sell data. ";
            }
        }
        break;//order/sell
    case 208: ///history
        if(data.startsWith("{\"success\":true,\"data\":{\"total\":"))
        {
            QByteArray historyData=getMidData("\"results\":[{","}]}",&data)+"^";
            if(lastHistory!=historyData)
            {
                lastHistory=historyData;
                if(historyData=="^")break;
                QString newLog(historyData);
                QStringList dataList=newLog.split("},{");
                if(dataList.count()==0)return;

                quint32 currentId;
                quint32 maxId=0;
                QList<HistoryItem> *historyItems=new QList<HistoryItem>;
                for(int n=0;n<dataList.count();n++)
                {
                    QByteArray curLog(dataList.at(n).toLatin1());

                    currentId=getMidData("id\":",",",&curLog).toUInt();
                    if(currentId<=lastHistoryId)break;
                    if(n==0)maxId=currentId;

                    HistoryItem currentHistoryItem;
                    QByteArray logType=getMidData("type\":\"","\"",&curLog);
                    if(logType=="sell")currentHistoryItem.type=1;else if(logType=="buy")currentHistoryItem.type=2;
                    if(currentHistoryItem.type)
                    {
                        currentHistoryItem.symbol=getMidData("currencyCrypto\":\"","\"",&curLog)+getMidData("currencyFiat\":\"","\"",&curLog);
                        currentHistoryItem.dateTimeInt=getMidData("time\":",",",&curLog).toUInt();
                        currentHistoryItem.price=getMidData("rate\":",",",&curLog).toDouble();
                        currentHistoryItem.volume=getMidData("amountCrypto\":",",",&curLog).toDouble();

                        if(currentHistoryItem.isValid())(*historyItems)<<currentHistoryItem;
                    }
                }
                if(maxId>lastHistoryId)lastHistoryId=maxId;
                emit historyChanged(historyItems);
            }
        }
        else {
            success=false;
            errorString+="Invalid history data. ";
        }
		break;//money/wallet/history
	default: break;
	}

    static int errorCount=0;
	if(!success)
    {
        errorCount++;if(errorCount<2)return;
        QByteArray errorMsg=getMidData("errorMsg\":\"","\"",&data);errorString+="Error message: "+errorMsg;
		if(debugLevel)logThread->writeLog("API error: "+errorString.toLatin1()+" ReqType:"+QByteArray::number(reqType),2);
        if(errorMsg=="Invalid nonce value"||errorMsg=="")return;
        emit showErrorMessage("I:>"+errorString);
	}
    else errorCount=0;
}