본문 바로가기
자동매매 이야기

프로그램에 대한 지식이 없어도 chat gpt를 이용해서 자동매매 개발하기

by 나도쫌씨 2023. 12. 29.

오늘은 개발에 대한 지식이 제로일지라도 chat gpt를 활용해서 

자동매매 만드는 방벙에 대한 힌트를 주고 싶다.

 

사실 힌트를 주면 그 다음부터는 스스로 알아서 원하는 자동화 전략을 모두 구현할 수 있을 것이다.

오늘의 자동매매 개발 힌트를 이해하려면

 

Meta4 를 설치하고 데모계좌를 오픈해서 최소한 meta4 트레이딩 시스템이 어떻게 돌아가는지는 알아야 한다.

이 부분은 요즘 유튜브나 기타 방법으로 해결이 가능할거라 생각되니 본격적으로

chat gpt를 어떻게 활용해서 자동매매 EA 전략을 개발할 수 있는지 설명하도록 하겠다.

 

만약 설치와 데모계좌 오픈을 아직도 하지 않았다면 아래의 믿을만한 브로커를 통해 데모계좌부터 오픈하시길~

Land Prime 브로커 계좌개설하기

 

데모 계좌 개설하는건 돈이 안들기 때문에 마음껏 하셔도 됩니다.

그렇다면 Mt4 프로그램이 컴퓨터에 설치되어 있다는 가정하에 chat gpt를 이용해서 어떻게 자동매매 전략을 만들 수 있는지 시작겠습니다.

 

우선 저는 chat gpt에 가입되어 있는 상태이고 매달 20달러의 이용료를 지불하고 있습니다.

 

아무래도 GPT-4 로 진행하는게 가장 최신의 프로그램 로직을 반영하여 도움을 받을 수 있는것 같습니다.

 

그렇다면 그리드 시스템을 이용해서 자동매매 전략을 만들어 보는 과정을 설명하겠습니다.

 

Setp1. 우선 어떤 전략을 사용해서 매매가 진행되게 할 것인지에 대한 요약이 필요합니다

-개발언어 : MetaEditor4

- 처음 거래가 시작되면 진입되어 있는 가격을 기준으로 100포인트씩 간격을 두고 buy limit 또는 sell limit를 20개 오픈해줘

- 거래 오픈할때에는 처음 진입되어 있는 lot와 같은 수량으로 진입해줘

- 만약에 거래중인 전체의 수익이 100달러 이상이 되면 모든 거래를 청산하고 체결되지 않은 거래도 모두 삭제해줘

 

이 정도의 설명이면 chat gpt가 알아들을 수 있을까요?

일단 이 상태로  chat gpt에 요청을 해보고 결과가 잘 반영되는지 확인해 보자

 

 

이렇게 질문을 했더니 아래와 같이 답변을 해주고 실제로 프로그램을 짜줬습니다

//+------------------------------------------------------------------+
//|                                             CustomEA.mq4         |
//|                        Copyright 2023, MetaQuotes Software Corp. |
//|                                       http://www.metaquotes.net |
//+------------------------------------------------------------------+
#property strict

// Input parameters
input double TakeProfit = 100.0; // Take profit level in dollars

// Global variables
double initialLotSize;
double initialPrice;
int ticket;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   // Get the lot size and price of the first trade
   if(OrdersTotal() > 0)
     {
      OrderSelect(0, SELECT_BY_POS);
      initialLotSize = OrderLots();
      initialPrice = OrderOpenPrice();
     }

   // Set up pending orders
   for(int i = 1; i <= 20; i++)
     {
      double priceOffset = i * 100 * Point;
      ticket = OrderSend(Symbol(), OP_BUYLIMIT, initialLotSize, initialPrice - priceOffset, 3, 0, 0, "", 0, 0, clrNONE);
      ticket = OrderSend(Symbol(), OP_SELLLIMIT, initialLotSize, initialPrice + priceOffset, 3, 0, 0, "", 0, 0, clrNONE);
     }

   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   // Close all trades and delete pending orders on deinitialization
   for(int i = OrdersTotal() - 1; i >= 0; i--)
     {
      if(OrderSelect(i, SELECT_BY_POS) && OrderSymbol() == Symbol())
        {
         if(OrderType() <= OP_SELL) // Close open trades
           {
            OrderClose(OrderTicket(), OrderLots(), MarketInfo(Symbol(), MODE_BID), 3, clrNONE);
           }
         else // Delete pending orders
           {
            OrderDelete(OrderTicket());
           }
        }
     }
  }

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   // Check the total profit and close all if it exceeds $100
   double totalProfit = 0.0;
   for(int i = 0; i < OrdersTotal(); i++)
     {
      if(OrderSelect(i, SELECT_BY_POS) && OrderSymbol() == Symbol())
        {
         totalProfit += OrderProfit();
        }
     }

   if(totalProfit >= TakeProfit)
     {
      OnDeinit(0); // Close and delete all orders
     }
  }
//+------------------------------------------------------------------+

그리고 프로그램 소스 하단에 아래와 같이 친절하게 코멘트도 알려줍니다.ㅎ

 

Step2. 프로그램 소스를 복사해서 MetaEditor에 적용하고 제대로 작동하는지 테스트해 봅시다.

일단 MetaEditor를 실행하고 아래의 이미지들 보면서 따라하시면 됩니다. 차트에서 아래 그림처럼 MetaQuotes 언어 편집기라는것을 클릭합니다.

 

[새문서]를 클릭하고 [시스템 트레이딩(템플릿)]을 선택합니다.

 

전략의 이름을 입력하고 다음으로 이동합니다.

다음~

마침~~~

 

에디터 화면에서 chat gpt가 만들어준 소스를 그대로 복사하여 붙여넣기 합니다.

(기존 소스는 모두 삭제하고 붙여넣기 합니다)

 

붙여넣기 했다면 바로 저장하고 컴파일 버튼을 클릭합니다.

 

 

컴파일 하고 나면 화면 하단에 아래와 같이 경고 메시지들이 표시될 수 있습니다. 

앞으로 이런 일들이 자주 발생할 수 있습니다. 당황하지 말고 복사해서 chat gpt에 수정요청 하면 됩니다.

 

아래 그림처럼 오류 부분을 선택해서 복사하세요.

 

chat gpt에 그대로 붙여넣기하고 전송합니다.

 

아래 그림처럼 원인과 해결방법으로 수정된 코드를 다시 만들어 줄 것입니다.

 

 

MQL4에서 `OrderSelect`, `OrderClose`, 및 `OrderDelete` 함수의 반환 값을 확인하는 것은 매우 중요합니다. 이는 함수가 성공적으로 실행되었는지 여부를 확인하기 위함입니다. 만약 이러한 함수들이 실패하면, 이는 주문이 존재하지 않거나 네트워크 문제, 또는 다른 이유로 인해 주문을 처리할 수 없음을 의미할 수 있습니다.

아래 코드는 이전에 제공한 스크립트를 수정하여 `OrderSelect`, `OrderClose`, 및 `OrderDelete` 함수의 반환 값을 확인하는 방법을 보여줍니다.

```mql4
// ...

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   // Check if there are open orders and select the first one
   if(OrdersTotal() > 0 && OrderSelect(0, SELECT_BY_POS))
     {
      initialLotSize = OrderLots();
      initialPrice = OrderOpenPrice();
     }
   else
     {
      Print("No open orders to initialize values.");
      return(INIT_FAILED);
     }

   // Set up pending orders
   for(int i = 1; i <= 20; i++)
     {
      double priceOffset = i * 100 * Point;
      if(OrderSend(Symbol(), OP_BUYLIMIT, initialLotSize, initialPrice - priceOffset, 3, 0, 0, "", 0, 0, clrNONE) < 0)
        {
         Print("Error in setting Buy Limit: ", GetLastError());
        }
      if(OrderSend(Symbol(), OP_SELLLIMIT, initialLotSize, initialPrice + priceOffset, 3, 0, 0, "", 0, 0, clrNONE) < 0)
        {
         Print("Error in setting Sell Limit: ", GetLastError());
        }
     }

   return(INIT_SUCCEEDED);
  }

// ...

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   // Close all trades and delete pending orders on deinitialization
   for(int i = OrdersTotal() - 1; i >= 0; i--)
     {
      if(OrderSelect(i, SELECT_BY_POS) && OrderSymbol() == Symbol())
        {
         if(OrderType() <= OP_SELL) // Close open trades
           {
            if(!OrderClose(OrderTicket(), OrderLots(), MarketInfo(Symbol(), MODE_BID), 3, clrNONE))
              {
               Print("Error in closing order: ", GetLastError());
              }
           }
         else // Delete pending orders
           {
            if(!OrderDelete(OrderTicket()))
              {
               Print("Error in deleting order: ", GetLastError());
              }
           }
        }
     }
  }

// ...
```

이 수정된 코드는 각 주요 함수의 반환 값을 확인하고, 오류가 발생할 경우 오류 메시지를 출력합니다. 이는 스크립트의 안정성과 신뢰성을 향상시키는 데 도움이 됩니다.

 

그런데 이렇게 결과물을 받으면 대부분 수정되어야 할 부분만 보여주는 경우가 많이 발생합니다.

chat gpt에 아래와 같이 정중하게 다시 요청하면 전체 수정 반영된 소스를 친절하게 알려줄 것입니다.

 

 

굉장히 친절하지 않습니까? ㅎㅎ 아래와 같은 최종 소스를 chat gpt가 만들어 주었습니다. 즉시 metaEditor 에 적용하고 결과를 봅시다.

//+------------------------------------------------------------------+
//|                                             CustomEA.mq4         |
//|                        Copyright 2023, MetaQuotes Software Corp. |
//|                                       http://www.metaquotes.net |
//+------------------------------------------------------------------+
#property strict

// Input parameters
input double TakeProfit = 100.0; // Take profit level in dollars

// Global variables
double initialLotSize;
double initialPrice;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   // Check if there are open orders and select the first one
   if(OrdersTotal() > 0 && OrderSelect(0, SELECT_BY_POS))
     {
      initialLotSize = OrderLots();
      initialPrice = OrderOpenPrice();
     }
   else
     {
      Print("No open orders to initialize values.");
      return(INIT_FAILED);
     }

   // Set up pending orders
   for(int i = 1; i <= 20; i++)
     {
      double priceOffset = i * 100 * Point;
      if(OrderSend(Symbol(), OP_BUYLIMIT, initialLotSize, initialPrice - priceOffset, 3, 0, 0, "", 0, 0, clrNONE) < 0)
        {
         Print("Error in setting Buy Limit: ", GetLastError());
        }
      if(OrderSend(Symbol(), OP_SELLLIMIT, initialLotSize, initialPrice + priceOffset, 3, 0, 0, "", 0, 0, clrNONE) < 0)
        {
         Print("Error in setting Sell Limit: ", GetLastError());
        }
     }

   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   // Close all trades and delete pending orders on deinitialization
   for(int i = OrdersTotal() - 1; i >= 0; i--)
     {
      if(OrderSelect(i, SELECT_BY_POS) && OrderSymbol() == Symbol())
        {
         if(OrderType() <= OP_SELL) // Close open trades
           {
            if(!OrderClose(OrderTicket(), OrderLots(), MarketInfo(Symbol(), MODE_BID), 3, clrNONE))
              {
               Print("Error in closing order: ", GetLastError());
              }
           }
         else // Delete pending orders
           {
            if(!OrderDelete(OrderTicket()))
              {
               Print("Error in deleting order: ", GetLastError());
              }
           }
        }
     }
  }

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   // Check the total profit and close all if it exceeds $100
   double totalProfit = 0.0;
   for(int i = 0; i < OrdersTotal(); i++)
     {
      if(OrderSelect(i, SELECT_BY_POS) && OrderSymbol() == Symbol())
        {
         totalProfit += OrderProfit();
        }
     }

   if(totalProfit >= TakeProfit)
     {
      OnDeinit(0); // Close and delete all orders
     }
  }
//+------------------------------------------------------------------+

 

 

아래 그림과 같이 컴파일을 클릭했을때 에러메시지가 0으로 표시되면 됩니다. 일단, 프로그램은 통과된 것입니다.

 

Step3. 실제 차트에 적용하기

이제부터는 만들어진 EA가 제대로 작동하는지 테스트하면서 chat gpt와 수정과정을 거쳐야 합니다.

아마 여기서부터는 chat gpt를 사람처럼 설득하고 설명하고 문제점을 지적하는 굉장히 수고스런 과정이 펼쳐질 가능성이 큽니다.

똑똑한 직원이 chat gpt 이지만 일머리를 잘 설명해주고 내가 만들고 싶은 전략을 최종 검증하는건 사람이 해야할 일입니다.

 

자 검증을 시작해 보겠습니다~

 

차트를 보면 아래 그림처럼 탐색기 화면에 우리 가 만든 전략이 있을 것입니다. 여기서 우리가 만든 전략을 선택하여 드래그로 오른쪽 테스트할 심볼의 차트로 이동시킵니다. 만약 우리가 만든 전략이 보이지 않으면 새로고침하세요.

 

아래 그림처럼 전략 세팅화면에서 "실거래 가능"에 체크를 해야 합니다.

 

그리고 변수 설정에서는 아마도 우리가 chat gpt에 요구했던 수익금이 100달러 이상일 경우 청산하기에 대한 설정을 만든것 같습니다. 100포인트를 입맛에 맞게 수정하면 될것 같습니다.

 

그리고 아래 그림처럼 "시스템트레이딩"에 빨강 정지 버튼이 표시되면 EA가 작동을 안합니다. 이걸 클릭해서 실행중으로 변경하세요.

이렇게요~

 

일단 Buy 버튼을 클릭해서 매수 거래 1개를 시작해 보겠습니다.

처음 거래할때는 아래와 같이 원클릭 거래에 대한 경고메시지가뜰텐데요. 동의하고 확인 누릅니다.

그리고 다시 매수버튼 클릭하여 진입합니다.

 

자~ 어떤가요. 우리가 원하는건 아래와 같은 전략이었죠?

예상하건데 1개의 거래가 진입되었으므로 아래의 박스친 부분에 20개의 buy limit 거래가 미리 대기되도록 자동삽입되어야 합니다.

그런데 아무런 반응이 없죠? 전략 프로그램에 문제가 있는 것입니다.

 

- 처음 거래가 시작되면 진입되어 있는 가격을 기준으로 100포인트씩 간격을 두고 buy limit 또는 sell limit를 20개 오픈해줘

- 거래 오픈할때에는 처음 진입되어 있는 lot와 같은 수량으로 진입해줘

- 만약에 거래중인 전체의 수익이 100달러 이상이 되면 모든 거래를 청산하고 체결되지 않은 거래도 모두 삭제해줘

 

chat gpt에 이런 문제점을 알려주고 수정해달라고 요청해보겠습니다.

그냥 사람한테 이해시키듯이 문제점을 잘 설명해 주면 됩니다. 저는 아래 화면처럼 chat gpt에게 문제점을 알려주고 수정을 요청했습니다.

그랬더니 잘 알아듣고 새로운 소스를 만들어 줬습니다.

그렇다고 방심하면 안됩니다. chat gpt는 잘못된 소스도 자신감에 차서 잘 만들었다고 하는 경우가 많기 때문에 늘 검증과정을 거쳐야 합니다.

 

저는 새로 만들어준 소스를 반영해서 테스트해본 결과 buy limit 또는 sell limit 진입이 계속 안되는 문제에 직면했습니다.

그래서 chat gpt를 계속 괴롭혔습니다. 그리고 최종 아래와 같이 요청했습니다.

//+------------------------------------------------------------------+
//|                                             CustomEA.mq4         |
//|                        Copyright 2023, MetaQuotes Software Corp. |
//|                                       http://www.metaquotes.net |
//+------------------------------------------------------------------+
#property strict

// Input parameters
input double TakeProfit = 100.0; // Take profit level in dollars
input int NumberOfOrders = 20;    // Number of limit orders to place
input int PointsAway = 100;       // Distance in points for each limit order

// Global variables
double initialLotSize;
double initialPrice;
int direction; // 1 for buy, -1 for sell

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   // Initialization code here
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   // Check if there are open trades and no pending orders
   if(OrdersTotal() > 0 && !HasPendingOrders())
     {
      if(OrderSelect(0, SELECT_BY_POS))
        {
         initialLotSize = OrderLots();
         initialPrice = OrderOpenPrice();
         direction = (OrderType() == OP_BUY) ? 1 : -1;

         // Set up pending orders
         for(int i = 1; i <= NumberOfOrders; i++)
           {
            double priceOffset = i * PointsAway * Point;
            if(direction == 1) // For Buy orders, place Buy Limits below
              {
               if(OrderSend(Symbol(), OP_BUYLIMIT, initialLotSize, initialPrice - priceOffset, 3, 0, 0, "", 0, 0, clrNONE) < 0)
                 {
                  Print("Error in setting Buy Limit: ", GetLastError());
                 }
              }
            else // For Sell orders, place Sell Limits above
              {
               if(OrderSend(Symbol(), OP_SELLLIMIT, initialLotSize, initialPrice + priceOffset, 3, 0, 0, "", 0, 0, clrNONE) < 0)
                 {
                  Print("Error in setting Sell Limit: ", GetLastError());
                 }
              }
           }
        }
     }

   // Existing profit check and order closing logic here
   // ...
  }

//+------------------------------------------------------------------+
//| Function to check if there are any pending orders                |
//+------------------------------------------------------------------+
bool HasPendingOrders()
  {
   for(int i = 0; i < OrdersTotal(); i++)
     {
      if(OrderSelect(i, SELECT_BY_POS) && OrderType() > OP_SELL)
        {
         return true; // There is at least one pending order
        }
     }
   return false; // No pending orders
  }

// Existing OnDeinit function here
// ...

새로 저장한 프로그램이 작동하지 않는것 같다면, 전략을 다시 차트 위로 드래그엔 드랍해서 설정해 주세요.

 

짜잔~~~~~

여러분도 아래 그림처럼 진입되어 있는 매수 주문을 확인하고 buy limit 거래가 오픈되었나요?

이 정도면 여러분이 원하는 전략을 chat gpt를 이용해서 만들어 갈 수 있는 힌트를 얻었을까요?

여기까지 이해했다면 마틴게일 전략이나 기타 동원가능한 여러분의 상상력을 발휘하여 여러분만의 전략을 만들 수 있습니다.

 

chat gpt를 이용하여 mt4 또는 mt5 전략만들기 결론

친한 개발자 친구를 옆에 두고 친절히 전략을 설명해주면서 얼마든지 개발이 가능합니다.

오늘 예시로 보여준 전략 만들고 적용하는 과정을 예제삼아 연습해보면

여러분도 웬만한 수준급 프로그래머 이상의 실력을 보유한 EA 전략가 소리를 들을 수 있을 것입니다.

오늘은 여기까지~

 

궁금하신 점은 문의 주시면 아는 선에서 설명드리겠습니다.

댓글