English Русский 中文 Español Deutsch Português
preview
PythonとMQL5でロボットを開発する(第3回):モデルベース取引アルゴリズムの実装

PythonとMQL5でロボットを開発する(第3回):モデルベース取引アルゴリズムの実装

MetaTrader 5トレーディングシステム | 6 1月 2025, 11:30
424 0
Yevgeniy Koshtenko
Yevgeniy Koshtenko

連載第1回では、データセットのロード、ラベルの配置、データセットのエンリッチ化、そしてデータセットのラベリングをおこないました。第2回は、モデルの作成と訓練、交差検証とバギングの実装に費やされました。 

これでモデルの学習とテストが完了したので、いよいよPython用のMetaTrader 5ライブラリを使って実際の取引を開始します。この強力なライブラリにより、MetaTrader 5プラットフォームが提供する関数やクラスを使用して、Pythonで直接取引を自動化することができます。


モデルベース取引アルゴリズムの実装

モデルに基づく取引アルゴリズムを実装するために、以下のアプローチを使用します。基本的なアルゴリズムは、あらかじめ設定されたストップロスで取引を開始し、モデルによって生成されたラベルに一致する利益を取ることです。モデルが資産価格の上昇を予測した場合、損切りと利食いの水準を設定してロングポジションを建てます。モデルが資産価格の下落を予測した場合、同様の損切りと利食いのパラメータでショートポジションを建てます。

Python用MetaTrader 5ライブラリは、取引の開始と終了を管理し、損切りと利食いのレベルを設定するために必要なツールを提供します。これにより、モデル予測に基づく取引を完全に自動化することができます。

前段階の分析と訓練で得られたデータを使用し、MetaTrader 5プラットフォーム上でポジションを開閉するシグナルをリアルタイムで送信することで、取引アルゴリズムの継続性と正確性を確保します。

したがって、訓練したモデルをPython用MetaTrader 5ライブラリと統合することで、モデルの予測に基づいて取引をおこない、事前に設定したストップロスでリスクを管理し、テイクプロフィットで利益を保護する、効率的な自動取引アルゴリズムを作成することができます。


環境、取引端末のセットアップ、アルゴリズムの実行

まず、環境とMetaTrader 5取引端末をセットアップする必要があります。そのためには、以下の手順に従います。

pipコマンドでPythonライブラリをインストールします。

pip install numpy pandas MetaTrader5 scikit-learn xgboost

端末へのリンクに、端末の実行ファイルへのパスを示します。

terminal_path = "C:/Program Files/RoboForex - MetaTrader 5/Arima/terminal64.exe"


オンライン取引の導入

オンライン取引を実装するために、モデルの予測に従って取引を開始するonline_trading関数を追加します。

online_trading関数は以下の引数を取ります。

  • symbol:取引銘柄
  • features:予測に使用する特徴のリスト
  • model:予測に使用する学習済みモデル

online_trading関数の内部では、まずterminal_pathで指定されたパスを使用してMetaTrader 5端末に接続します。次に、mt5.symbol_info_tick(symbol)関数を使用して、現在の銘柄の価格を取得します。

次に、渡された特徴に基づき、モデルを使ってシグナルを予測します。予想がプラス(0.5以上)の場合はロングポジションを建て、予想がマイナス(0.5未満)の場合はショートポジションを建てます。

また、リスクを最小限に抑えるために、各取引に損切りと利食いを設定します。

すでに未決済取引の最大数(MAX_OPEN_TRADES定数で設定)に達している場合は、新規取引をおこなわず、未決済取引の1つが決済されるまで待ちます。

予想が新規取引を許可しない場合は、新たなシグナルが表示されるまで待ちます。

関数の最後に、取引に成功した場合は約定結果を返し、取引に失敗した場合はNoneを返します。

def online_trading(symbol, features, model):
    terminal_path = "C:/Program Files/RoboForex - MetaTrader 5/Arima/terminal64.exe"

    if not mt5.initialize(path=terminal_path):
        print("Error: Failed to connect to MetaTrader 5 terminal")
        return

    open_trades = 0
    e = None
    attempts = 30000

    while True:
        symbol_info = mt5.symbol_info(symbol)
        if symbol_info is not None:
            break
        else:
            print("Error: Instrument not found. Attempt {} of {}".format(_ + 1, attempts))
            time.sleep(5)

    while True:
        price_bid = mt5.symbol_info_tick(symbol).bid
        price_ask = mt5.symbol_info_tick(symbol).ask

        signal = model.predict(features)

        positions_total = mt5.positions_total()

        for _ in range(attempts):
            if positions_total < MAX_OPEN_TRADES and signal[-1] > 0.5:
                request = {
                    "action": mt5.TRADE_ACTION_DEAL,
                    "symbol": symbol,
                    "volume": 0.3,
                    "type": mt5.ORDER_TYPE_BUY,
                    "price": price_ask,
                    "sl": price_ask - 150 * symbol_info.point,
                    "tp": price_ask + 800 * symbol_info.point,
                    "deviation": 20,
                    "magic": 123456,
                    "comment": "Test deal",
                    "type_time": mt5.ORDER_TIME_GTC,
                    "type_filling": mt5.ORDER_FILLING_FOK,
                }
            elif positions_total < MAX_OPEN_TRADES and signal[-1] < 0.5:
                request = {
                    "action": mt5.TRADE_ACTION_DEAL,
                    "symbol": symbol,
                    "volume": 0.3,
                    "type": mt5.ORDER_TYPE_SELL,
                    "price": price_bid,
                    "sl": price_bid + 150 * symbol_info.point,
                    "tp": price_bid - 800 * symbol_info.point,
                    "deviation": 20,
                    "magic": 123456,
                    "comment": "Test deal",
                    "type_time": mt5.ORDER_TIME_GTC,
                    "type_filling": mt5.ORDER_FILLING_FOK,
                }
            else:
                print("No signal to open a position")
                return None

            result = mt5.order_send(request)

            if result.retcode == mt5.TRADE_RETCODE_DONE:
                if signal[-1] < 0.5:
                    print("Buy position opened")
                    open_trades += 1
                elif signal[-1] > 0.5:
                    print("Sell position opened")
                    open_trades += 1
                return result.order
            else:
                print("Error: Trade request not executed, retcode={}. Attempt {}/{}".format(result.retcode, _ + 1, attempts))
                time.sleep(3)

        time.sleep(4000)

def process_symbol(symbol):
    try:
        # Retrieve data for the specified symbol
        raw_data = retrieve_data(symbol)
        if raw_data is None:
            print("No data found for symbol {}".format(symbol))
            return None

        # Augment data
        augmented_data = augment_data(raw_data)

        # Markup data
        marked_data = markup_data(augmented_data.copy(), 'close', 'label')

        # Label data
        labeled_data = label_data(marked_data, symbol)

        # Generate new features
        labeled_data_generate = generate_new_features(labeled_data, num_features=100, random_seed=1)

        # Cluster features by GMM
        labeled_data_clustered = cluster_features_by_gmm(labeled_data_generate, n_components=4)

        # Feature engineering
        labeled_data_engineered = feature_engineering(labeled_data_clustered, n_features_to_select=10)

        # Train XGBoost classifier
        train_data = labeled_data_engineered[labeled_data_engineered.index <= FORWARD]


オンライン取引アルゴリズムを発表

オンライン取引アルゴリズムを起動するために、process_symbol関数を呼び出し、取引された銘柄を渡します。

process_symbol関数の中で、online_trading関数を呼び出し、必要な引数を渡し、中断されるまで実行するループを開始します。

ループの最後には、MetaTrader 5端末に過負荷をかけないように、6秒間の休止を設けます。

アルゴリズム実行中にエラーが発生した場合は、エラーメッセージを表示し、実行を中断します。


インテリジェントなリスクおよびドローダウン管理システム

リスク管理は成功する取引戦略の要です。トレーダーが直面する主なリスクのひとつは、資産価格が所定の水準を下回るドローダウンのリスクです。このリスクを最小化するためには、市場環境の変化に対応できる効果的なリスク管理システムが必要です。

Python用MetaTrader 5ライブラリのツールを使って、口座残高が減ると自動的に取引量が減るシステムを開発します。

システムの基本ルール

  1. 当座預金残高の日次検索:毎日、当座預金残高を検索し、その変化を分析します。

  2. ドローダウン中に取引量を減らす:残高が1日に2%以上減少した場合、システムは自動的にオープンした取引量を10%減らします。これは0.01ロット単位でおこなわれ、徐々にリスクを減らしていきます。

  3. 残高の減少に伴う取引量の追加削減:残高の減少が続く場合、取引量は毎日さらに10%、0.01ロットずつ削減され、さらなる資本保護が保証されます。

  4. 残高回復後に元の取引量に戻す:現在の口座残高が以前のピークを超えると、システムは自動的に取引量を元の値に戻します。これは、ドローダウンによる一時的な出来高減少の後、完全な取引活動を回復するのに役立ちます。

online_trading関数に新しい変数が追加されました(account_balance:現在の残高を保存、peak_balance:前回のピーク残高レベルを保存、daily_drop:毎日のドローダウンを追跡)。これらの変数は、リスク管理ロジックの実装に使用されます。

サンプルコード

def online_trading(symbol, features, model):
    terminal_path = "C:/Program Files/RoboForex - MetaTrader 5/Arima/terminal64.exe"

    if not mt5.initialize(path=terminal_path):
        print("Error: Failed to connect to MetaTrader 5 terminal")
        return

    open_trades = 0
    e = None
    attempts = 30000

    # Get the current account balance
    account_info = mt5.account_info()
    account_balance = account_info.balance

    # Set the initial volume for opening trades
    volume = 0.3

    # Set the initial peak balance
    peak_balance = account_balance

    while True:
        symbol_info = mt5.symbol_info(symbol)
        if symbol_info is not None:
            break
        else:
            print("Error: Instrument not found. Attempt {} of {}".format(_ + 1, attempts))
            time.sleep(5)

    while True:
        price_bid = mt5.symbol_info_tick(symbol).bid
        price_ask = mt5.symbol_info_tick(symbol).ask

        signal = model.predict(features)

        positions_total = mt5.positions_total()

        # Calculate the daily drop in account balance
        account_info = mt5.account_info()
        current_balance = account_info.balance
        daily_drop = (account_balance - current_balance) / account_balance

        # Reduce the volume for opening trades by 10% with a step of 0.01 lot for each day of daily drop
        if daily_drop > 0.02:
            volume -= 0.01
            volume = max(volume, 0.01)
        elif current_balance > peak_balance:
            volume = 0.3
            peak_balance = current_balance

        for _ in range(attempts):
            if positions_total < MAX_OPEN_TRADES and signal[-1] > 0.5:
                request = {
                    "action": mt5.TRADE_ACTION_DEAL,
                    "symbol": symbol,
                    "volume": volume,
                    "type": mt5.ORDER_TYPE_BUY,
                    "price": price_ask,
                    "sl": price_ask - 150 * symbol_info.point,
                    "tp": price_ask + 800 * symbol_info.point,
                    "deviation": 20,
                    "magic": 123456,
                    "comment": "Test deal",
                    "type_time": mt5.ORDER_TIME_GTC,
                    "type_filling": mt5.ORDER_FILLING_FOK,
                }
            elif positions_total < MAX_OPEN_TRADES and signal[-1] < 0.5:
                request = {
                    "action": mt5.TRADE_ACTION_DEAL,
                    "symbol": symbol,
                    "volume": volume,
                    "type": mt5.ORDER_TYPE_SELL,
                    "price": price_bid,
                    "sl": price_bid + 150 * symbol_info.point,
                    "tp": price_bid - 800 * symbol_info.point,
                    "deviation": 20,
                    "magic": 123456,
                    "comment": "Test deal",
                    "type_time": mt5.ORDER_TIME_GTC,
                    "type_filling": mt5.ORDER_FILLING_FOK,
                }
            else:
                print("No signal to open a position")
                return None

            result = mt5.order_send(request)

            if result.retcode == mt5.TRADE_RETCODE_DONE:
                if signal[-1] < 0.5:
                    print("Buy position opened")
                    open_trades += 1
                elif signal[-1] > 0.5:
                    print("Sell position opened")
                    open_trades += 1
                return result.order
            else:
                print("Error: Trade request not executed, retcode={}. Attempt {}/{}".format(result.retcode, _ + 1, attempts))
                time.sleep(3)

        time.sleep(4000)


ケリー基準に基づくロット管理の実施

ロットサイズ管理は、取引におけるリスク管理のもう一つの重要な側面です。ロット密度をコントロールする一般的な方法のひとつに、ケリー基準があります。ケリー基準は、勝率と勝敗比率から最適なベットサイズを決定する数学的方程式です。

ここでは、ケリーロットサイズ管理をリスク管理システムに導入する方法を見ていきます。モデルの予測値と0.5との距離を勝率とします。モデルの予測が0.5に近ければ近いほど、勝つ確率は低くなり、ベットサイズは小さくなるはずです。

修正したonline_trading関数は以下のようになります。

def online_trading(symbol, features, model):
    terminal_path = "C:/Program Files/RoboForex - MetaTrader 5/Arima/terminal64.exe"

    if not mt5.initialize(path=terminal_path):
        print("Error: Failed to connect to MetaTrader 5 terminal")
        return

    open_trades = 0
    e = None
    attempts = 30000

    # Get the current account balance
    account_info = mt5.account_info()
    account_balance = account_info.balance

    # Set the initial volume for opening trades
    volume = 0.1

    # Set the initial peak balance
    peak_balance = account_balance

    while True:
        symbol_info = mt5.symbol_info(symbol)
        if symbol_info is not None:
            break
        else:
            print("Error: Instrument not found. Attempt {} of {}".format(_ + 1, attempts))
            time.sleep(5)

    while True:
        price_bid = mt5.symbol_info_tick(symbol).bid
        price_ask = mt5.symbol_info_tick(symbol).ask

        signal = model.predict(features)

        positions_total = mt5.positions_total()

        # Calculate the daily drop in account balance
        account_info = mt5.account_info()
        current_balance = account_info.balance
        daily_drop = (account_balance - current_balance) / account_balance

        # Calculate the probability of winning based on the distance between the model's prediction and 0.5
        probability_of_winning = abs(signal[-1] - 0.5) * 2

        # Calculate the optimal volume for opening trades using the Kelly criterion
        optimal_volume = (probability_of_winning - (1 - probability_of_winning) / risk_reward_ratio) / risk_reward_ratio * account_balance / price_ask

        # Reduce the volume for opening trades by 10% with a step of 0.01 lot for each day of daily drop
        if daily_drop > 0.02:
            optimal_volume -= 0.01
            optimal_volume = max(optimal_volume, 0.01)
        elif current_balance > peak_balance:
            optimal_volume = (probability_of_winning - (1 - probability_of_winning) / risk_reward_ratio) / risk_reward_ratio * account_balance / price_ask
            peak_balance = current_balance

        # Set the volume for opening trades
        volume = optimal_volume

        for _ in range(attempts):
            if positions_total < MAX_OPEN_TRADES and signal[-1] > 0.5:
                request = {
                    "action": mt5.TRADE_ACTION_DEAL,
                    "symbol": symbol,
                    "volume": volume,
                    "type": mt5.ORDER_TYPE_BUY,
                    "price": price_ask,
                    "sl": price_ask - 150 * symbol_info.point,
                    "tp": price_ask + 800 * symbol_info.point,
                    "deviation": 20,
                    "magic": 123456,
                    "comment": "Test deal",
                    "type_time": mt5.ORDER_TIME_GTC,
                    "type_filling": mt5.ORDER_FILLING_FOK,
                }
            elif positions_total < MAX_OPEN_TRADES and signal[-1] < 0.5:
                request = {
                    "action": mt5.TRADE_ACTION_DEAL,
                    "symbol": symbol,
                    "volume": volume,
                    "type": mt5.ORDER_TYPE_SELL,
                    "price": price_bid,
                    "sl": price_bid + 150 * symbol_info.point,
                    "tp": price_bid - 800 * symbol_info.point,
                    "deviation": 20,
                    "magic": 123456,
                    "comment": "Test deal",
                    "type_time": mt5.ORDER_TIME_GTC,
                    "type_filling": mt5.ORDER_FILLING_FOK,
                }
            else:
                print("No signal to open a position")
                return None

            result = mt5.order_send(request)

            if result.retcode == mt5.TRADE_RETCODE_DONE:
                if signal[-1] < 0.5:
                    print("Buy position opened")
                    open_trades += 1
                elif signal[-1] > 0.5:
                    print("Sell position opened")
                    open_trades += 1
                return result.order
            else:
                print("Error: Trade request not executed, retcode={}. Attempt {}/{}".format(result.retcode, _ + 1, attempts))
                time.sleep(3)

        time.sleep(4000)

この関数に、probability_of_winning と optimal_volume変数を追加しました。probability_of_winningには、モデル予想と0.5との距離に2を掛けたものとして計算された勝率が格納されます。optimal_volumeには、ケリー基準を用いて計算した最適なベットサイズが格納されます。

「if daily_drop > 0.02:」ブロックで、optimal_volumeを0.01ロット単位で10%ずつ減らしています。また、「elif current_balance > peak_balance:」条件も追加しました。これは、現在の口座残高が前回のピークレベルを超えているかどうかを確認するものです。超えている場合、peak_balanceが更新される間に、現在の残高と勝敗比率に対してoptimal_volumeを再計算します。

このケリーロットサイズ管理システムは、勝率と勝敗率に基づいてベットサイズを自動的に最適化することができます。こうすることで、利益を最大化し、ドローダウンのリスクを最小化することができます。


多通貨運用と並列計算の実装

多通貨取引は、アルゴリズムが複数の通貨ペアを同時に取引することを可能にし、リスクを分散します。これは、ペアを持つsymbolsリストを介して実装されています。

並列コンピューティングは、同時にタスクを実行することで作業をスピードアップします。process_symbol関数でペアごとに別々のスレッドが作成されます。

process_symbolは、ペアデータをダウンロードし、変換し、XGBoostモデルを訓練し、テストし、定期的にデータを更新しながらオンラインで取引します。

スレッドはsymbolsからすべてのペアに対して作成されます。すべてのスレッドが完了したら、プログラムはthread.join()を使って待機します。

こうして、XGBoostに基づく高性能マルチスレッド多通貨取引システムが実装されました。

import threading

def process_symbol(symbol):
    try:
        # Retrieve data for the specified symbol
        raw_data = retrieve_data(symbol)
        if raw_data is None:
            print("No data found for symbol {}".format(symbol))
            return None

        # Augment data
        augmented_data = augment_data(raw_data)

        # Markup data
        marked_data = markup_data(augmented_data.copy(), 'close', 'label')

        # Label data
        labeled_data = label_data(marked_data, symbol)

        # Generate new features
        labeled_data_generate = generate_new_features(labeled_data, num_features=100, random_seed=1)

        # Cluster features by GMM
        labeled_data_clustered = cluster_features_by_gmm(labeled_data_generate, n_components=4)

        # Feature engineering
        labeled_data_engineered = feature_engineering(labeled_data_clustered, n_features_to_select=10)

        # Train XGBoost classifier
        train_data = labeled_data_engineered[labeled_data_engineered.index <= FORWARD]
        test_data = labeled_data_engineered[labeled_data_engineered.index > FORWARD]
        xgb_clf = train_xgboost_classifier(train_data, num_boost_rounds=1000)

        # Test XGBoost classifier
        test_features = test_data.drop(['label', 'labels'], axis=1)
        test_labels = test_data['labels']
        initial_balance = 10000.0
        markup = 0.00001
        test_model(xgb_clf, test_features, test_labels, markup, initial_balance)

        # Online trading
        position_id = None
        while True:
            # Get the last 2000 data points for online trading
            features = raw_data[-6000:].drop(['label', 'labels'], axis=1).values.tolist()

            # Update features every 6 seconds
            time.sleep(6)
            new_data = retrieve_data(symbol)
            if new_data is not None:
                raw_data = pd.concat([raw_data, new_data])
                raw_data = raw_data.dropna()

            # Online trading
            position_id = online_trading(symbol, features, xgb_clf, position_id)

    except Exception as e:
        print("Error processing {} symbol: {}".format(symbol, e))
        return None

symbols = ["EURUSD", "GBPUSD", "USDJPY", "AUDUSD", "USDCAD"]

# Create a list of threads for each symbol
threads = []
for symbol in symbols:
    thread = threading.Thread(target=process_symbol, args=(symbol,))
    thread.start()
    threads.append(thread)

# Wait for all threads to complete
for thread in threads:
    thread.join()

コードを実行した後、異なるスレッドからの画面出力(印字)が重なるという問題が発生しました。このため、画面上の出力が読めなくなり、アルゴリズム動作のデバッグや監視が困難になります。この問題を解決するために多くの試みがなされてきましたが、出力の重複を避けることはまだできていません。

Instruments in terminal: 31Instruments in terminal: 31Instruments in terminal: 31Instruments in terminal: 31Instruments in terminal: 31




No data for symbol USDCAD yet (attempt 1)No data for symbol NZDUSD yet (attempt 1)No data for symbol AUDUSD yet (attempt 1)
No data for symbol GBPUSD yet (attempt 1)


Instruments in terminal: 31Instruments in terminal: 31Instruments in terminal: 31Instruments in terminal: 31



No data for symbol USDCAD yet (attempt 2)No data for symbol AUDUSD yet (attempt 2)No data for symbol GBPUSD yet (attempt 2)


Instruments in terminal: 31Instruments in terminal: 31

Instruments in terminal: 31
No data for symbol GBPUSD yet (attempt 3)
Instruments in terminal: 31

この問題にもかかわらず、アルゴリズム自体は正しく機能し、その機能を果たしています。データをうまく処理し、モデルを訓練し、「銘柄」リストから各通貨ペアの取引を実行します。並列コンピューティングは、アルゴリズムの速度を大幅に向上させ、その効率を改善することを可能にします。

つまり、アルゴリズムが正しく取引をオープンしていることがわかります。



さらなるシステム改善の可能性

量子機械学習

現在は古典的なモデル学習を使用していますが、将来的には、精度と処理速度を向上させるために量子ビットを活用した量子機械学習への移行を計画しています。量子コンピューターには依然として課題がありますが、特別なソフトウェアやアルゴリズムの開発はすでに進行中です。私たちは量子学習を研究し、システムへの導入を目指します。これにより、大きな進歩が期待できます。

市場からのフィードバック:強化学習

取引システムの改善には強化学習の導入が有効です。このシステムは、市場と対話するエージェントとして機能し、利益の出た取引には報酬を、損失の出た取引にはペナルティを受け取ります。DQNなどのアルゴリズムを活用することで、システムは学習と適応を繰り返し、予測精度を向上させることが可能です。

SL&TPを選択する群知能

システムの効率を向上させるために、粒子群最適化(PSO)アルゴリズムを活用して群知能を導入することが考えられます。この手法により、さまざまなストップロスおよびテイクプロフィットのパラメータを生成し、過去のデータを用いてそれらの効率を評価します。PSOは最適なパラメータを選定するために役立ち、システムの適応性を高め、リスクの軽減にも貢献します。


結論

私たちの取引機械学習モデルは、データの前処理、データ分析、XGBoostタイプのアルゴリズムを使用しています。また、ノイズ付加、タイムシフト、特徴計算、クラスバランスの調整、そして交差検証を適用しています。テストデータでの精度は約60%です。

量子コンピューティング、強化学習、さらにストップロスやテイクプロフィットを選択するための群知能は、今後実装される予定です。これにより、訓練の質が向上し、実データに基づく効率やリスク管理も改善されるでしょう。

しかし、一つ問題があります。これらの技術は市場においてアルゴリズム間の激しい競争を引き起こす可能性があります。以前はトレーダー同士が競い合っていましたが、今や「誰のアルゴリズムが優れているか」が重要な要素となってきています。


MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/15127

データサイエンスとML(第31回):取引のためのCatBoost AIモデルの使用 データサイエンスとML(第31回):取引のためのCatBoost AIモデルの使用
CatBoost AIモデルは、その予測精度、効率性、散在する困難なデータセットに対する頑健性により、機械学習コミュニティの間で最近大きな人気を博しています。この記事では、外国為替市場を打ち負かすために、この種のモデルをどのように導入するかについて詳しく説明します。
ニューラルネットワークが簡単に(第95回):Transformerモデルにおけるメモリ消費の削減 ニューラルネットワークが簡単に(第95回):Transformerモデルにおけるメモリ消費の削減
Transformerアーキテクチャに基づくモデルは高い効率を示しますが、その使用は、訓練段階と運転中の両方で高いリソースコストによって複雑になります。この記事では、このようなモデルのメモリ使用量を削減するアルゴリズムを紹介します。
Connexusの本体(第4回):HTTP本体サポートの追加 Connexusの本体(第4回):HTTP本体サポートの追加
この記事では、JSONやプレーンテキストなどのデータを送信するために不可欠な、HTTPリクエストにおける本体(ボディ)の概念について探りました。適切なヘッダを使った正しい使い方を議論し、説明しました。また、Connexusライブラリの一部であるChttpBodyクラスを導入し、リクエストの本体の処理を簡素化しました。
化学反応最適化(CRO)アルゴリズム(第2回):組み立てと結果 化学反応最適化(CRO)アルゴリズム(第2回):組み立てと結果
第2回では、化学演算子を1つのアルゴリズムに集め、その結果の詳細な分析を紹介します。化学反応最適化(CRO)法がテスト機能に関する複雑な問題の解決にどのように対処するかを見てみましょう。