외부 라이브러리를 사용하지 않고 3D 시각화 구현: MetaTrader 5에서 MQL5 + DX11을 통해 최적화 결과를 보여주는 방법
아름다운 그림에서 실용적인 도구로
전략 매개변수의 수가 10개를 넘어가게 되고 테스트 보고서가 여러 페이지에 걸친 수치들의 표로 변하게 되면 트레이더와 개발자는 문제에 직면하게 됩니다: 유용한 신호가 노이즈 속에 묻혀버리는 것입니다. 평면 차트와 2차원 히트맵은 어느 정도까지는 효과적이지만 그 이상으로 가게 되면 데이터의 다차원성 때문에 인간의 두뇌는 필연적으로 어려움을 겪게 됩니다. 우리는 지표의 기간, 손절매, 변동성 및 최대 손실률 간의 상관관계를 기억해 두려고 노력하지만 인지적 부담이 정보의 유용성보다 더 빠르게 증가합니다.
MetaTrader 5의 3D 시각화 및 반응형 인터페이스는 트레이딩 터미널을 게임 엔진으로 바꾸려는 시도가 아니라 인지적 마찰을 줄이기 위한 기술입니다. 높이가 예상 값에 해당하고 색상 그라데이션이 드로다운 탄력성을 반영하는 3D 표면을 사용하면 "안정성 고원"을 강조하고 "과적합의 바늘"을 몇 초 만에 잘라낼 수 있습니다. 표 형식으로 몇 시간 동안 비교해야 하는 것도 3차원 공간에서는 패턴으로 읽을 수 있습니다: 평면의 경사, 고도 변화, 고원/뾰족한 봉우리, 그리고 대비 영역 등이 그것입니다.
MetaTrader 5는 이러한 작업을 위한 완벽한 기술적 기반을 제공합니다. 네이티브 DirectX 11 지원, 내장 셰이더 파이프라인 및 CDXCanvas/CChartObjectDX 클래스가 MQL5 환경에 직접 통합되었습니다. 개발자는 외부 그래픽 라이브러리를 연결하거나 C++로 래퍼를 작성하거나 종속성을 처리할 필요가 없습니다: 장치 생성부터 프레임 출력까지의 전체 과정은 표준 3D API를 통해 접근할 수 있으며 셰이더와 텍스처 로딩은 Files\DX\ 폴더에서 직접 이루어집니다.
이 글에서는 최적화 결과 배열, 클러스터 볼륨 및 시나리오 모델을 목적에 따라 다루기 쉬운 3D 환경으로 변환하는 방법을 단계별로 살펴보겠습니다. 우리는 어떤 경우에 3D가 적절한지에 대한 기준을 다음과 같이 정의할 것입니다: 3D 그래픽이 신호 분석 기능을 추가하는 경우와 시각적 노이즈를 생성하는 경우. 다음으로 DX 파이프라인의 아키텍처, 초기화 과정, 메트릭을 정점 버퍼에 바인딩, 카메라 작동 방식, UI 패널을 검토한 후 마지막으로 이 환경의 기술적 한계를 평가하겠습니다.
그림 1. 텍스트 vs. 시각화
3D와 상호 작용성이 진정으로 유용한 경우
트레이더와 전략 개발자는 강력하지만 종종 과소평가되는 도구를 보유하고 있습니다: 시각적 인지 능력. 보고서 표, 지표 목록 및 평면 그래프는 결과를 문서화하는 데 효과적입니다. 하지만 복잡한 관계를 이해하는 데 있어서 인간의 뇌는 다른 모드로 전환됩니다: 이미지, 부피, 맥락의 형태로 패턴을 찾는 것입니다. 바로 이 지점에서 3D 시각화와 상호 작용성은 단순한 장식을 넘어 분석적 도구로 활용되는 것입니다.
데이터에 명확한 분석 가설이 있을 때 세 번째 축을 추가하는 것이 정당화됩니다. 예를 들어 고정된 위험 수준에서 시스템의 두 가지 핵심 매개변수에 대한 기대값의 의존성. 이 경우 3D 표면은 추상적인 좌표를 지형으로 변환하며 녹색의 "산"은 안정적인 수익 영역을 나타내고 빨간색인 "골"은 드로다운을 나타냅니다. 3D 표현은 필터 역할을 합니다: 노이즈를 걸러내고 의미 있는 조합만 남깁니다.
이는 미적인 이유 때문이 아니라 분석적 가치 때문입니다.
우리가 말하는 것은 장식을 위한 그래픽이 아니라 최적화 보고서 속에 숨겨진 내용을 직접적으로 드러내는 시각적 레이어입니다. 평평한 테이블은 다음 질문에 대한 답입니다: "이러한 매개변수 조합의 결과는 무엇입니까?"
3D 표면은 다음 질문에 답합니다: "두 매개변수를 부드럽게 변화시킬 때 결과는 어떻게 달라지며 안정성 영역은 어디에 있습니까?" 이는 근본적으로 다른 종류의 전략 분석입니다. 어떤 아이디어를 검증할 때 가장 중요한 것은 외부 환경이 변하더라도 결과가 안정적으로 유지되는 것입니다. 나머지는 모두 부차적인 것들입니다.
3D 시각화가 이점을 제공하는 경우는 최소한 세 가지가 있습니다:
1. 최적화 지형
여러분이 두 가지 매개변수, 가령 이동평균 기간과 손절매 크기를 선택한다고 가정해 보세요. 표에는 수익과 드로다운 값이 있는 100개의 행이 있습니다. 색상 그라데이션이 있는 3D 표면에서는 다음과 같은 현상을 바로 확인할 수 있습니다.
- 견고성 고원은 다양한 매개변수에도 불구하고 전략이 지속적으로 수익성을 유지하는 광범위한 녹색 영역입니다;
- 날카로운 봉우리는 좁은 국소 최대값으로 종종 과적합의 징후입니다;
- 급경사면은 매개변수의 작은 변화에도 드로다운이 급격히 증가하는 지역입니다.
이 3D 표면은 최대 이익이 아닌 안정성을 기반으로 최적의 매개변수 세트를 선택하는 데 정보에 입각한 결정을 내릴 수 있도록 해 줍니다.
2. 다차원 공간인 시장 상황
시장 양상(추세, 횡보, 변동성 증가)을 분류하려면 종종 세 가지 이상의 지표를 동시에 분석해야 합니다. 여기서 3D 시각화는 다음과 같은 이점이 있습니다:
- 각 시장 상태를 피처 공간의 한 점으로 나타냅니다;
- 이 모드(이 시점)에서 전략의 효과를 색상으로 구분합니다;
- 포인트 클라우드를 상호적으로 회전시켜 숨겨진 그룹을 드러냅니다.
이는 특히 매개변수를 적응적으로 설정할 때 매우 편리합니다: 어떤 조건에서 전략이 실패하고 어떤 조건에서 안정적으로 작동하는지 확인할 수 있습니다.
3. 시나리오 모델링 및 스트레스 테스트
몬테카를로 메서드, 가격 경로 생성, 변동성이 30% 증가하면 어떻게 될 까와 같은 다양한 합성적인 시나리오에서 전략을 실행할 때 세 번째 차원은 다음과 같은 결과를 보여줄 수 있습니다:
- X축 — 전략 매개변수;
- Y축 – 시장 스트레스 수준(변동성, 갭);
- Z축/색상 — 최종 메트릭(복구율, 기대값).
결과적으로 우리는 최악의 시나리오뿐만 아니라 시장 상황이 악화되는 중에 전략의 견고성의 한계를 관찰하고 있는 것입니다.
선택 기준: 3D가 과할 때
규칙을 하나 만들어 봅시다: 3D는 결과가 두 개 이상의 연속 변수에 의존하는 관계를 조사하고 이러한 의존 관계의 기하학적 형태를 파악하는 것이 중요할 때 유용합니다.
보고서를 일일이 검토하는 데 소요되는 시간을 직관적인 시각적 분석으로 대체할 준비가 되셨다면 렌더링 파이프라인부터 시작해 보겠습니다.
MQL5의 기본 DX 파이프라인: 초기화부터 첫 번째 프레임까지
MetaTrader 5에서 3D 그래픽을 생성하는 것은 각 단계마다 고유한 목적이 있는 순차적인 과정입니다. DirectX 객체의 아키텍처와 렌더링 루프를 이해하면 대용량 데이터를 처리할 때 발생하는 메모리 누수, 화면 깜빡임, 성능 저하와 같은 일반적인 문제를 피할 수 있습니다.
MQL5의 DirectX 객체 아키텍처
MQL5에서 3D 그래픽의 기반은 DirectX 11 작업의 모든 복잡함을 캡슐화 하는 CCanvas3D 클래스입니다. 이는 개발자에게 하이 레벨 API를 제공하고 장치, 컨텍스트 및 버퍼 생성과 관련된 로우 레벨 세부 사항을 숨깁니다.
객체 계층 구조:
- CCanvas3D — 장면, 카메라 및 렌더링을 관리하는 클래스
- CDXMesh 및 그 파생 클래스(CDXBox, CDXSphere, CDXTorus) — 기하학적 객체
- DXVertex — 좌표, 법선(노멀), 텍스처 좌표 및 색상을 포함하는 정점(버텍스) 구조체
struct DXVertex { DXVector4 position; // vertex coordinates DXVector4 normal; // normal vector DXVector2 tcoord; // texture coordinates DXColor vcolor; // color };
이 구조는 표준 정점 셰이더와 호환되며 기본적인 작업을 위해 사용자 맞춤형 셰이더를 작성할 필요가 없습니다. 복잡한 프로젝트의 경우 MQL5\Include\Canvas\DX\DXUtils.mqh 파일에 제시된 메서드와 유틸리티를 사용하는 것이 좋습니다.
그림 2. MQL5에서 3D 그래픽 계층 구조
모든 리소스(셰이더, 텍스처, 버퍼)는 DXDispatcher를 통해 관리됩니다. 생성된 모든 객체는 소멸자에서 Destroy() 또는 Shutdown()을 통해 명시적으로 소멸되어야 합니다. MetaTrader 5에는 DirectX 리소스용 가비지 컬렉터가 없습니다. 따라서 터미널을 다시 시작할 때까지 메모리 누수가 누적됩니다.
파이프라인 초기화
첫 번째 단계는 캔버스를 생성하고 투영 행렬을 설정하는 것입니다:
//+------------------------------------------------------------------+ //+ canvas creation and projection matrix setup | //+------------------------------------------------------------------+ virtual bool Create(const int width, const int height) { //--- save canvas dimensions m_width = width; m_height = height; //--- create a canvas to render a 3D scene ResetLastError(); if(!m_canvas.CreateBitmapLabel("3D Sample_1", 0, 0, m_width, m_height, COLOR_FORMAT_ARGB_NORMALIZE)) { Print("Error creating canvas: ", GetLastError()); return(false); } //--- set the projection matrix parameters m_canvas.ProjectionMatrixSet((float)M_PI/6, (float)m_width/m_height, 0.1f, 100.0f); //--- create a 3D object if(!m_box.Create(m_canvas.DXDispatcher(), m_canvas.InputScene(),DXVector3(-1.0, -1.0, -1.0), DXVector3(1.0, 1.0, 1.0))) { m_canvas.Destroy(); return(false); } //--- add a cube to the scene m_canvas.ObjectAdd(&m_box); Redraw(); return(true); }
주요 투영 매개변수:
- 시야각(FOV) - 30도(M_PI/6), 원근감과 왜곡 사이의 균형;
- 화면 비율 — 가로세로 비율(m_width/m_height), 이 비율을 유지하면 가로/세로 방향으로 늘어나는 것을 방지;
- 클리핑 평면은 0.1f(가장 가까운)와 100.0f(가장 먼), 이 범위를 벗어난 객체는 렌더링 되지 않음.
이러한 매개변수는 가시성 피라미드를 정의합니다: 두 가상 벽 사이에 위치하고 수평 시야각 내에 있는 객체만 투영 행렬에 포함됩니다.
셰이더 컴파일 - 표준 기본 도형의 경우 셰이더가 자동으로 컴파일 됩니다. 사용자 맞춤형 효과를 적용하는 경우 오류 처리와 함께 DXCompileShader()를 사용하세요.
string error_log; if(!DXCompileShader("shader.hlsl", "vs_main", "vs_5_0", shader_blob, error_log)) { Print("Shader compilation failed: ", error_log); return(false); }
데이터 → 정점 → 프레임
초기화가 완료되면 렌더링 주기가 시작됩니다. 각 프레임은 변환 파이프라인을 거칩니다:
객체 모델 — 3차원 모델은 다각형 메쉬로 표현됩니다. 실제로는 삼각분할이 사용됩니다: 삼각형은 공간에서 하나의 평면을 고유하게 나타내기 때문에 각각의 다각형은 삼각형으로 나뉘어집니다. 예를 들어 정육면체는 8개의 정점을 가지고 있지만 정확한 조명을 위해서는 24개의 정점이 생성됩니다(각 면에 고유한 법선을 가진 4개씩).
//--- preparing vertices and indices for the sphere DXVertex vertices[]; uint indices[]; if(!DXComputeSphere(0.3f, 50, vertices, indices)) return(false); //--- create the sphere object if(!m_sphere.Create(m_canvas.DXDispatcher(), m_canvas.InputScene(), vertices, indices)) { m_canvas.Destroy(); return(false); }
변환 — 각 객체는 행렬들을 거칩니다:
- 모델 행렬 — 로컬 좌표 → 월드 (회전, 크기 조정, 재배치);
- 뷰 행렬 — 월드 좌표 → 카메라 좌표;
- 투영 행렬 — 카메라 좌표 → 화면 좌표.
//--- calculate the cube position and the transfer matrix DXMatrix rotation, translation; //--- rotate the cube sequentially along the X, Y and Z axes DXMatrixRotationYawPitchRoll(rotation, (float)M_PI/4, (float)M_PI/3, (float)M_PI/6); //--- shift the cube to the right-down-into the depth DXMatrixTranslation(translation, 1.0, -2.0, 5.0); //--- get the transformation matrix as a product of rotation and transfer DXMatrix transform; DXMatrixMultiply(transform, rotation, translation); //--- set the transformation matrix m_box.TransformMatrixSet(transform);
조명(퐁 모델) — 사실적인 이미지를 구현하려면 세 가지 조명 구성 요소를 계산해야 합니다.
- 주변광(배경광) — 산란된 빛을 시뮬레이션 하는 일정한 요소;
- 산란광(확산광) — 표면에 입사하는 빛의 각도에 따라 달라짐;
- 반사광(거울) — 광택 효과를 만들어내는 하이라이트.
//--- set the source color to yellow and direct it from top to bottom m_canvas.LightColorSet(DXColor(1.0, 1.0, 0.0, 0.8f)); m_canvas.LightDirectionSet(DXVector3(0.0, -1.0, 0.0)); //--- set the blue color for the ambient light m_canvas.AmbientColorSet(DXColor(0.0, 0.0, 1.0, 0.4f)); //--- set the cube color to white with a green glow m_box.DiffuseColorSet(DXColor(1.0, 1.0, 1.0, 1.0)); m_box.EmissionColorSet(DXColor(0.0, 1.0, 0.0, 0.2f));
렌더링 및 캔버스 업데이트 - 모든 작업은 Render() 메서드에서 수행됩니다. 그 후, Update()를 통해 이미지가 캔버스로 전송됩니다:
//--- calculate the 3D scene m_canvas.Render(DX_CLEAR_COLOR | DX_CLEAR_DEPTH, ColorToARGB(clrBlack)); //--- update the picture on the canvas in accordance with the current scene m_canvas.Update();
메모리 관리 — 각 DX 객체는 비디오 메모리를 소비합니다. 동적 장면(예: 최적화 표면 업데이트)을 생성할 때는 다음과 같이 해야 합니다:
- 새로운 버퍼를 생성하기 전에 기존 버퍼를 비웁니다;
- 리소스를 명시적으로 해제하려면 DXResourceRelease()를 사용 해야 합니다.
- 정점 개수를 제어 해야합니다: 정적 객체의 경우 수천 개의 폴리곤이 허용되고 애니메이션 객체의 경우 수백 개의 폴리곤이 허용됩니다(정확한 수치는 컴퓨터 성능에 따라 다릅니다).
진단 및 오류 검사 — 항상 반환 값을 확인하고 오류가 발생하면 GetLastError()를 사용하여 진단하세요.
if(!m_canvas.CreateBitmapLabel(...)) { int err = GetLastError(); Print("DX Error code: ", err); //--- typical errors: //--- 1: device does not support DX11 //--- 2: insufficient video memory //--- 3: shader compilation error }
하드웨어 가속 또는 소프트웨어 렌더링:
MT5는 비디오 카드의 성능을 자동으로 감지합니다. DirectX 11을 사용할 수 없는 경우 그래픽이 표시되지 않습니다. 확인할 사항:
- DX11 및 셰이더 버전 5.0을 지원하는 비디오 카드;
- 관련 드라이버(구버전은 오류를 유발할 수 있음);
- 터미널 설정에서 하드웨어 가속을 활성화합니다.
설치된 DirectX 버전을 확인하려면 다음 명령어를 실행하세요 following steps:
- 윈도우 도구 모음의 검색 창에 "dxdiag"를 입력합니다. 그런 다음 결과 목록에서 "dxdiag"를 선택합니다;
- DirectX 진단 도구에서 시스템 탭을 선택하세요 - DirectX 버전은 11 이상이어야 합니다.
그림 3. DirectX 버전 확인
주의:
DirectX 진단 도구를 처음 사용할 때 드라이버의 디지털 서명을 확인하라는 메시지가 나타날 수 있습니다. 드라이버가 진위 여부가 확인된 게시자에 의해 서명되었는지 확인하기 위해 '예'를 선택하는 것이 좋습니다.
렌더링 루프의 컴퓨터 리소스 사용량 최적화:
- OnTimer() 또는 OnChartEvent() — 정적 장면의 경우, 데이터가 변경될 때만 Redraw() 함수를 호출하세요, 매 틱마다 호출하지 마세요;
- 세부 묘사 수준(LOD:Level of Detail) — 카메라가 멀어질수록 물체의 세부 묘사를 줄입니다;
- 인스턴싱 - 여러 개의 동일한 객체(군집, 마커 등)를 처리할 때 하나의 메시(Mesh)에 서로 다른 변환 행렬을 적용하여 사용합니다.
기본 파이프라인은 준비되었습니다. 우리는 캔버스를 만들고 투영을 설정하고 정점과 법선을 사용하여 객체를 정의하고 변환과 조명을 적용했습니다. 다음 단계는 이 프레임워크에 분석적인 콘텐츠를 채우는 것입니다: 최적화 결과를 3D 표면으로, 유동성 클러스터를 입체 구조로, 시나리오 모델을 대화형 보고서로 변환하는 것입니다.
복잡한 데이터 시각화 - 표면, 클러스터, 시나리오
기본 DX 파이프라인 설정이 완료되면 이제 우리에게는 데이터를 시각화 할 수 있는 빈 공간이 있는 것입니다. 다음 작업은 테스터의 보고서에 있는 숫자를 사람이 이해할 수 있는 기하학적 프리미티브로 변환하는 것입니다. 우리는 원시 행렬에서 시각적으로 해석 가능한 풍경으로 나아가는 것입니다.
3D 최적화 표면을 구축하는 것은 트레이딩에서 3D를 활용하는 가장 유용한 방법일 것입니다. 전략 테스터는 행은 실행 결과이고 열은 매개변수 및 메트릭인 표를 생성합니다. 최적화 결과를 3D로 시각화 하면 이 표가 지형으로 바뀝니다.
간단한 시각화 공식: X축과 Z축은 전략 매개변수(예: 이동평균 기간 및 손절매 사이즈)가 되고 Y축(높이)은 목표 함수(예: 회복 요소, 기대값)가 됩니다. 이러한 표면을 구축하기 위해서는 결과 배열을 기반으로 삼각형 메쉬(Mesh)를 생성해야 합니다.
구성 알고리즘:
- 데이터 수집 – 최적화 결과 배열들을 검토하고 필요한 데이터를 선택하고 구조화합니다;
- 정규화 - 그래프가 평평해 보이지 않도록 매개변수 값을 일반적인 척도로 정규화합니다;
- 정점 생성 - 각 데이터 포인트에 대해 DXVertex 정점을 생성합니다;
- 삼각분할 - 인접한 꼭짓점들을 인덱스를 이용하여 삼각형으로 연결합니다.
//+------------------------------------------------------------------+ //| example of creating a surface from a data array | //+------------------------------------------------------------------+ void CreateOptimizationSurface(const double &data[],const int width,const int height) { DXVertex vertices[]; uint indices[]; int v_count = 0; int i_count = 0; //--- allocate memory for vertices (width*height of points) ArrayResize(vertices,width*height); for(int y=0;y<height;y++) { for(int x=0;x<width;x++) { int idx=y*width+x; //--- X and Z are the coordinates of the parameters, Y is the value of the metric (profit) vertices[idx].position=DXVector3(x, data[idx], y); vertices[idx].normal=DXVector3(0, 1, 0); // simplified normal vertices[idx].vcolor=ColorToVector4(ColorFromValue(data[idx])); // color depends on value vertices[idx].tcoord=DXVector2((float)x/width, (float)y/height); } } //--- next, we form an array of indices for triangles and create an object using m_mesh.Create(...) }
이러한 표면에서는 매개변수가 변경될 때 전략이 비교적 안정적으로 작동하는 넓은 영역인 "고원"이 즉시 눈에 띕니다. 반대로 바늘처럼 좁은 수익 정점이 뚜렷하게 나타나는데 이는 과적합을 나타냅니다. 1000개의 행으로 이루어진 표에서 그러한 "바늘"을 알아차리는 것보다 시각적으로 잘라내는 것이 훨씬 쉽습니다. 다차원적 종속성은 표 형식에서는 잘 드러나지 않기 때문입니다.
공간에서의 클러스터 분석
시장 데이터에는 가격과 시간뿐만 아니라 볼륨도 포함됩니다. 2D에서는 일반적으로 화면 하단에 볼륨 히스토그램을 그리지만 3D에서는 볼륨이 하나의 완전한 차원이 됩니다. 평평한 바 그래프 대신 트레이딩 볼륨이나 클러스터 밀도에 따라 높이와 두께가 달라지는 볼륨 블록(복셀)이나 원통을 사용할 수 있습니다:
- X축 - 시간;
- Z축 - 가격;
- Y축 — 볼륨 / 매매 건수(복셀 반경).
유동성 시각화 - DXComputeSphere 또는 사용자 맞춤형 메시를 사용하여 다양한 크기와 투명도를 가진 구체로 대규모 매매 클러스터를 그릴 수 있습니다. 이러한 요소들이 서로 겹쳐지면서 이들이 유동성 구름을 형성하고 트레이더는 그 안에서 "빈 구간(voids)"(가격이 빠르게 변동한 영역)과 "유동성 덩어리(clots)"(지지/저항 수준)를 확인할 수 있습니다.
//--- setting color based on volume (heatmap effect) //--- the larger the volume, the redder the color (from blue to red) color cluster_color=ColorInterpolate(clrBlue,clrRed,volume_ratio); m_cluster.MeshColorSet(ColorToVector4(cluster_color,0.7)); // 0.7 - transparency
DXComputeSurface()를 통한 표면 생성
일반적인 2차원 데이터 시각화 작업(히트맵, 최적화 결과, 상관 행렬)의 경우 DirectX MQL5 라이브러리는 DXComputeSurface()라는 기성 템플릿 함수를 제공합니다. 해당 함수는 DXUtils.mqh 파일에 있습니다.
선언:
//+------------------------------------------------------------------+ //| Surface | //| TVertex must have | //| DXVector4 position, DXVector4 normal and DXVector2 tcoord members| //+------------------------------------------------------------------+ template <typename TVertex> bool DXComputeSurface(double &data[],uint data_width,uint data_height,double data_range, const DXVector3 &from,const DXVector3 &to,DXVector2 &texture_size, bool two_sided,bool use_normals, TVertex &vertices[],uint &indices[])
목적:
2D 데이터 배열을 기반으로 3D 표면의 정점과 인덱스를 자동으로 생성합니다. 이 함수를 사용하면 개발자는 좌표, 메쉬 삼각분할 및 법선을 수동으로 계산할 필요가 없습니다.
입력:
| 매개변수 | 타입 | 설명 |
|---|---|---|
| [in] data[] | double& | 높이 값의 1차원 배열(최적화 데이터, 상관관계 등) |
| [in] data_width | uint | 원본 데이터 행렬의 너비(열의 개수) |
| [in] data_height | uint | 원본 데이터 행렬의 높이(행 수) |
| [in] data_range | double | Z축(높이)을 따른 값의 스케일링 범위 |
| [in] from | const DXVector3& | 3차원 공간에서 표면의 왼쪽 아래 모서리의 좌표 |
| [in] to | const DXVector3& | 3차원 공간에서 표면의 오른쪽 위 모서리의 좌표 |
| [in] texture_size | DXVector2& | 텍스처 좌표 크기 (텍스처 매핑 또는 그라디언트용) |
| [in] two_sided | bool | 양면 렌더링 플래그(투명 표면에 유용) |
| [in] use_normals | bool | 정확한 조명을 위한 법선 계산 플래그 |
| [out] vertices[] | TVertex& | 함수에 의해 채워진 출력 정점 배열 |
| [out] indices[] | uint& | 삼각분할에 필요한 인덱스 배열을 출력합니다(함수에 의해 채워짐). |
TVertex 유형 요구 사항 - TVertex 템플릿 매개변수는 최소 3개의 필드를 포함하는 구조체여야 합니다:
struct MyVertex { DXVector4 position; // vertex coordinates (x,y,z,w) DXVector4 normal; // normal vector (nx,ny,nz,0) DXVector2 tcoord; // texture coordinates (u,v) // additional fields as needed: color, binormal, etc. };
반환 값:
- 참 — 표면이 성공적으로 생성됨;
- 거짓 — 오류 (배열 크기 및 입력 데이터 유효성을 확인).
사용 예시:
전략 최적화 결과가 20x20 행렬 형태로 표현되어 있다고 가정해 봅시다. 여기서 각 값은 거래의 기대값을 나타냅니다. 우리는 이 데이터를 3D 표면으로 시각화 하려고 하는 것입니다.
//+------------------------------------------------------------------+ //| Generate optimization surface via DXComputeSurface | //+------------------------------------------------------------------+ void BuildOptimizationSurface(double &optimization_data[],uint width,uint height) { //--- define the vertex type with an additional color field struct SVertex { DXVector4 position; DXVector4 normal; DXVector2 tcoord; DXColor vcolor; // vertex color for gradient }; SVertex vertices[]; uint indices[]; //--- surface parameters DXVector3 from(-10.0,-5.0,0.0); // lower left corner DXVector3 to(10.0,5.0,1.0); // upper right corner DXVector2 texture_size(1.0,1.0); // full coverage of texture coordinates double data_range=2.0; // height scaling //--- generate geometry if(!DXComputeSurface(optimization_data,width,height,data_range, from,to,texture_size, false,true, // one-sided, with normals vertices,indices)) { Print("surface generation error: ",GetLastError()); return; } //--- color the vertices by height (gradient: red → green) for(uint i=0;i<ArraySize(vertices);i++) { double t=MathMax(0.0,MathMin(1.0,vertices[i].position.z/data_range)); vertices[i].vcolor=DXColor(1.0f-(float)t,(float)t,0.2f,1.0f); } //--- create a mesh and add it to the scene if(!mesh.Create(canvas.DXDispatcher(),canvas.InputScene(),vertices,indices)) Print("error creating mesh: ",GetLastError()); mesh.DiffuseColorSet(DXColor(1.0f,1.0f,1.0f,1.0f)); canvas.ObjectAdd(&mesh); }
DXComputeSurface()의 장점:
- 개발 속도 - 삼각분할 및 법선 계산 사이클을 직접 작성할 필요가 없습니다;
- 최적화 - 내부 구현에서는 효율적인 메쉬 생성 알고리즘을 사용합니다;
- 유연성 - 템플릿 정점 유형을 사용하면 색상, 질감, 사용자 지정 데이터와 같은 추가 속성을 자유롭게 추가할 수 있습니다.
DXComputeSurface() 제한 사항:
- 정규 그리드에서만 작동합니다 - 이 함수는 데이터가 직사각형 행렬이라고 가정합니다. 불규칙한 포인트 클라우드 또는 임의의 토폴로지의 경우 직접 생성해야 합니다;
- 디폴트 보간 - 정점 높이는 그리드 노드 사이에서 선형적으로 보간 됩니다. 불규칙한 표면을 매끄럽게 하기 위해 데이터를 사전에 필터링해야 할 수도 있습니다.
- 메모리 - 이 함수는 정점 및 인덱스 배열을 동적으로 할당합니다. 대규모 행렬(예: 100x100 이상)을 다룰 때는 메모리 사용량과 표면 재구성 빈도를 모니터링해야 합니다.
반응형 제어와의 통합:
DXComputeSurface() 함수는 정적 형상을 생성하므로 동적 업데이트(예: 최적화 매개변수를 실시간으로 변경하는 등)에는 다음이 필요합니다:
- CDXMesh 객체에 대한 참조를 저장합니다,
- 데이터가 변경되면 mesh.Shutdown()을 호출하여 이전 버퍼를 해제합니다,
- 새로운 데이터를 사용하여 DXComputeSurface() 및 mesh.Create()를 다시 호출합니다,
- 변경 사항을 표시하려면 RedrawScene()을 호출합니다.
부드러운 애니메이션을 위해서는 DX_OptimizationSurface EA 처럼 무거운 작업을 OnTimer 핸들러로 옮기는 것이 좋습니다(아래 설명 참조). DXComputeSurface() 함수를 사용하면 로우 레벨 그래픽보다는 분석 논리에 집중할 수 있습니다. 일반적인 표면을 구성할 때 코드 양이 30~40% 감소하기 때문입니다.
시나리오 모델링 및 반응형 보고서
MQL5에서 DirectX를 사용하는 장점 중 하나는 인디케이터를 다시 로드 하지 않고도 장면을 동적으로 업데이트 할 수 있다는 것입니다. 이는 "만약 ~라면?" 시나리오를 모델링할 수 있는 길을 열어줍니다. 예를 들어, "변동성" 또는 "수수료"라고 표시된 슬라이더를 움직이는 패널이 있다고 합시다. data[] 배열은 실시간으로 다시 계산되며 VertexSet() 정점 버퍼 업데이트 함수는 3D 표면을 동적으로 변경합니다.
//+------------------------------------------------------------------+ //| dynamic update example | //+------------------------------------------------------------------+ void OnSliderChange(const double new_vol) { //--- recalculate the strategy metrics with the new volatility RecalculateStrategyMetrics(new_vol); //--- update only the Y-coordinate of the vertices (height), without recreating the mesh for(int i=0;i<ArraySize(m_vertices);i++) { m_vertices[i].position.y=m_new_metrics[i]; //--- recalculate normals for correct lighting m_vertices[i].normal=CalculateNormal(i); } //--- send updated data to video memory m_mesh.VertexSet(m_vertices); Redraw(); }
이를 통해 트레이더는 전략의 지속 가능성을 확인할 수 있습니다. 변동성의 작은 변화로 수익성 있는 차트가 손실 차트로 바뀐다면 해당 전략은 장기적으로 실행 가능성이 낮을 것입니다.
분석 필터로서의 셰이더
MetaTrader 5의 기본 셰이더가 조명(퐁 모델)을 담당합니다. 하지만 분석을 위해서는 데이터와 함께 작동하는 셰이더가 필요합니다. 우리는 필터 역할을 하는 간단한 픽셀 셰이더를 작성할 수 있습니다.
예를 들어 3D 차트에서 드로다운이 20%를 초과하는 영역이나 profit factor가 1보다 작은 영역만 강조 표시해야 할 때가 있습니다.
//+------------------------------------------------------------------+ //| example of logic in HLSL shader | //+------------------------------------------------------------------+ float4 PS_Main(PS_INPUT input) : SV_TARGET { //--- input.color contains the metric information encoded in the vertex float profit=input.color.r; //--- if the profit is below the threshold, make the object transparent if(profit<threshold) return float4(0.5,0.5,0.5,0.2); // gray and transparent else return float4(0.0,1.0,0.0,1.0); // bright green }
셰이더에서는 정점 속성(예: 높이 또는 전달된 색상)의 값을 확인하고 기준을 충족하지 않으면 해당 픽셀을 투명하게 하거나 회색으로 만듭니다. 이러한 접근 방식을 통해 우리는 그래프에서 "잡음"을 제거하고 의미 있는 영역만 남길 수 있습니다. 이는 대규모 최적화 데이터 배열을 분석할 때 중요합니다.
상호 작용 - 마우스, 버튼 및 카메라 제어
정적인 3D 이미지는 아름답지만 회전, 확대/축소 또는 필터링이 불가능하다면 트레이딩에는 거의 쓸모가 없습니다. MQL5에서 DirectX의 진정한 이점은 데이터를 적극적으로 탐색해야 할 때 나타납니다. 마우스 및 키보드 이벤트를 카메라 연산과 연동하여 장면을 생동감 있게 만드는 방법을 살펴보겠습니다.
MQL5에서의 이벤트 처리 - 캔버스에 생명을 불어넣기
기본적으로 캔버스(CDXCanvas)는 커서에 반응하지 않는 래스터 이미지입니다. 사용자와 상호 작용하도록 하려면 차트 이벤트를 구독해야 합니다. 이는 OnInit() 함수의 CHART_EVENT_MOUSE_... 수정자를 통해 수행됩니다:
//+------------------------------------------------------------------+ //| subscribe to mouse events | //+------------------------------------------------------------------+ int OnInit() { //--- enable receiving mouse events ChartSetInteger(0,CHART_EVENT_MOUSE_MOVE,1); ChartSetInteger(0,CHART_EVENT_MOUSE_WHEEL,1); //--- timer for animation EventSetMillisecondTimer(16); return(INIT_SUCCEEDED); }
이후 모든 커서의 이동은 OnChartEvent() 핸들러에 의해 처리됩니다. 다음 작업은 필요한 ID(CHARTEVENT_MOUSE_MOVE, CHARTEVENT_MOUSE_WHEEL)를 필터링하고 해당 좌표를 코드의 렌더링 부분으로 전달하는 것입니다.
비고:
OnDeinit() 메서드에서 ChartSetInteger(..., 0)을 호출하여 이러한 이벤트를 비활성화해야 합니다. 그렇지 않으면 지표를 삭제한 후에도 터미널에서 이벤트가 계속 발생하여 불필요한 부하가 발생합니다.
카메라 제어 - 회전 및 줌
3D 그래픽과 상호 작용하는 가장 일반적인 방법은 객체를 중심으로 회전(궤도 회전)하거나 확대/축소하는 것입니다. DirectX에서는 객체 자체를 회전시키는 것이 아니라 장면의 중심을 기준으로 구형 궤도를 따라 카메라를 이동시켜 이를 구현합니다.
CCanvas3D에서 카메라를 제어하는 데에는 서로 연관된 세 가지 방법이 사용됩니다:
- ViewPositionSet() — 관찰자의 눈 위치(카메라 좌표)를 설정합니다;
- ViewTargetSet() — 관찰자가 바라보는 위치를 설정합니다(일반적으로 장면의 중심은 0,0,0입니다);
- ViewUpDirectionSet() — 프레임 상단의 방향을 설정합니다(카메라가 뒤집히지 않도록).
회전 구현
마우스 왼쪽 버튼을 누른 상태에서 마우스 커서를 움직여 회전시킬 수 있습니다. 장면을 회전시키기 위해 커서 이동량 델타를 추적합니다: 현재 위치와 이전 위치의 차이. 우리는 이 델타를 X축과 Y축을 중심으로 한 회전 각도로 변환합니다.
//+------------------------------------------------------------------+ //| mouse movement event handler | //+------------------------------------------------------------------+ void OnMouseMove(int x, int y, uint flags) { //--- check that the left mouse button is pressed if((flags&1)==1) { //--- calculate the change in angles based on the mouse offset //--- divide by the coefficient (for example, 300.0f) for sensitivity m_camera_angles.y+=(x-m_mouse_x)/300.0f; m_camera_angles.x+=(y-m_mouse_y)/300.0f; //--- limit the vertical angle if(m_camera_angles.x<-DX_PI*0.49f) m_camera_angles.x=-DX_PI*0.49f; if(m_camera_angles.x>DX_PI*0.49f) m_camera_angles.x=DX_PI*0.49f; //--- recalculate the camera position UpdateCameraPosition(); Redraw(); } //--- save the current coordinates for the next step m_mouse_x=x; m_mouse_y=y; }
UpdateCameraPosition() 함수에서는 DXMatrixRotationX 및 DXMatrixRotationY 회전 행렬을 사용하여 카메라의 방향 벡터를 회전시키고 공간에서의 위치를 업데이트합니다.
줌 구현
마우스 휠을 돌리면 카메라와 장면 중심 사이의 거리(m_camera_distance)가 변경됩니다.
//+------------------------------------------------------------------+ //| mouse wheel rotation event handler | //+------------------------------------------------------------------+ void OnMouseWheel(double delta) { //--- decrease or increase the distance m_camera_distance*=1.0-delta*0.001; //--- limit the zoom to reasonable values if(m_camera_distance>50.0) m_camera_distance=50.0; if(m_camera_distance<3.0) m_camera_distance=3.0; UpdateCameraPosition(); Redraw(); }
3D 장면 위에 UI 패널이 있습니다.
3D 그래픽은 데이터를 표시하는 역할을 하지만 매개변수를 제어하려면 표준적이고 친숙한 MQL5 인터페이스 요소가 필요합니다. 이미 존재하는 기능을 다시 개발하는 수고를 덜기 위해 그래픽 캔버스 위나 옆에 그려지는 표준 MQL5 컨트롤 라이브러리(CAppDialog, CSlider, CComboBox)와 같은 클래스를 사용하세요. 인터페이스를 구축하는 데 다른 클래스를 사용할 수도 있습니다.
슬라이더 값이 변경될 때(예: "수익 임계값") 정점 버퍼의 데이터를 업데이트하거나 셰이더 변수를 변경하는 함수가 호출된 후 Redraw() 함수가 호출됩니다. 이를 통해 우리는 완벽한 분석 도구를 만들 수 있습니다. 예를 들어 왼쪽에는 최적화 결과를 보여주는 대화형 3D 화면이 있고 오른쪽에는 필터가 있는 제어판이 있습니다.
반응형 주기 최적화
반응형 기능이 단말기 및 컴퓨터 전체의 성능을 크게 저하시켜서는 안 됩니다. 마우스 버튼을 누르지 않고 마우스를 아주 조금만 움직여도 Redraw() 함수가 호출되면 터미널 인터페이스 속도가 느려지기 시작합니다.
상호 작용성을 최적화하기 위한 기본 규칙을 정립해 봅시다.
- Redraw()는 필요한 경우에만 호출하세요. 장면 다시 그리기는 체크 블록 내에서만 호출해야 합니다: 예를 들어, if((flags & 1) == 1) (버튼이 눌렸을 때 확인) 또는 UI 매개변수가 변경될 때 호출합니다;
- 불필요한 이벤트 필터링 - 다시 그리기를 위한 데이터가 너무 자주 발생하는 경우(예: OnTick() 핸들러의 틱에서 발생하는 경우) 정점 버퍼를 초당 10~15회 이하로 업데이트합니다;
- 대규모 계산의 비동기화 - 매개변수 변경으로 수천 개의 정점을 다시 계산해야 하는 경우(예: 전체 최적화 표면을 다시 구축하는 경우), 인터페이스가 멈추는 것을 방지하기 위해 OnTimer() 타이머 이벤트 핸들러에서 수행하거나 DLL을 통해 별도의 스레드로 이동하세요.
3D 검증 테스트 EA
우리는 앞서 살펴본 3D 기술을 구현하는 EA를 개발할 것입니다. 이 EA는 MetaTrader 5 트레이딩 터미널에서 분석 데이터를 3차원으로 시각화 하는 도구입니다. 주요 목적은 매매 전략 최적화의 수치적 결과를 3차원 표면으로 변환하여 트레이더 및/또는 개발자가 전략의 품질과 안정성을 신속하게 평가할 수 있도록 하는 것입니다.
EA는 다음과 같은 문제를 해결합니다:
- 최적화 표면의 시각화는 목적 함수(이익, 기대값, 샤프 비율)가 두 가지 최적화 전략 매개변수에 어떻게 의존하는지를 3차원 지형도 형태로 보여주는 것입니다.
- 전략 안정성 분석 – "안정성의 고원"(결과 변화가 완만한 영역)와 "과적합 바늘"(과거 데이터에 과적합 되었음을 나타내는 고립된 정점)를 식별합니다.
- 마우스를 사용하여 표면을 회전, 확대/축소하고 자세히 탐색할 수 있는 반응형 데이터 탐색 기능을 제공합니다.
- 모드 비교 – 최적화 품질을 평가하기 위해 다양한 표시 모드(예: 수익 및 노이즈) 간에 전환합니다.
특징:
3D 시각화 — EA는 차트에 640×480 픽셀 크기의 반응형 3D 캔버스를 생성하여 분석 함수를 기반으로 생성된 표면을 표시합니다. 표면은 25x25 정점 메쉬이며 정확한 표시를 위해 삼각으로 분할되었습니다.
색상 코딩 — 다음 색상표가 적용되었습니다:
- 최상단(최대값)은 진한 녹색;
- 기준값(최소값) - 진한 붉은색;
- 중간값은 노란색에서 주황색으로 이어지는 부드러운 그라데이션.
이 코딩을 통해 우리는 최대 수익 영역(녹색 "언덕")과 손실 영역(빨간색 "골")을 확실하게 식별할 수 있습니다.
카메라 제어 — 이제 시점을 완벽하게 제어할 수 있게 되었습니다:
- 회전 - 마우스 왼쪽 버튼을 누른 상태에서 커서를 움직이면 카메라가 장면의 중심을 기준으로 구형 궤도를 따라 회전합니다;
- 줌 - 마우스 휠을 돌리면 카메라가 확대 또는 축소됩니다(5.0~40.0 단위 거리);
- 제한 - 카메라가 뒤집히는 것을 방지하기 위해 수직 각도는 ±0.9×π/2로 제한됩니다.
반응형 제어
캔버스에 모드 전환 버튼이 있습니다:
- 수익 모드 - 부드러운 가우시안 곡선 표면을 표시(안정적인 전략을 시뮬레이션);
- 노이즈 모드 - 표면에 무작위 노이즈를 추가하여 표시(과도하게 최적화된 전략을 시뮬레이션).
모드를 전환하면 버튼 텍스트가 자동으로 업데이트됩니다.
조명 및 재료
사실적인 입체 이미지를 생성하기 위해 세 가지 구성 요소로 이루어진 퐁 조명 모델이 사용되었습니다:
- 방향성 광원 - 노란색(1.0, 0.95, 0.8), 방향(0.5, -0.8, 0.3);
- 주변 조명 - 회색(0.55, 0.55, 0.55)이며 그림자 영역의 가시성을 높이기 위해 강도를 높였습니다;
- 디퓨즈 재질 - 정점 색상과의 올바른 혼합을 위해 흰색(1.0, 1.0, 1.0, 1.0)을 사용합니다.
피처 구현
비동기 이벤트 처리:
- 마우스 커서 움직임 및 휠 회전에 대한 반응 - 프로그램은 OnChartEvent() 함수 호출을 수신하고 즉시 이를 처리합니다(3D 모델의 방향, 크기 등이 변경됨). 복잡한 계산은 필요하지 않습니다.
- 모드 전환 버튼을 누르는 것에 대한 반응 - 프로그램은 OnChartEvent() 함수 호출을 수신하고 need_rebuild 플래그를 설정합니다. 기존 메시를 파괴하고 새로운 3D 표면을 생성하여 렌더링하는 BuildSurface() 함수는 50ms마다 need_rebuild 플래그의 상태를 확인하는 OnTimer() 핸들러 함수 내에서 호출됩니다.
이러한 접근 방식을 통해 CPU 리소스가 소모되더라도 3D 모델을 다시 계산하는 데 터미널 차트와 컨트롤이 항상 완벽하게 반응하도록 유지할 수 있습니다.
MQL5\Include\Canvas\DX\DXMath.mqh 라이브러리는 조명 및 카메라 방향을 정확하게 계산하는 데 사용됩니다:
- 법선 벡터 - 표면의 각 정점에 대해 DXVec3Cross() 벡터곱 함수를 사용하여 법선 벡터가 계산됩니다. 이는 표면에 입체감이 생기고 광원에 반응하여 사실적인 그림자와 하이라이트를 만들어내기 위해 필요합니다.
- 카메라 - 관찰자의 위치는 구면 좌표계를 사용하여 계산되므로 카메라가 뒤집히는 효과 없이 수직 각도를 제한하며 물체 주위를 직관적으로 회전(궤도)할 수 있습니다.
EA의 전체 코드는 첨부된 DX_OptimizationSurface.mq5 파일에 포함되어 있습니다.
EA가 다양한 모드에서 수행하는 작업의 예는 아래 그림에 나와 있습니다:
그림 4. 수익 모드
그림 5. 노이즈 모드
이제 우리는 모든 도구를 갖추었습니다: 장면을 구성하고 최적화 데이터를 채우고 사용자가 회전 및 확대/축소를 통해 이 데이터를 탐색할 수 있도록 할 수 있습니다. 하지만 3D 기술을 모든 곳에 서둘러 도입하기 전에 이 기술이 불필요한 곳과 기존 그래프를 고수하는 것이 더 나은 곳을 먼저 살펴보겠습니다.
일반 그래프를 사용하는 것이 더 나은 경우는 언제일까요?
도구는 이전 도구보다 문제를 더 빠르고 정확하게 해결할 때만 유용합니다. 우리는 DX 파이프라인 아키텍처를 살펴보고 표면을 생성하는 방법과 카메라를 제어하는 방법을 배웠습니다. 하지만 트레이딩을 할 때는 유용한 분석적 시각화와 시각적 잡음의 혼돈을 구분해야 합니다. MetaTrader 5에 3D 그래픽을 통합하는 것은 그 자체가 목적이 아니라 문제를 해결하는 방법입니다. 3D 방식을 포기하고 기존의 2D 방식을 선택하는 것이 기술적, 경제적으로 타당한 경우를 살펴보겠습니다.
데이터 차원 규칙
3D 시각화의 필요성에 대한 규칙을 만들어 봅시다: 세 번째 차원은 반드시 고유한 정보를 담고 있어야 합니다.
- 3D는 시계열 데이터(가격/시간)를 3D 공간에 표시하려는 경우에는 쓸모가 없습니다. 가격이나 시간을 복제하는 Z축을 추가하면 인식이 복잡 해져 트레이더는 일반 추세선을 보기 위해 화면을 회전해야 할 뿐입니다.
- 최적화 결과를 분석할 때는 3D가 필요합니다. 여기 우리에게 두 개의 독립적인 입력값(예: 이동평균 기간과 손절매 규모)과 하나의 출력 지표(수익 또는 profit factor)가 있습니다. 3D 표면이 없다면 우리는 단지 점들의 집합만 보게 될 것입니다. 3D는 두 변수와 그 결과 사이의 관계를 파악할 수 있게 해줍니다.
데이터 세트가 두 좌표 쌍으로 요약되는 경우 일반적인 2D 그래프(DRAW_LINE, DRAW_HISTOGRAM)를 사용하는 것이 더 효율적입니다.
하드웨어 제한 및 VPS
MQL5의 3D 그래픽은 DirectX 11을 기반으로 합니다. 이를 위해서는 셰이더 모델 5.0 지원과 일정 수준의 CPU/GPU 성능이 필요합니다.
대부분의 전문 개발자는 가상 사설 서버(VPS)에서 EA를 실행합니다. 일반적인 VPS에는 고성능 그래픽 카드나 DirectX 하드웨어 가속 기능이 없는 경우가 많습니다. 이러한 환경에서는 CreateBitmapLabel()을 호출하면 EA 오류가 발생하거나 프로그램이 충돌할 수 있습니다.
따라서 여러분의 프로그램이 그래픽 없이 또는 저사양 서버에서 실행되는 "블라인드 모드"로 설계되었다면 3D 모듈을 비활성화하거나 파일/데이터베이스에 로깅하는 것으로 대체해야 합니다. 2D 그래픽은 비디오 카드가 없더라도 CPU로 쉽게 렌더링할 수 있습니다.
인지 속도 — 3D 표면과 히트맵 비교
3D 표면을 대체할 수 있는 주요 방법 중 하나는 2차원 히트맵(HeatMap)입니다. 둘 사이의 근본적인 차이점은 다음과 같습니다:
- 3D - 높이(Z)를 물리적 고도로 나타냅니다. 모든 면과 숨겨진 경사면을 정확하게 분석하려면 회전이 필요합니다.
- 히트맵 — (X, Y) 평면에서 셀의 색상으로 (Z) 값을 보여줍니다.
최적의 상태(가장 녹색인 영역)를 빠르게 찾는 것이 목표라면 표준 지표의 히트맵이 더 빠르고 코드도 적게 필요합니다.
상호 작용 vs 모니터링
반응형 3D 장면(우리의 DX_OptimizationSurface EA와 같은)은 사람의 적극적인 참여를 필요로 합니다. 여러분은 마우스 커서를 그 위에 올려놓고 버튼을 누른 상태로 회전시켜야 합니다.
차트의 목적이 모니터링(상황에 대한 백그라운드 추적)이라면 반응형 3D 그래픽은 주의를 산만하게 하고 프로세스를 지연시킬 수 있습니다.
전략 실행 전 프레젠테이션이나 심층 분석이 목표라면 3D 기술은 필수적입니다.
결론:
데이터의 양이나 구조 때문에 2D 분석이 불가능한 경우에만 3D 분석을 사용하십시오. 최적화 표에서 최댓값을 빠르게 찾는 것이 목표라면 히트맵이 더 효과적일 것입니다. 3D는 단순히 값만이 아니라 관계의 형태를 파악해야 할 때 필요합니다.
다른 경우에는 표준 MQL5 클래스(2D 또는 그래픽 객체용 CCanvas)가 더 간단한 해결책이 될 수 있습니다.
결론
우리는 3D 그래픽의 필요성을 이론적으로 정당화하는 단계에서 부터 완전한 기능을 갖춘 반응형 EA를 제작하는 단계까지 살펴보았습니다. DX_OptimizationSurface EA는 MetaTrader 5가 단순히 주문을 실행하는 터미널이 아니라 강력한 시각적 데이터를 분석하는 플랫폼임을 보여줍니다.
주요 결과:
- 인지 효율성 – 3D 시각화는 무수히 많은 숫자를 시각적으로 해석 가능한 풍경으로 변환할 수 있게 해줍니다. 이는 트레이더의 인지적 부담을 줄여 줌으로 해서 안정적인 수익 구간과 위험한 과적합 바늘을 시각적으로 구분할 수 있게 해줍니다.
- 기술적 접근성 – 내장된 DirectX 11 지원과 네이티브 CCanvas3D 및 CDXMesh 클래스는 개발자에게 트레이딩의 문제를 해결하는 데 필요한 도구를 제공합니다. C++ 코드를 작성하거나 외부 라이브러리를 포함할 필요가 없습니다 - 모든 것이 MQL5 내부에 이미 포함되어 있습니다. 이제 남은 건 이 기회를 활용하는 것입니다.
- 아키텍처의 중요성 — 앞에서 살펴본 바와 같이 그래픽을 통합하려면 리소스 수명 주기와 비동기성에 세심한 주의를 기울여야 합니다. 연산 작업을 타이머로 옮기고 메모리를 적절히 정리하면 터미널 성능 문제가 발생하지 않을 것이라는 보장이 됩니다.
시각화는 장식이 아니라 렌즈와 같은 것이고 특정한 분석적 질문에 답해야 합니다.
우리는 겉보기를 위해서가 아니라 의사결정 과정을 신속하게 진행하기 위해 이 도구를 개발했습니다. 3D 그래픽을 통해 여러분이 전략의 작동 방식을 빠르게 이해하고 실행 불가능한 옵션을 걸러낼 수 있다면 3D 그래픽은 제 역할을 다한 것입니다. 그런데 만약 그것이 단지 집중을 방해하는 요소라면 검증된 2D 방식으로 돌아가셔도 좋습니다. 도구의 가치는 어떻게 보이는지 때문이 아니라 그 도구가 의사 결정을 빠르게 하는 데 도움을 주기 때문입니다.
다음 단계 - 이 주제에 대해 더 자세히 알아보고 싶은 분들을 위해 다음을 추천합니다:
- 쿼터니언 및 복소수 변환 작업을 위한 DXMath 라이브러리.
- 독창적인 렌더링 효과를 구현하기 위해 사용자 정의 셰이더(HLSL) 개발.
- 터미널에서 데이터를 시각화하기 전에 데이터를 사전 처리하기 위해 MetaTrader 5를 통해 Python과 통합.
MetaTrader 5는 기술적 기반을 제공합니다. 그 위에 구축하는 분석 도구는 오로지 여러분의 상상력과 끝없는 시장 데이터 속에서 "보석"을 찾아내려는 욕구에 달려 있는 것입니다.
MetaTrader 5에서 DirectX를 사용하는 방법을 배우는 데 추천하는 자료:
- MetaEditor DirectX 도움말,
- MetaTrader 5에서 DirectX를 사용하여 3D 그래픽을 만드는 방법
- DirectX 튜토리얼 (1부): 첫 번째 삼각형 그리기,
- MetaTrader 5 테스터에서 전략 시각화.
첨부된 파일 목록:
| 파일 이름 | 설명 |
|---|---|
| DX_OptimizationSurface.mq5 | 반응형 3D 시각화 기능을 갖춘 테스트 EA 코드가 포함된 파일 |
MetaQuotes 소프트웨어 사를 통해 러시아어가 번역됨.
원본 기고글: https://www.mql5.com/ru/articles/22393
경고: 이 자료들에 대한 모든 권한은 MetaQuotes(MetaQuotes Ltd.)에 있습니다. 이 자료들의 전부 또는 일부에 대한 복제 및 재출력은 금지됩니다.
새로운 기능: MQL5의 커스텀 인디케이터
가장 강력한 머신러닝 기반의 트레이딩 플랫폼은 어떻게 구축 된 것인가: 아카이브, 포럼 및 릴리스를 통해 살펴본 MQL과 MetaTrader의 진화
새 MetaTrader 와 MQL5를 소개해드립니다
MetaTrader 5: 전략에 맞게 시장을 구축하기 — 렌코/레인지/볼륨, 합성 상품 그리고 사용자 맞춤형 심볼 스트레스 테스트
와, 이거 진짜 멋지네요! 고마워요. 한번 분해해 볼게요...
대단해..........