Open Ai API integration so Chat gpt can make trades automatically

 

I am trying to get my EA working that calls on Open Ai API for chat gpt to make trades automatically based on current price and history. Maybe news too. 

But i keep getting these errors - 

Yes i know my API key should not be hardcoded but for testing purposes i have put it in. Also open ai api url is allowed in tools - options - expert advisors.


I hope someone can help. Been trying to get it working for the past couple of weeks or so... 

#include <Trade\Trade.mqh>


CTrade trade;  // Declare trade object for global use


// User-configurable settings

input double RiskPercent = 1.0;           // Risk 1% of account per trade

input double StopLossPips = 50;           // Default stop loss in pips

input double TakeProfitPips = 100;        // Default take profit in pips

input int Slippage = 2;                   // Maximum slippage in points

input int RetryAttempts = 3;              // Number of retry attempts on failure

input int RequestTimeout = 20000;         // Timeout for WebRequest (in milliseconds)


// API settings (Replace these with more secure methods of storing credentials in production)

string api_key = "sk-your-api-key-here";  // Replace with your actual API key

string api_url = "https://api.openai.com/v1/chat/completions";

string org_id = "org-your-organization-id";  // Optional: Your OpenAI organization ID


string initial_prompt = "You are a master of trading any asset.";

string messages = "[{\"role\": \"system\", \"content\": \"" + initial_prompt + "\"}]";


//+------------------------------------------------------------------+

//| Expert initialization function                                   |

//+------------------------------------------------------------------+

int OnInit()

{

   Print("EA initialized successfully.");

   return(INIT_SUCCEEDED);

}


//+------------------------------------------------------------------+

//| Expert deinitialization function                                 |

//+------------------------------------------------------------------+

void OnDeinit(const int reason)

{

   Print("EA deinitialized.");

}


//+------------------------------------------------------------------+

//| Expert tick function                                             |

//+------------------------------------------------------------------+

void OnTick()

{

    double price = iClose(_Symbol, PERIOD_CURRENT, 0); // Get the latest price

    string user_message = "The current price of " + _Symbol + " is " + DoubleToString(price, _Digits) + ". What should be my next trading move?";


    // Append user message to the conversation

    messages += ",{\"role\": \"user\", \"content\": \"" + user_message + "\"}";


    // Prepare request body for the API call

    string request_body = "{\"model\": \"gpt-3.5-turbo\", \"messages\": " + messages + "}";


    // Send the request and get the response

    string response = SendChatGPTRequest(request_body);


    if (response != "")

    {

        string reply = ExtractReplyFromResponse(response);

        messages += ",{\"role\": \"assistant\", \"content\": \"" + reply + "\"}";


        Print("ChatGPT: ", reply);


        // Process the trading decision based on the response

        ProcessTradingDecision(reply, price);

    }

    else

    {

        Print("Failed to get a valid response from ChatGPT.");

    }

}


//+------------------------------------------------------------------+

//| Function to send request to ChatGPT with retry logic and logging |

//+------------------------------------------------------------------+

string SendChatGPTRequest(string request_body)

{

    string headers = 

        "Content-Type: application/json\r\n" +

        "Authorization: Bearer " + api_key + "\r\n" +

        "OpenAI-Organization: " + org_id + "\r\n";  // Optional


    char result[4096];  // Buffer for response

    string result_headers;


    // Convert request body to a char array and ensure it's properly null-terminated

    char post_data[];

    ArrayResize(post_data, StringLen(request_body) + 1);  // Adjust size

    StringToCharArray(request_body, post_data);

    post_data[StringLen(request_body)] = '\0';  // Ensure null-termination


    int attempts = 0;

    while (attempts < RetryAttempts)

    {

        Print("Sending request to OpenAI (Attempt: ", attempts + 1, ")");

        

        int res = WebRequest("POST", api_url, headers, NULL, RequestTimeout, post_data, StringLen(request_body), result, result_headers);


        if (res == 200)  // Success

        {

            Print("Request successful.");

            return CharArrayToString(result);  // Return response as a string

        }

        else

        {

            Print("Attempt ", attempts + 1, ": Error in request. Status code: ", res, ", HTTP code: ", GetLastError(), ", Response: ", result_headers);

            attempts++;

            Sleep(1000 * attempts);  // Exponential backoff: increase delay on each attempt

        }

    }


    Print("Failed to get a valid response after ", RetryAttempts, " attempts.");

    return "";  // Return empty if all attempts fail

}


//+------------------------------------------------------------------+

//| Function to extract reply from ChatGPT response                  |

//+------------------------------------------------------------------+

string ExtractReplyFromResponse(string response)

{

    // Simplified extraction logic (parsing JSON manually)

    int start = StringFind(response, "\"content\":\"") + 11;

    int end = StringFind(response, "\"}", start);

    if (start > 0 && end > 0 && end > start)

    {

        return StringSubstr(response, start, end - start);

    }

    else

    {

        Print("Failed to extract reply from response.");

        return "";

    }

}


//+------------------------------------------------------------------+

//| Function to process ChatGPT trading decision                     |

//+------------------------------------------------------------------+

void ProcessTradingDecision(string reply, double price)

{

    double stop_loss, take_profit;

    double account_balance = AccountInfoDouble(ACCOUNT_BALANCE);

    double risk_amount = account_balance * (RiskPercent / 100.0);

    double lot_size = CalculateLotSize(risk_amount, StopLossPips);


    if (StringFind(reply, "buy") >= 0)

    {

        stop_loss = price - StopLossPips * _Point;

        take_profit = price + TakeProfitPips * _Point;

        ExecuteTrade(ORDER_TYPE_BUY, lot_size, stop_loss, take_profit);

    }

    else if (StringFind(reply, "sell") >= 0)

    {

        stop_loss = price + StopLossPips * _Point;

        take_profit = price - TakeProfitPips * _Point;

        ExecuteTrade(ORDER_TYPE_SELL, lot_size, stop_loss, take_profit);

    }

}


//+------------------------------------------------------------------+

//| Function to calculate lot size based on risk management          |

//+------------------------------------------------------------------+

double CalculateLotSize(double risk_amount, double stop_loss_pips)

{

    double pip_value = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);

    double lot_size = risk_amount / (stop_loss_pips * pip_value);

    return NormalizeDouble(lot_size, 2);

}


//+------------------------------------------------------------------+

//| Function to execute a trade with error handling                  |

//+------------------------------------------------------------------+

void ExecuteTrade(int order_type, double lot_size, double stop_loss, double take_profit)

{

    MqlTradeRequest request;

    MqlTradeResult result;


    for (int i = 0; i < RetryAttempts; i++)

    {

        ZeroMemory(request);

        request.action = TRADE_ACTION_DEAL;

        request.symbol = _Symbol;

        request.volume = lot_size;

        request.type = order_type;

        request.price = (order_type == ORDER_TYPE_BUY) ? SymbolInfoDouble(_Symbol, SYMBOL_ASK) : SymbolInfoDouble(_Symbol, SYMBOL_BID);

        request.sl = stop_loss;

        request.tp = take_profit;

        request.deviation = Slippage;

        request.magic = 123456;

        request.comment = (order_type == ORDER_TYPE_BUY) ? "Buy order from ChatGPT" : "Sell order from ChatGPT";


        if (OrderSend(request, result) && result.retcode == TRADE_RETCODE_DONE)

        {

            Print("Order placed successfully, Ticket: ", result.order);

            return;

        }

        else

        {

            Print("Error placing order, attempt ", i + 1, ": ", GetLastError());

            Sleep(1000);  // Pause before retrying

        }

    }


    Print("Failed to place order after ", RetryAttempts, " attempts.");

}
 
Have you tried to allow WebRequest to access this domain:

https://api.openai.com

WebRequest access
 
Soewono Effendi #:
Have you tried to allow WebRequest to access this domain:

https://api.openai.com

Yes 

 
After closer look at the error code returned, please modify your code as following:

string SendChatGPTRequest(string request_body)
{

    string headers = 
        "Content-Type: application/json\r\n" +
        "Authorization: Bearer " + api_key + "\r\n" +
        "OpenAI-Organization: " + org_id + "\r\n";  // Optional

    char result[];  // Buffer for response
    string result_headers;

    // Convert request body to a char array and ensure it's properly null-terminated
    char post_data[];
    ArrayResize(post_data, StringLen(request_body) + 1);  // Adjust size
    StringToCharArray(request_body, post_data);
    post_data[StringLen(request_body)] = '\0';  // Ensure null-termination
    int attempts = 0;
    while (attempts < RetryAttempts)
    {
        Print("Sending request to OpenAI (Attempt: ", attempts + 1, ")");
        int res = WebRequest("POST", api_url, headers, RequestTimeout, post_data, result, result_headers);
        if (res == 200)  // Success
        {
            Print("Request successful.");
            return CharArrayToString(result);  // Return response as a string
        }
        else
        {
            Print("Attempt ", attempts + 1, ": Error in request. Status code: ", res, ", HTTP code: ", GetLastError(), ", Response: ", result_headers);
            attempts++;
            Sleep(1000 * attempts);  // Exponential backoff: increase delay on each attempt
        }
    }

    Print("Failed to get a valid response after ", RetryAttempts, " attempts.");
    return "";  // Return empty if all attempts fail
}

Good luck.
 
Soewono Effendi #:
After closer look at the error code returned, please modify your code as following:


Good luck.

Getting different errors now... 

I know 401 is unauthorised in terms of a api request.


I can send you my API key in a private message so you can test if you dont mind ? 


FF 0 15:10:22.010 AI Beast (EURUSD,H1) Sending request to OpenAI (Attempt: 1)

PQ 0 15:10:22.158 AI Beast (EURUSD,H1) Attempt 1: Error in request. Status code: 401, HTTP code: 0, Response: Date: Thu, 05 Sep 2024 14:10:22 GMT

EN 0 15:10:22.158 AI Beast (EURUSD,H1) Content-Type: application/json; charset=utf-8

MH 0 15:10:22.158 AI Beast (EURUSD,H1) Content-Length: 218

IP 0 15:10:22.158 AI Beast (EURUSD,H1) Connection: keep-alive

JE 0 15:10:22.158 AI Beast (EURUSD,H1) vary: Origin

OR 0 15:10:22.158 AI Beast (EURUSD,H1) x-request-id: req_79abc03967a6c03b0d764920bc472244

MN 0 15:10:22.158 AI Beast (EURUSD,H1) strict-transport-security: max-age=15552000; includeSubDomains; preload

JE 0 15:10:22.158 AI Beast (EURUSD,H1) CF-Cache-Status: DYNAMIC

CM 0 15:10:22.158 AI Beast (EURUSD,H1) X-Content-Type-Options: nosniff

LD 0 15:10:22.158 AI Beast (EURUSD,H1) Server: cloudflare

IS 0 15:10:22.158 AI Beast (EURUSD,H1) CF-RAY: 8be6cd66af9071f8-LHR

OJ 0 15:10:22.158 AI Beast (EURUSD,H1) alt-svc: h3=":443"; ma=86400

DH 0 15:10:22.158 AI Beast (EURUSD,H1)

HK 0 15:10:23.023 AI Beast (EURUSD,H1) Sending request to OpenAI (Attempt: 2)

PO 0 15:10:23.023 AI Beast (EURUSD,H1) Attempt 2: Error in request. Status code: 1003, HTTP code: 5203, Response: Date: Thu, 05 Sep 2024 14:10:22 GMT

MH 0 15:10:23.023 AI Beast (EURUSD,H1) Content-Type: application/json; charset=utf-8

MS 0 15:10:23.023 AI Beast (EURUSD,H1) Content-Length: 218

IJ 0 15:10:23.023 AI Beast (EURUSD,H1) Connection: keep-alive

RO 0 15:10:23.023 AI Beast (EURUSD,H1) vary: Origin

OE 0 15:10:23.023 AI Beast (EURUSD,H1) x-request-id: req_79abc03967a6c03b0d764920bc472244

EP 0 15:10:23.023 AI Beast (EURUSD,H1) strict-transport-security: max-age=15552000; includeSubDomains; preload

RO 0 15:10:23.023 AI Beast (EURUSD,H1) CF-Cache-Status: DYNAMIC

CG 0 15:10:23.023 AI Beast (EURUSD,H1) X-Content-Type-Options: nosniff

LN 0 15:10:23.023 AI Beast (EURUSD,H1) Server: cloudflare

QI 0 15:10:23.023 AI Beast (EURUSD,H1) CF-RAY: 8be6cd66af9071f8-LHR

OP 0 15:10:23.023 AI Beast (EURUSD,H1) alt-svc: h3=":443"; ma=86400