파이썬, ONNX 및 MetaTrader 5: RobustScaler 및 PolynomialFeatures 데이터 전처리를 사용하여 RandomForest 모델 만들기
어떤 기반을 사용할 예정인가요? 랜덤 포레스트란 무엇인가요?
랜덤 포레스트 메서드의 개발 역사는 오래 전으로 거슬러 올라가며 머신 러닝 및 통계 분야의 저명한 과학자들의 연구와 연결되어 있습니다. 이 메서드의 원리와 적용을 더 잘 이해하기 위해 함께 일하는 거대한 그룹(의사 결정 트리)으로 상상해 보겠습니다.
랜덤 포레스트 방식은 의사 결정 트리에 뿌리를 두고 있습니다. 의사 결정 트리는 의사 결정 알고리즘의 그래픽적인 표현으로 각 노드는 속성 중 하나에 대한 테스트를 나타내고 각각의 가지는 해당 테스트의 결과이며 잎은 예측된 결과입니다. 의사 결정 트리는 20세기 중반에 개발되어 널리 사용되는 분류 및 회귀 도구가 되었으며
그 발전에서 중요한 단계는 1996년 레오 브레이먼이 제안한 배깅(부트스트랩 애그리게이팅)이라는 개념입니다. 배깅은 학습 데이터 세트를 여러 부트 스트랩 샘플(하위 샘플)로 분할하고 그 각각에서 별도의 모델을 학습하는 것을 의미합니다. 그런 다음 모델의 결과를 평균화 하거나 결합하여 보다 강력하고 정확한 예측을 생성합니다. 이 방법은 모델 편차를 줄이고 일반화 능력을 향상시켰습니다.
랜덤 포레스트 방식은 2000년대 초 레오 브레이만과 아델 커틀러가 제안한 방식입니다. 이는 배깅과 추가 무작위성을 사용하여 여러 의사 결정 트리를 결합하는 아이디어를 기반으로 합니다. 각 트리는 학습 데이터 세트의 무작위 하위 샘플로 구축되며 트리의 각 노드를 구축할 때 무작위 기능 세트가 선택됩니다. 이렇게 하면 각 트리가 고유해지고 트리 간의 상관관계가 줄어들어 일반화의 능력이 향상됩니다.
랜덤 포레스트는 높은 성능과 분류 및 회귀 문제를 모두 처리할 수 있는 능력으로 인해 머신 러닝 분야에서 가장 인기 있는 방법 중 하나로 빠르게 자리 잡았으며 분류 문제에서는 객체가 속한 클래스를 결정하는 데 사용되며 회귀 문제에서는 숫자 값을 예측하는 데 사용됩니다.
오늘날 랜덤 포레스트는 금융, 의료, 데이터 분석 등 다양한 분야에서 널리 사용되고 있으며 견고함과 복잡한 머신 러닝 문제를 처리하는 능력으로 높이 평가받고 있습니다.
랜덤 포레스트는 머신러닝 툴킷의 강력한 도구입니다. 어떻게 작동하는지 더 잘 이해하기 위해 거대한 그룹이 함께 모여 집단적인 의사 결정을 내리는 것으로 시각화해 보겠습니다. 그러나 이 그룹의 각 구성원은 실제 사람이 아니라 현재 상황을 독립적으로 분류하거나 예측하는 역할을 합니다. 이 그룹 내에서 사람은 특정 속성을 기반으로 의사 결정을 내릴 수 있는 의사 결정 트리입니다. 랜덤 포레스트는 의사 결정을 내릴 때 민주주의와 투표를 사용합니다. 각 나무가 의견을 표현하고 결정은 다수의 투표를 바탕으로 내려집니다.
랜덤 포레스트는 다양한 분야에서 널리 사용되고 있으며 그 유연성으로 인해 분류 및 회귀 문제 모두에 적합합니다. 분류 작업에서 모델은 현재 상태가 미리 정의된 클래스 중 어느 클래스에 속하는지 결정합니다. 예를 들어 금융 시장에서는 다양한 지표를 바탕으로 자산을 매수(1등급)하거나 매도(0등급)하는 결정을 내리는 것을 의미할 수 있습니다.
하지만 이 글에서 우리는 회귀 문제에 초점을 맞추겠습니다. 머신 러닝의 회귀는 과거의 값을 기반으로 시계열의 미래의 수치를 예측하려는 시도입니다. 객체를 특정 클래스에 할당하는 분류 대신 회귀에서는 특정 숫자를 예측하는 것을 목표로 합니다. 예를 들어 주가 예측, 기온 예측 또는 기타 수치 변수를 예측할 수 있습니다.
기본 RF 모델 만들기
기본 랜덤 포레스트 모델을 만들기 위해 Python의 sklearn(Scikit-learn) 라이브러리를 사용하겠습니다. 다음은 랜덤 포레스트 회귀 모델을 학습하기 위한 간단한 코드 템플릿입니다. 이 코드를 실행하기 전에 Python 패키지 설치 도구를 사용하여 sklearn을 실행하는 데 필요한 라이브러리를 설치해야 합니다.
pip install onnx
pip install skl2onnx
pip install MetaTrader5
다음으로 라이브러리를 가져오고 매개변수를 설정해야 합니다. 데이터 작업을 위한 'pandas', Google 드라이브에서 데이터를 로드하기 위한 'gdown', 데이터 처리 및 랜덤 포레스트 모델 생성을 위한 라이브러리 등 필요한 라이브러리를 가져옵니다. 또한 데이터 시퀀스의 시간 단계 수(n_step)를 설정해야 하는데 이는 특정한 요구사항에 따라 결정됩니다:
import pandas as pd import gdown import numpy as np import joblib import random import onnx import os import shutil from sklearn.ensemble import RandomForestRegressor from sklearn.metrics import mean_squared_error, r2_score from sklearn.utils import shuffle from skl2onnx import convert_sklearn from skl2onnx.common.data_types import FloatTensorType from sklearn.pipeline import Pipeline from sklearn.preprocessing import RobustScaler, MinMaxScaler, PolynomialFeatures, PowerTransformer import MetaTrader5 as mt5 from datetime import datetime # Set the number of time steps according to requirements n_steps = 100
다음 단계에서는 데이터를 로드하고 처리합니다. 구체적인 예시에서 우리는 MetaTrader 5에서 가격 데이터를 로드 하여 처리합니다. 시간 지수를 설정하고 종가만 선택합니다(이 가격으로 작업할 것입니다):
다음은 데이터를 학습 세트와 테스트 세트로 분할하고 모델 학습을 위해 세트에 레이블을 지정하는 코드의 일부입니다. 데이터를 학습 세트와 테스트 세트로 나눕니다. 그런 다음 회귀를 위해 데이터에 레이블을 지정하는데 이는 각 레이블이 실제의 미래 가격 가치를 나타낸다는 의미입니다. labelling_relabeling_regression 함수는 레이블링된 데이터를 생성하는 데 사용됩니다.mt5.initialize() SYMBOL = 'EURUSD' TIMEFRAME = mt5.TIMEFRAME_H1 START_DATE = datetime(2000, 1, 1) STOP_DATE = datetime(2023, 1, 1) # Set the number of time steps according to your requirements n_steps = 100 # Process data data = pd.DataFrame(mt5.copy_rates_range(SYMBOL, TIMEFRAME, START_DATE, STOP_DATE), columns=['time', 'close']).set_index('time') data.index = pd.to_datetime(data.index, unit='s') data = data.dropna() data = data[['close']] # Work only with close prices
# Define train_data_initial training_size = int(len(data) * 0.70) train_data_initial = data.iloc[:training_size] test_data_initial = data.iloc[training_size:] # Function for creating and assigning labels for regression (changes made for regression, not classification) def labelling_relabeling_regression(dataset, min_value=1, max_value=1): future_prices = [] for i in range(dataset.shape[0] - max_value): rand = random.randint(min_value, max_value) future_pr = dataset['<CLOSE>'].iloc[i + rand] future_prices.append(future_pr) dataset = dataset.iloc[:len(future_prices)].copy() dataset['future_price'] = future_prices return dataset # Apply the labelling_relabeling_regression function to raw data to get labeled data train_data_labeled = labelling_relabeling_regression(train_data_initial) test_data_labeled = labelling_relabeling_regression(test_data_initial)
다음으로 특정 시퀀스에서 학습 데이터 세트를 생성합니다. 중요한 것은 모델이 시퀀스의 모든 종가를 피처로 사용한다는 것입니다. ONNX 모델에 입력된 데이터의 사이즈와 동일한 시퀀스 사이즈가 사용됩니다. 이 단계에서는 정규화가 없습니다; 모델 파이프라인 작업의 일부로 학습 파이프라인에서 수행됩니다.
# Create datasets of features and target variables for training x_train = np.array([train_data_labeled['<CLOSE>'].iloc[i - n_steps:i].values[-n_steps:] for i in range(n_steps, len(train_data_labeled))]) y_train = train_data_labeled['future_price'].iloc[n_steps:].values # Create datasets of features and target variables for testing x_test = np.array([test_data_labeled['<CLOSE>'].iloc[i - n_steps:i].values[-n_steps:] for i in range(n_steps, len(test_data_labeled))]) y_test = test_data_labeled['future_price'].iloc[n_steps:].values # After creating x_train and x_test, define n_features as follows: n_features = x_train.shape[1] # Now use n_features to determine the ONNX input data type initial_type = [('float_input', FloatTensorType([None, n_features]))]
데이터 전처리를 위한 파이프라인 만들기
다음 단계는 랜덤 포레스트 모델을 만드는 것입니다. 이 모델은 파이프라인으로 구축해야 합니다.
스킷-런(scikit-learn, sklearn) 라이브러리의 파이프라인은 데이터 분석 및 머신 러닝을 위한 순차적인 변환 및 모델 체인을 만드는 메서드입니다. 파이프라인을 사용하면 여러 데이터 처리 및 모델링 단계를 단일 객체로 결합하여 데이터를 효율적이고 순차적으로 작업할 수 있도록 해줍니다.
코드 예제에서 우리는 다음과 같은 파이프라인을 생성합니다:
# Create a pipeline with MinMaxScaler, RobustScaler, PolynomialFeatures and RandomForestRegressor
pipeline = Pipeline([
('MinMaxScaler', MinMaxScaler()),
('robust', RobustScaler()),
('poly', PolynomialFeatures()),
('rf', RandomForestRegressor(
n_estimators=20,
max_depth=20,
min_samples_split=5000,
min_samples_leaf=5000,
random_state=1,
verbose=2
))
])
# Train the pipeline
pipeline.fit(x_train, y_train)
# Make predictions
predictions = pipeline.predict(x_test)
# Evaluate model using R2
r2 = r2_score(y_test, predictions)
print(f'R2 score: {r2}')
보시다시피 파이프라인은 데이터 처리 및 모델링 단계가 하나의 체인으로 결합된 일련의 데이터 처리 및 모델링 단계입니다. 이 코드에서는 scikit-learn 라이브러리를 사용하여 파이프라인을 생성합니다. 여기에는 다음과 같은 단계가 포함됩니다:
-
MinMaxScaler는 데이터를 0에서 1 범위로 스케일링 합니다. 이는 모든 기능이 동일한 스케일로 표시되도록 하는 데 유용합니다.
-
RobustScaler도 데이터 스케일링을 수행하지만 데이터 세트의 이상값에 대해 더 강력합니다. 중앙값 및 사 분위수 범위를 사용하여 배율을 조정합니다.
-
PolynomialFeatures는 피처에 다항식 변환을 적용합니다. 이렇게 하면 모델이 데이터의 비선형 관계를 설명하는 데 도움이 되는 다항식 기능이 추가됩니다.
-
랜덤 포레스트 레귤레이터는 하이퍼파라미터 집합으로 랜덤 포레스트 모델을 정의합니다:
- n_estimators(숲의 나무 수). 금융 시장의 가격 예측을 전문으로 하는 전문가 그룹이 있다고 가정해 보겠습니다. 무작위 포레스트의 나무 수(n_estimators)에 따라 그룹에 이러한 전문가가 몇 명 포함될지를 결정됩니다. 트리가 많을수록 모델이 결정을 내릴 때 더 다양한 의견과 예측을 고려할 수 있습니다.
- max_depth(각 트리의 최대 깊이). 이 매개 변수는 각 전문가(트리)가 데이터 분석에 얼마나 깊이 '뛰어들 수 있는지를 설정합니다. 예를 들어 최대 깊이를 20으로 설정하면 각 트리는 20개 이하의 기능 또는 특성을 기반으로 의사 결정을 내립니다.
- min_samples_split(트리 노드를 분할할 최소 샘플 수). 이 매개변수는 트리를 계속 작은 노드로 나누기 위해 트리 노드에 얼마나 많은 샘플(관측)이 있어야 하는지를 알려줍니다. 예를 들어 분할할 최소 샘플 수를 5000개로 설정하면 트리는 노드당 5000개 이상의 관측값이 있는 경우에만 노드를 분할합니다.
- min_samples_leaf(트리 리프 노드에 있는 최소 샘플 수). 이 매개변수는 트리의 리프 노드에 얼마나 많은 샘플이 있어야 해당 노드가 리프가 되고 더 이상 분할되지 않는지를 결정합니다. 예를 들어 리프 노드의 최소 샘플 수를 5000개로 설정하면 트리의 각 리프에 최소 5000개의 관측값이 포함됩니다.
- random_state(무작위 생성을 위한 초기 상태를 설정하여 재현 가능한 결과를 보장합니다). 이 파라미터는 모델 내 무작위 프로세스를 제어하는 데 사용됩니다. 고정 값(예: 1)으로 설정하면 모델을 실행할 때마다 결과가 동일합니다. 이는 결과의 재현성을 높이는 데 유용합니다.
- verbose(모델 학습 과정에 대한 정보를 출력할 수 있게 합니다). 모델을 학습시킬 때 프로세스에 대한 정보를 확인하는 것이 유용할 수 있습니다. 'verbose' 매개변수를 사용하면 여러분은 이 정보의 세부 수준을 제어할 수 있습니다. 값이 높을수록(예: 2) 학습 과정에서 더 많은 정보가 출력됩니다.
파이프라인을 생성한 후에는 'fit' 메서드를 사용하여 학습 데이터에 대해 학습합니다. 그런 다음 'predict' 메서드를 사용하여 테스트 데이터에 대한 예측을 수행합니다. 마지막으로 데이터에 대한 모델의 적합도를 측정하는 R2 메트릭을 사용하여 모델의 품질을 평가합니다.
파이프라인을 학습한 다음 R2 메트릭에 대해 평가합니다. 정규화를 사용하여 데이터에서 이상값을 제거하고 다항식 피처를 생성합니다. 이렇게 하는 것이 가장 간단한 데이터 전처리 방법입니다. 다음 글에서는 함수 트랜스포머를 사용하여 여러분 자신만의 전처리 함수를 만드는 방법에 대해 살펴보겠습니다.
ONNX로 모델 내보내기, 내보내기 함수 작성하기
파이프라인을 학습한 후에는 skl2onnx 라이브러리를 사용하여 joblib 형식으로 저장하고 이를 ONNX 형식으로 저장합니다.
# Save the pipeline
joblib.dump(pipeline, 'rf_pipeline.joblib')
# Convert pipeline to ONNX
onnx_model = convert_sklearn(pipeline, initial_types=initial_type)
# Save the model in ONNX format
model_onnx_path = "rf_pipeline.onnx"
onnx.save_model(onnx_model, model_onnx_path)
# Save the model in ONNX format
model_onnx_path = "rf_pipeline.onnx"
onnx.save_model(onnx_model, model_onnx_path)
# Connect Google Drive (if you work in Colab and this is necessary)
from google.colab import drive
drive.mount('/content/drive')
# Specify the path to Google Drive where you want to move the model
drive_path = '/content/drive/My Drive/' # Make sure the path is correct
rf_pipeline_onnx_drive_path = os.path.join(drive_path, 'rf_pipeline.onnx')
# Move ONNX model to Google Drive
shutil.move(model_onnx_path, rf_pipeline_onnx_drive_path)
print('The rf_pipeline model is saved in the ONNX format on Google Drive:', rf_pipeline_onnx_drive_path)
이것이 우리가 모델을 학습시키고 ONNX에 저장하는 방법입니다. 학습을 완료하면 다음과 같은 내용을 확인할 수 있습니다:

모델은 Google 드라이브의 기본 디렉터리에 ONNX 형식으로 저장됩니다. ONNX는 머신 러닝 모델을 위한 일종의 '플로피 디스크'로 생각할 수 있습니다. 이 형식을 사용하면 학습된 모델을 저장하고 다양한 애플리케이션에서 사용할 수 있도록 변환할 수 있습니다. 이는 플래시 드라이브에 파일을 저장한 다음 다른 장치에서 읽을 수 있는 방식과 같습니다. 우리의 경우 ONNX 모델은 MetaTrader 5 환경에서 금융 시장 가격을 예측하는 데 사용됩니다. ONNX "플로피 디스크"는 MetaTrader 5와 같은 타사 애플리케이션에서 읽을 수 있습니다. 이것이 바로 지금 우리가 할 일입니다.
MetaTrader 5 테스터에서 모델 확인
이전에 ONNX 모델을 Google 드라이브에 저장했습니다. 이제 거기에서 다운로드해 보겠습니다. MetaTrader 5에서 이 모델을 사용하기 위해 이 모델을 읽고 매매 결정에 적용할 EA를 만들어 보겠습니다. 제시된 MetaTrader 코드에서 랏 거래량, 손절 주문 사용, 이익실현 및 손절매 수준과 같은 거래와 관련한 매개변수를 설정합니다. 다음은 ONNX 모델을 '읽는' EA의 코드입니다:
//+------------------------------------------------------------------+ //| ONNX Random Forest.mq5 | //| Copyright 2023 | //| Evgeniy Koshtenko | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, Evgeniy Koshtenko" #property link "https://www.mql5.com" #property version "0.90" static vectorf ExtOutputData(1); vectorf output_data(1); #include <Trade\Trade.mqh> CTrade trade; input double InpLots = 1.0; // Lot volume to open a position input bool InpUseStops = true; // Trade with stop orders input int InpTakeProfit = 500; // Take Profit level input int InpStopLoss = 500; // Stop Loss level #resource "Python/rf_pipeline.onnx" as uchar ExtModel[] #define SAMPLE_SIZE 100 long ExtHandle=INVALID_HANDLE; int ExtPredictedClass=-1; datetime ExtNextBar=0; datetime ExtNextDay=0; CTrade ExtTrade; #define PRICE_UP 1 #define PRICE_SAME 2 #define PRICE_DOWN 0 // Function for closing all positions void CloseAll(int type=-1) { for(int i=PositionsTotal()-1; i>=0; i--) { if(PositionSelectByTicket(PositionGetTicket(i))) { if(PositionGetInteger(POSITION_TYPE)==type || type==-1) { trade.PositionClose(PositionGetTicket(i)); } } } } // Expert Advisor initialization int OnInit() { if(_Symbol!="EURUSD" || _Period!=PERIOD_H1) { Print("The model should work with EURUSD, H1"); return(INIT_FAILED); } ExtHandle=OnnxCreateFromBuffer(ExtModel,ONNX_DEFAULT); if(ExtHandle==INVALID_HANDLE) { Print("Error creating model OnnxCreateFromBuffer ",GetLastError()); return(INIT_FAILED); } const long input_shape[] = {1,100}; if(!OnnxSetInputShape(ExtHandle,ONNX_DEFAULT,input_shape)) { Print("Error setting the input shape OnnxSetInputShape ",GetLastError()); return(INIT_FAILED); } const long output_shape[] = {1,1}; if(!OnnxSetOutputShape(ExtHandle,0,output_shape)) { Print("Error setting the output shape OnnxSetOutputShape ",GetLastError()); return(INIT_FAILED); } return(INIT_SUCCEEDED); } // Expert Advisor deinitialization void OnDeinit(const int reason) { if(ExtHandle!=INVALID_HANDLE) { OnnxRelease(ExtHandle); ExtHandle=INVALID_HANDLE; } } // Process the tick function void OnTick() { if(TimeCurrent()<ExtNextBar) return; ExtNextBar=TimeCurrent(); ExtNextBar-=ExtNextBar%PeriodSeconds(); ExtNextBar+=PeriodSeconds(); PredictPrice(); if(ExtPredictedClass>=0) if(PositionSelect(_Symbol)) CheckForClose(); else CheckForOpen(); } // Check position opening conditions void CheckForOpen(void) { ENUM_ORDER_TYPE signal=WRONG_VALUE; if(ExtPredictedClass==PRICE_DOWN) signal=ORDER_TYPE_SELL; else { if(ExtPredictedClass==PRICE_UP) signal=ORDER_TYPE_BUY; } if(signal!=WRONG_VALUE && TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) { double price,sl=0,tp=0; double bid=SymbolInfoDouble(_Symbol,SYMBOL_BID); double ask=SymbolInfoDouble(_Symbol,SYMBOL_ASK); if(signal==ORDER_TYPE_SELL) { price=bid; if(InpUseStops) { sl=NormalizeDouble(bid+InpStopLoss*_Point,_Digits); tp=NormalizeDouble(ask-InpTakeProfit*_Point,_Digits); } } else { price=ask; if(InpUseStops) { sl=NormalizeDouble(ask-InpStopLoss*_Point,_Digits); tp=NormalizeDouble(bid+InpTakeProfit*_Point,_Digits); } } ExtTrade.PositionOpen(_Symbol,signal,InpLots,price,sl,tp); } } // Check position closing conditions void CheckForClose(void) { if(InpUseStops) return; bool tsignal=false; long type=PositionGetInteger(POSITION_TYPE); if(type==POSITION_TYPE_BUY && ExtPredictedClass==PRICE_DOWN) tsignal=true; if(type==POSITION_TYPE_SELL && ExtPredictedClass==PRICE_UP) tsignal=true; if(tsignal && TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) { ExtTrade.PositionClose(_Symbol,3); CheckForOpen(); } } // Function to get the current spread double GetSpreadInPips(string symbol) { double spreadPoints = SymbolInfoInteger(symbol, SYMBOL_SPREAD); double spreadPips = spreadPoints * _Point / _Digits; return spreadPips; } // Function to predict prices void PredictPrice() { static vectorf output_data(1); static vectorf x_norm(SAMPLE_SIZE); double spread = GetSpreadInPips(_Symbol); if (!x_norm.CopyRates(_Symbol, _Period, COPY_RATES_CLOSE, 1, SAMPLE_SIZE)) { ExtPredictedClass = -1; return; } if (!OnnxRun(ExtHandle, ONNX_NO_CONVERSION, x_norm, output_data)) { ExtPredictedClass = -1; return; } float predicted = output_data[0]; if (spread < 0.000005 && predicted > iClose(Symbol(), PERIOD_CURRENT, 1)) { ExtPredictedClass = PRICE_UP; } else if (spread < 0.000005 && predicted < iClose(Symbol(), PERIOD_CURRENT, 1)) { ExtPredictedClass = PRICE_DOWN; } else { ExtPredictedClass = PRICE_SAME; } }
다음 입력 차원에 유의하세요:
const long input_shape[] = {1,100};
파이썬 모델의 차원과 일치해야 합니다:
# Set the number of time steps to your requirements n_steps = 100
다음으로 MetaTrader 5 환경에서 모델 테스트를 시작합니다. 모델의 예측을 통해 가격 변동의 방향을 결정합니다. 모델이 가격의 상승을 예측하면 롱 포지션(매수)을 오픈할 준비를 하고 반대로 가격이 하락할 것으로 예측하면 숏 포지션(매도)을 오픈할 준비를 합니다. 익절 1000, 손절 500으로 모델을 테스트해 보겠습니다:

결론
이 글에서는 파이썬에서 랜덤 포레스트 모델을 만들고 훈련하는 방법, 모델 내에서 직접 데이터를 전처리 하는 방법, ONNX 표준으로 내보낸 다음 MetaTrader 5에서 모델을 열고 사용하는 방법에 대해 알아보았습니다.
ONNX는 훌륭한 모델 가져오기-내보내기 시스템이며 보편적이고 간단합니다. ONNX에서 모델을 저장하는 것은 실제로 보기보다 훨씬 쉽습니다. 데이터 전처리도 매우 쉽습니다.
물론 의사 결정 트리가 20개에 불과한 우리의 모델은 매우 단순하며 랜덤 포레스트 모델 자체는 이미 상당히 오래된 솔루션입니다. 다음 글에서는 더 복잡한 데이터 전처리를 사용하여 더 복잡하고 현대적인 모델을 만들어 보겠습니다. 저는 전처리와 동시에 sklearn 파이프라인의 형태로 즉시 모델 앙상블을 만들 수 있다는 점에 주목하고 싶습니다. 이를 통해 분류 문제를 포함하여 우리의 역량을 크게 확장할 수 있습니다.
MetaQuotes 소프트웨어 사를 통해 러시아어가 번역됨.
원본 기고글: https://www.mql5.com/ru/articles/13725
경고: 이 자료들에 대한 모든 권한은 MetaQuotes(MetaQuotes Ltd.)에 있습니다. 이 자료들의 전부 또는 일부에 대한 복제 및 재출력은 금지됩니다.
이 글은 사이트 사용자가 작성했으며 개인의 견해를 반영합니다. Metaquotes Ltd는 제시된 정보의 정확성 또는 설명 된 솔루션, 전략 또는 권장 사항의 사용으로 인한 결과에 대해 책임을 지지 않습니다.
MQL5의 정량적 분석: 유망한 알고리즘 구현하기
HarmonyOS NEXT에 MetaTrader 5 및 기타 MetaQuotes 앱 설치
간단한 예로 숲만 선택했습니다)다음 글에서 설명하겠습니다, 지금은 약간 수정 중입니다)
Good)
컨베이어에 대한 주제를 더 발전시키고 메타트레이더에서 나중에 사용하여 ONNX로 변환하는 것이 흥미로울 것입니다. 예를 들어, 파이프라인에 사용자 지정 변환을 추가할 수 있으며 이러한 파이프라인에서 얻은 ONNX 모델을 메타트레이더에서 열 수 있습니까? 임호, 이 주제는 여러 기사의 가치가 있습니다.
컨베이어에 대한 주제를 더 발전시키고 메타트레이더에서 나중에 사용하여 ONNX로 변환하는 것이 흥미로울 것입니다. 예를 들어, 파이프라인에 사용자 지정 변환을 추가할 수 있으며 이러한 파이프라인에서 얻은 ONNX 모델을 메타트레이더에서 열 수 있습니까? 임호, 이 주제는 여러 기사의 가치가 있습니다.