Пример #1
0
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int CProcessor::OnFXIResponse(Response *resp)
{
    SLTPOrderRequest req = { 0 };
    if (resp->status == OrderSLExecuted || resp->status == OrderTPExecuted)
        if (ExtProcessor.m_orderRequests.Dequeue(resp->requestId, &req))
        {
            CharString str;
            str.Printf(FALSE, "FXI response on SL-TP order %d, price=%g", req.orderId, resp->price);
            ExtServer->LogsOut(CmdOK, PROGRAM_TITLE, str.ToArray());

            // модифицировать ордер - активировать его
            TradeRecord order = { 0 };
            if (ExtServer->OrdersGet(req.orderId, &order))
            {
                UserInfo  user = {0};
                user.login = ExtProcessor.m_manager;
                COPY_STR(user.name, "Virtual Dealer");
                COPY_STR(user.ip,   "VirtualDealer");
                order.close_price = resp->price;
                str.Printf(FALSE, "FXI response order detail: login=%d, volume=%d", order.login, order.volume);
                ExtServer->LogsOut(CmdOK, PROGRAM_TITLE, str.ToArray());


                UserInfo us;
                if (GetUserInfo(order.login, &us))
                {
#pragma pack(push,1)
                    TradeTransInfo tti;
                    memset(&tti, 0, sizeof(tti));
                    tti.cmd = order.cmd;
                    strcpy(tti.symbol, order.symbol);
                    tti.volume = order.volume;
                    tti.price = resp->price;
                    tti.type = TT_ORDER_MK_CLOSE;
                    tti.order = order.order;
                    if (ExtServer->OrdersClose(&tti, &us) == FALSE)
                        ExtServer->LogsOut(CmdOK, PROGRAM_TITLE, "OrdersClose failed");
                    else
                        ExtServer->LogsOut(CmdOK, PROGRAM_TITLE, "OrdersClose OK");
#pragma pack(pop)
                }
                else
                    ExtServer->LogsOut(CmdOK, PROGRAM_TITLE, "GetUserInfo failed");
            }
            return TRUE;
        }
    return FALSE;
}
Пример #2
0
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int CProcessor::ProcessStopApply(TradeRecord *trade,
                                 const ConGroup *group, const int isTP)
{
    char *groupStr = new char[50];
    strcpy(groupStr, group->group);
    if (CheckGroup(m_groups, groupStr) == FALSE)
    {
        delete []groupStr;
        return FALSE;
    }
    delete []groupStr;

    double price = 0;
    // получим текущие цены для группы и установки символа
    double    prices[2] = { 0, 0 };
    int orderSide = trade->cmd == OP_BUY ? 1 : 0;
    if (ExtServer->HistoryPricesGroup(trade->symbol, group, prices) == RET_OK)
    {
        int orderSide = trade->cmd == OP_BUY ? 0 : 1; // меняется от знака сделки
        price = prices[orderSide];
    }

    CharString strMsg;
    strMsg.Printf(FALSE, "%s (%s at %g) is applying to order %d",
                  isTP ? "TP" : "SL",
                  orderSide == 1 ? "BUY" : "SELL",
                  price,
                  trade->order);
    ExtServer->LogsOut(CmdOK, PROGRAM_TITLE, strMsg.ToArray());

    SLTPOrderRequest req = { trade->order, price };
    m_orderRequests.Enqueue(&req);

    // отправить запрос на сервер
    int requestId = m_nextStopRequestId++;
    strMsg.Printf(FALSE, "requestId=%d;type=%s;price=%g;login=%d;symbol=%s;volume=%d;",
                  trade->order,
                  isTP ? "TP" : "SL",
                  price,
                  trade->login,
                  trade->symbol,
                  trade->volume);
    m_sender->SendTo(&strMsg, m_sendHost, m_sendPort);

    return TRUE;
}
Пример #3
0
//+------------------------------------------------------------------+
//| Позиция открылась (закрылась) - уведомить FXI                    |
//+------------------------------------------------------------------+
void CProcessor::OnTradeHistoryRecord(TradeRecord *trade)
{
    CharString str;
    PendingRequest req = { 0 };
    if (extPendingRequestQueue.FindRequest(trade->login, trade->cmd, trade->symbol,
                                           trade->volume, trade->open_price, &req))
    {
        str.Printf(FALSE, "type=NOTIFY;requestId=%d;order=%d;", req.requestId, trade->order);
        m_sender->SendTo(&str, m_sendHost, m_sendPort);
        return;
    }
    str.Printf(FALSE, "Request for order=%d not found", trade->order);
    ExtServer->LogsOut(CmdOK, PROGRAM_TITLE, str.ToArray());
    str.Printf(FALSE, "Detail: login=%d, cmd=%d, symbol=%s, volume=%d, op_price=%g, state=%d",
               trade->login, trade->cmd, trade->symbol,
               trade->volume, trade->open_price, trade->state);
    ExtServer->LogsOut(CmdOK, PROGRAM_TITLE, str.ToArray());
}
Пример #4
0
DWORD WINAPI UdpListener::ThreadProc(LPVOID lpParameter)
{
    UdpListener* thisObj = (UdpListener*) lpParameter;

    char                buffer[MAXDATASIZE + 1];

    // create socket
    if ((thisObj->m_hSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET)
    {
        // Failed creating socket
        SetEvent(thisObj->m_hShutdownCompletedEvent);
        ExtLogger.Out("socket was not created: %d", WSAGetLastError());
        return -200;
    }

    sockaddr_in local_addr;
    local_addr.sin_family=AF_INET;
    local_addr.sin_addr.s_addr=INADDR_ANY;
    local_addr.sin_port=htons(thisObj->m_port);

    if (bind(thisObj->m_hSocket,(sockaddr *) &local_addr,
             sizeof(local_addr)))
    {
        closesocket(thisObj->m_hSocket);
        WSACleanup();
        SetEvent(thisObj->m_hShutdownCompletedEvent);
        ExtLogger.Out("socket was not bound: %d", WSAGetLastError());
        return -300;
    }

    while (1)
    {
#ifdef DEBUG_MESSAGE_MODE
        CharString str;
        str.Printf("Listening on port %d", thisObj->m_port);
        Logger::LogMessage(str.ToArray());
#endif

        int retVal = recv(thisObj->m_hSocket, buffer, MAXDATASIZE, 0);
        if (retVal == 0) break;
        if (retVal < 0)
        {
            int erCode = WSAGetLastError();
            if (erCode == WSAEINTR) break;
            else
            {
                CharString errStr;
                errStr.Printf("Error code is %d", erCode);
                ExtLogger.Out(CharString(errStr).ToArray());
            }
        }
        if (retVal > 0)
        {
            buffer[retVal] = 0;
            (*thisObj->m_onRecv)(buffer, retVal);
        }
    }

    // close socket
    if (thisObj->m_hSocket > 0)
        closesocket(thisObj->m_hSocket);
    SetEvent(thisObj->m_hShutdownCompletedEvent);
    return 0;
}
Пример #5
0
DWORD WINAPI UdpListener::ThreadProc(LPVOID lpParameter)
{	
	UdpListener* thisObj = (UdpListener*) lpParameter;
	CharString str;
	    
    char                buffer[MAXDATASIZE + 1];        
    
    // create socket
    if ((thisObj->m_hSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET)
    {
        // Failed creating socket
		SetEvent(thisObj->m_hShutdownCompletedEvent);		
		str.Printf(FALSE, "Socket was not created: %d", WSAGetLastError());
		ExtServer->LogsOut(CmdOK, PROGRAM_TITLE, str.ToArray());
		//ExtLogger.Out(0, APP_NAME, msg.ToArray());
		return -200;
    }	
	
	sockaddr_in local_addr;
    local_addr.sin_family=AF_INET;
    local_addr.sin_addr.s_addr=INADDR_ANY;
	local_addr.sin_port=htons(thisObj->m_port);

    if (bind(thisObj->m_hSocket,(sockaddr *) &local_addr,
        sizeof(local_addr)))
    {		
		closesocket(thisObj->m_hSocket);
		WSACleanup();
		SetEvent(thisObj->m_hShutdownCompletedEvent);
				
		str.Printf(FALSE, "Socket was not bound: %d", WSAGetLastError());		
		ExtServer->LogsOut(CmdOK, PROGRAM_TITLE, str.ToArray());
		
		return -300;
    }	
    
	str.Printf(FALSE, "Now listening port %d", thisObj->m_port);
	ExtServer->LogsOut(CmdOK, PROGRAM_TITLE, str.ToArray());

	while (1)		
	{
		int retVal = recv(thisObj->m_hSocket, buffer, MAXDATASIZE, 0);
		if (retVal == 0) break;
		if (retVal < 0)
		{
			int erCode = WSAGetLastError();			
			if (erCode == WSAEINTR) break;
			else
			{
				CharString errStr;
				errStr.Printf(FALSE, "Error while recv. Error code is %d", erCode);
				ExtServer->LogsOut(CmdOK, PROGRAM_TITLE, errStr);
			}
		}
		if (retVal > 0)
		{
			buffer[retVal] = 0;
			(*thisObj->m_onRecv)(buffer, retVal);
		}
	}

    // close socket
    if (thisObj->m_hSocket > 0)
		closesocket(thisObj->m_hSocket);        
    SetEvent(thisObj->m_hShutdownCompletedEvent);
	return 0;
}
Пример #6
0
/*
returns: FALSE - request should be deleted, TRUE - keep request
*/
int CProcessor::ProcessSingleRequest(Request *req)
{
    UserInfo   user = {0};
    ConGroup   group = {0};
    double     prices[2];
    CharString str, strMsg;
    char       strCmd[64], strType[64];

    user.login = m_manager;
    COPY_STR(user.name, "Virtual Dealer");
    COPY_STR(user.ip,   "VirtualDealer");

    ExtServer->GroupsGet(req->group, &group);
    // получим текущие цены для группы и установки символа
    if (ExtServer->HistoryPricesGroup(req->trans.symbol, &group, prices) != RET_OK)
    {
        ExtServer->RequestsReset(req->id, &user, DC_RESETED);
        str.Printf(FALSE, "ProcessSingleRequest: HistoryPricesGroup (symbol [%s],  group [%s]) failed", req->trans.symbol, req->group);
        ExtServer->LogsOut(CmdOK, PROGRAM_TITLE, str.ToArray());
        return FALSE;
    }

    // если это запрос на открытие позы...
    if (req->trans.type == TT_ORDER_IE_OPEN || req->trans.type == TT_ORDER_IE_CLOSE
            || req->trans.type == TT_ORDER_MK_OPEN || req->trans.type == TT_ORDER_MK_CLOSE)
    {
        // запрос был отправлен, ответа нет - таймаут
        if (req->sent && (GetTickCount() > req->time + m_waitForFXIReply))
        {
            str.Printf(FALSE, "Таймаут для запроса %d (нет ответа от сервера FXI)", req->id);
            ExtServer->LogsOut(CmdOK, PROGRAM_TITLE, str.ToArray());
            // !! добавить открытие сделки (отложенное)
            ExtServer->RequestsRequote(req->id, &user, prices, FALSE);
            return FALSE;
        }

        // запрос к FXI еще не был отправлен - отправить
        if (!req->sent)
        {
            ExtServer->LogsOut(CmdOK, PROGRAM_TITLE, "Отправка UDP");
            CharString reqStr;
            reqStr.Printf(FALSE, "requestId=%d;group=%s;time=%d;login=%d;", req->id, req->group, req->time, req->login);

            reqStr.Printf(TRUE, "type=%s;side=%d;order=%d;orderby=%d;price=%g;symbol=%s;volume=%d;tp=%g;sl=%g;slippage=%d;pending=%d;stopout=%d",
                          req->trans.type == TT_ORDER_IE_OPEN || req->trans.type == TT_ORDER_MK_OPEN
                          ? "OPEN" : "CLOSE",
                          req->trans.cmd == OP_BUY || req->trans.cmd == OP_BUY_LIMIT || req->trans.cmd == OP_BUY_STOP
                          ? FXI_OP_BUY : FXI_OP_SELL,
                          req->trans.order, req->trans.orderby,
                          req->trans.price, req->trans.symbol, req->trans.volume,
                          req->trans.tp, req->trans.sl, req->trans.ie_deviation, req->isPending, req->isStopout);

            FormatCommand(req->trans.cmd, strCmd);
            FormatRequestType(req->trans.type, strType);
            str.Printf(FALSE, "Отправка запроса FXI [%s] типа [%s] по цене [%g], ордер [%d]",
                       strCmd, strType, req->trans.price, req->trans.order);
            ExtServer->LogsOut(CmdOK, PROGRAM_TITLE, str.ToArray());

            m_sender->SendTo(&reqStr, m_sendHost, m_sendPort);
            req->sent = TRUE;
            ExtServer->LogsOut(CmdOK, PROGRAM_TITLE, "Отправка UDP::OK");
            return TRUE;
        }

        Response resp = { 0 };
        int requestId = req->trans.type == TT_ORDER_MK_CLOSE || req->trans.type == TT_ORDER_IE_CLOSE ?
                        req->trans.order : req->id;
        int respFound = extQueue->FindAndDequeue(requestId, &resp);

        if (!respFound) return TRUE;

        // получен ответ от FXI
        ExtServer->LogsOut(CmdOK, PROGRAM_TITLE, "Обработка ответа FXI");

        // обработан успешно
        if (resp.status == RequestCompleted)
        {
            strMsg.Printf(FALSE,
                          "Запрос (%d) подтвержден по цене (%g), сейчас цена (%g)",
                          req->id,
                          req->trans.cmd == OP_BUY ? prices[1] : prices[0],
                          resp.price);
            ExtServer->LogsOut(CmdOK, PROGRAM_TITLE, strMsg.ToArray());
            double    newPrices[2] = { resp.price, resp.price };
            req->trans.price = resp.price;

            // отложенный ордер
            if (resp.isPendingActivate)
            {
                ActivatePendingOrder(&resp);
                return FALSE;
            }

            // обработка ответа на закрытие (стопаут)
            if (resp.isStopoutReply)
            {
                ClosePositionStopout(&resp, req);
                return FALSE;
            }

            // обычный ордер
            // подтвердить запрос
            if (ExtServer->RequestsConfirm(req->id, &user, newPrices) == RET_OK)
            {
                // если запрос на открытие...
                if (req->trans.type == TT_ORDER_IE_OPEN || req->trans.type == TT_ORDER_MK_OPEN)
                    // сохранить подтвержденный запрос (потом ассоциировать его с открывшейся
                    // позицией)
                    extPendingRequestQueue.AddRequest(resp.requestId, req->login,
                                                      req->trans.cmd, req->trans.symbol, req->trans.volume, resp.price);
            }
            else
            {   // сделка открыта у брокера, но не открылась в МТ4

            }
            return FALSE;
        }
        // обработан с ошибкой
        if (resp.status == RequestFailed)
        {
            ExtServer->LogsOut(CmdOK, PROGRAM_TITLE, "Запрос не подтвержден (отрицательная квитанция)");
            ExtServer->RequestsReset(req->id, &user, DC_RESETED);
            return FALSE;
        }
        // прочие возвраты
        strMsg.Printf(FALSE, "Запрос: код ответа [%d]", resp.status);
        ExtServer->LogsOut(CmdOK, PROGRAM_TITLE, strMsg.ToArray());

        return FALSE;
    } // if (req->trans.type == TT_ORDER_IE_OPEN ...

    // запрос цены, не более
    if (req->trans.type == TT_PRICES_GET)
    {
        ExtServer->RequestsPrices(req->id, &user, prices, FALSE);
        return FALSE;
    }

    if (req->trans.type == TT_ORDER_DELETE)
    {
        ExtServer->LogsOut(CmdOK, PROGRAM_TITLE, "Удаление отложенного ордера");
        ExtServer->RequestsConfirm(req->id, &user, prices);
        ExtServer->LogsOut(CmdOK, PROGRAM_TITLE, "Отложенный ордер удален");
        return FALSE;
    }

    // остальные запросы подтверждаем
    ExtServer->RequestsConfirm(req->id, &user, prices);

    return FALSE;
}
Пример #7
0
int CProcessor::Add(const UserInfo *user, const ConGroup *group, const ConSymbol *symbol,
                    const TradeRecord *pending, TradeRecord *trade)
{
    Request *temp;
    UINT     id;
    static int uid = 1;
    CharString str;

    if (pending == NULL || trade == NULL) return(FALSE);
    // проверки - кто управляет счетом
    if (m_delay == 0 || CheckGroup(m_groups, group->group) == FALSE)
        return (TRUE);

    double    prices[2];
    // получим текущие цены для группы и установки символа
    if (ExtServer->HistoryPricesGroup(symbol->symbol, group, prices) != RET_OK)
    {
        str.Printf(FALSE, "CProcessor::Add Pending (symbol [%s], group [%s]) failed", symbol->symbol, group->group);
        ExtServer->LogsOut(CmdOK, PROGRAM_TITLE, str.ToArray());
        return FALSE;
    }

    m_sync.Lock();

    // проверить - нет ли такого запроса в списке
    Request  *reqTmp;
    if (m_requests != NULL)
    {
        int i = 0;
        for (reqTmp = m_requests; i < m_requests_total; i++, reqTmp++)
        {
            if (reqTmp->isPending)
                if (reqTmp->pendingId == pending->order)
                {
                    ExtServer->LogsOut(CmdOK, PROGRAM_TITLE, "Отложенный ордер уже в списке");
                    m_sync.Unlock();
                    return (TRUE);
                }
        }
    }

    // лог
    /*char reqCmdStr[64];
    FormatCommand(pending->cmd, reqCmdStr);
    str.Printf(FALSE, "CProcessor::Add Pending(order [%d], cmd [%s], req Id [%d])",
    	pending->order, reqCmdStr, startPendingRequestId);
    ExtServer->LogsOut(CmdOK, PROGRAM_TITLE, str.ToArray());*/


    //---- если место для запросов нет выделим
    if(m_requests == NULL)
    {
        if((m_requests = new Request[256]) == NULL)
        {
            m_sync.Unlock();
            return (FALSE);
        }
        m_requests_max = 256;
        m_requests_total = 0;
    }
    //---- посмотрим может надо перевыделить
    if (m_requests_total >= m_requests_max)
    {
        if((temp = new Request[m_requests_max + 256]) == NULL)
        {
            m_sync.Unlock();
            return(FALSE);
        }
        //---- скопируем старое
        memcpy(temp, m_requests, sizeof(Request) * m_requests_total);
        //---- удалим уже не нужное
        delete m_requests;

        m_requests = temp;
        m_requests_max += 256;
    }
    //---- вставляем запрос
    m_requests[m_requests_total].pendingId = pending->order;
    m_requests[m_requests_total].isPending = TRUE;
    m_requests[m_requests_total].id = startPendingRequestId++;
    m_requests[m_requests_total].time = GetTickCount();
    m_requests[m_requests_total].sent = FALSE;
    m_requests[m_requests_total].login = user->login;
    memcpy(&m_requests[m_requests_total].trans, pending, sizeof(TradeTransInfo));
    m_requests[m_requests_total].trans.volume = trade->volume;
    Out(CmdOK, "Pending order %d added of volume %d",
        m_requests[m_requests_total].id, trade->volume);
    COPY_STR(m_requests[m_requests_total].group, group->group);
    // поправить команду
    char origTradeCmd[32], newTradeCmd[32];
    FormatCommand(m_requests[m_requests_total].trans.cmd, origTradeCmd);

    int pendCmd = trade->cmd; //m_requests[m_requests_total].trans.cmd;
    pendCmd = (pendCmd == OP_BUY_LIMIT || pendCmd == OP_BUY_STOP) ? OP_BUY
              : (pendCmd == OP_SELL_LIMIT || pendCmd == OP_SELL_STOP) ? OP_SELL
              : pendCmd;
    m_requests[m_requests_total].trans.cmd = pendCmd;
    FormatCommand(m_requests[m_requests_total].trans.cmd, newTradeCmd);

    m_requests[m_requests_total].trans.type = TT_ORDER_MK_OPEN;
    m_requests[m_requests_total].trans.price = pendCmd == OP_BUY ? prices[1] : prices[0];
    strcpy(m_requests[m_requests_total].trans.symbol, symbol->symbol);
    m_requests[m_requests_total].trans.order = pending->order;

    str.Printf(FALSE, "Отложенный ордер %d добавлен, всего %d (%s, теперь %s)",
               pending->order, m_requests_total, origTradeCmd, newTradeCmd);
    ExtServer->LogsOut(CmdOK, PROGRAM_TITLE, str.ToArray());

    m_requests_total++;
    //---- запускаем поток
    if (m_thread == NULL)
        if ((m_thread = (HANDLE)_beginthreadex(NULL, 256000, ThreadFunction, this, 0, &id))==NULL)
        {
            m_sync.Unlock();
            return(FALSE);
        }

    m_sync.Unlock();
    return(TRUE);
}
Пример #8
0
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int CProcessor::Add(RequestInfo *request, int isStopout)
{
    Request *temp;
    UINT     id;
    Request  req = {0};
    static int uid = 1;

    if (request == NULL) return(FALSE);
    // проверки - кто управляет счетом
    if (m_delay == 0 || CheckGroup(m_groups, request->group) == FALSE)
        return (TRUE);

    // лог
    char reqTypeStr[64];
    char reqCmdStr[64];
    FormatCommand(request->trade.cmd, reqCmdStr);
    FormatRequestType(request->trade.type, reqTypeStr);
    CharString str;
    str.Printf(FALSE, "CProcessor::Add(тип [%s], cmd [%s])", reqTypeStr, reqCmdStr);
    ExtServer->LogsOut(CmdOK, PROGRAM_TITLE, str.ToArray());

    m_sync.Lock();
    //---- если место для запросов нет выделим
    if(m_requests == NULL)
    {
        if((m_requests = new Request[256]) == NULL)
        {
            m_sync.Unlock();
            return (FALSE);
        }
        m_requests_max = 256;
        m_requests_total = 0;
    }
    //---- посмотрим может надо перевыделить
    if (m_requests_total >= m_requests_max)
    {
        if((temp = new Request[m_requests_max + 256]) == NULL)
        {
            m_sync.Unlock();
            return(FALSE);
        }
        //---- скопируем старое
        memcpy(temp, m_requests, sizeof(Request) * m_requests_total);
        //---- удалим уже не нужное
        delete m_requests;

        m_requests = temp;
        m_requests_max += 256;
    }
    //---- вставляем запрос
    m_requests[m_requests_total].isStopout = isStopout;
    m_requests[m_requests_total].isPending = FALSE;
    m_requests[m_requests_total].id = request->id;
    m_requests[m_requests_total].time = GetTickCount();
    m_requests[m_requests_total].sent = FALSE;
    m_requests[m_requests_total].login = request->login;
    memcpy(&m_requests[m_requests_total].trans, &request->trade, sizeof(TradeTransInfo));
    COPY_STR(m_requests[m_requests_total].group, request->group);
    m_requests_total++;
    //---- запускаем поток
    if (m_thread == NULL)
        if ((m_thread = (HANDLE)_beginthreadex(NULL, 256000, ThreadFunction, this, 0, &id))==NULL)
        {
            m_sync.Unlock();
            return(FALSE);
        }

    m_sync.Unlock();
    return(TRUE);
}