avatar of 发明者量化-小小梦 发明者量化-小小梦
フォロー ダイレクトメッセージ
4
フォロー
1271
フォロワー

マーケットコレクターのバックテストカスタムデータソース機能をアップグレードする手順を説明します

作成日:: 2020-05-07 17:43:54, 更新日:: 2023-10-09 22:47:43
comments   15
hits   2523

マーケットコレクターのバックテストカスタムデータソース機能をアップグレードする手順を説明します

マーケットコレクターのバックテストカスタムデータソース機能をアップグレードする手順を説明します

前の記事マーケットコレクターを実装するためのステップバイステップの指導私たちは協力して、市場データを収集するためのロボット プログラムを実装しました。収集した市場データをどのように使用するのでしょうか?もちろん、バックテストシステムにも使用されます。ここでは、発明者の定量取引プラットフォームのバックテストシステムのカスタムデータソース機能を利用して、収集したデータをバックテストシステムのデータソースとして直接使用できるため、バックテスト システムを作成できます。テスト システムは、履歴データをバックテストするあらゆる市場に適用できます。

したがって、「マーケットコレクター」をアップグレードすることができます!マーケットコレクターは、バックテスト システムにデータを提供するためのカスタム データ ソースとしても使用できます。

必要があれば、行動を起こしましょう!

準備する

前回とは準備が異なります。前回は、ローカルの MAC コンピューターでホスト プログラムを実行し、mongodb データベースをインストールして、データベース サービスを開始しました。今回は動作環境をVPSに変更し、Alibaba Cloud Linuxサーバーを利用してプログラムを実行しました。

  • mongodb データベース

前回の記事と同様に、マーケットコレクタープログラムが実行されるデバイスに MongoDB データベースをインストールし、サービスを開始する必要があります。基本的には、MAC コンピュータに mongodb をインストールするのと同じです。インターネット上には多くのチュートリアルがあります。検索してみてください。とても簡単です。

  • Python 3をインストールする このプログラムは Python 3 を使用します。いくつかのライブラリが使用されるため、利用できない場合はインストールする必要があることに注意してください。

    • pymongo
    • http
    • urllib
  • ホスト Inventor 定量取引プラットフォームの管理者を運営するだけです。

「マーケット情報コレクター」を変更する

マーケットコレクターRecordsCollecter (チュートリアル)この戦略。 いくつか変更してみましょう: プログラムがデータ収集のための while ループに入る前に、マルチスレッド ライブラリを使用して、Inventor の Quantitative Trading Platform バックテスト システムからのデータ要求をリッスンするサービスを同時に開始します。 (その他の詳細は無視できます)

RecordsCollecter (カスタム データ ソース機能を提供するようにアップグレード)

import _thread
import pymongo
import json
import math
from http.server import HTTPServer, BaseHTTPRequestHandler
from urllib.parse import parse_qs, urlparse

def url2Dict(url):
    query = urlparse(url).query  
    params = parse_qs(query)  
    result = {key: params[key][0] for key in params}  
    return result

class Provider(BaseHTTPRequestHandler):
    def do_GET(self):
        try:
            self.send_response(200)
            self.send_header("Content-type", "application/json")
            self.end_headers()

            dictParam = url2Dict(self.path)
            Log("自定义数据源服务接收到请求,self.path:", self.path, "query 参数:", dictParam)
            
            # 目前回测系统只能从列表中选择交易所名称,在添加自定义数据源时,设置为币安,即:Binance
            exName = exchange.GetName()                                     
            # 注意,period为底层K线周期
            tabName = "%s_%s" % ("records", int(int(dictParam["period"]) / 1000))  
            priceRatio = math.pow(10, int(dictParam["round"]))
            amountRatio = math.pow(10, int(dictParam["vround"]))
            fromTS = int(dictParam["from"]) * int(1000)
            toTS = int(dictParam["to"]) * int(1000)
            
            
            # 连接数据库
            Log("连接数据库服务,获取数据,数据库:", exName, "表:", tabName)
            myDBClient = pymongo.MongoClient("mongodb://localhost:27017")
            ex_DB = myDBClient[exName]
            exRecords = ex_DB[tabName]
            
            
            # 要求应答的数据
            data = {
                "schema" : ["time", "open", "high", "low", "close", "vol"],
                "data" : []
            }
            
            # 构造查询条件:大于某个值{'age': {'$gt': 20}} 小于某个值{'age': {'$lt': 20}}
            dbQuery = {"$and":[{'Time': {'$gt': fromTS}}, {'Time': {'$lt': toTS}}]}
            Log("查询条件:", dbQuery, "查询条数:", exRecords.find(dbQuery).count(), "数据库总条数:", exRecords.find().count())
            
            for x in exRecords.find(dbQuery).sort("Time"):
                # 需要根据请求参数round和vround,处理数据精度
                bar = [x["Time"], int(x["Open"] * priceRatio), int(x["High"] * priceRatio), int(x["Low"] * priceRatio), int(x["Close"] * priceRatio), int(x["Volume"] * amountRatio)]
                data["data"].append(bar)
            
            Log("数据:", data, "响应回测系统请求。")
            # 写入数据应答
            self.wfile.write(json.dumps(data).encode())
        except BaseException as e:
            Log("Provider do_GET error, e:", e)


def createServer(host):
    try:
        server = HTTPServer(host, Provider)
        Log("Starting server, listen at: %s:%s" % host)
        server.serve_forever()
    except BaseException as e:
        Log("createServer error, e:", e)
        raise Exception("stop")

def main():
    LogReset(1)
    exName = exchange.GetName()
    period = exchange.GetPeriod()
    Log("收集", exName, "交易所的K线数据,", "K线周期:", period, "秒")
    
    # 连接数据库服务,服务地址 mongodb://127.0.0.1:27017 具体看服务器上安装的mongodb设置
    Log("连接托管者所在设备mongodb服务,mongodb://localhost:27017")
    myDBClient = pymongo.MongoClient("mongodb://localhost:27017")   
    # 创建数据库
    ex_DB = myDBClient[exName]
    
    # 打印目前数据库表
    collist = ex_DB.list_collection_names()
    Log("mongodb ", exName, " collist:", collist)
    
    # 检测是否删除表
    arrDropNames = json.loads(dropNames)
    if isinstance(arrDropNames, list):
        for i in range(len(arrDropNames)):
            dropName = arrDropNames[i]
            if isinstance(dropName, str):
                if not dropName in collist:
                    continue
                tab = ex_DB[dropName]
                Log("dropName:", dropName, "删除:", dropName)
                ret = tab.drop()
                collist = ex_DB.list_collection_names()
                if dropName in collist:
                    Log(dropName, "删除失败")
                else :
                    Log(dropName, "删除成功")
    
    # 开启一个线程,提供自定义数据源服务
    try:
        # _thread.start_new_thread(createServer, (("localhost", 9090), ))     # 本机测试
        _thread.start_new_thread(createServer, (("0.0.0.0", 9090), ))         # VPS服务器上测试
        Log("开启自定义数据源服务线程", "#FF0000")
    except BaseException as e:
        Log("启动自定义数据源服务失败!")
        Log("错误信息:", e)
        raise Exception("stop")
    
    # 创建records表
    ex_DB_Records = ex_DB["%s_%d" % ("records", period)]
    Log("开始收集", exName, "K线数据", "周期:", period, "打开(创建)数据库表:", "%s_%d" % ("records", period), "#FF0000")
    preBarTime = 0
    index = 1
    while True:
        r = _C(exchange.GetRecords)
        if len(r) < 2:
            Sleep(1000)
            continue
        if preBarTime == 0:
            # 首次写入所有BAR数据
            for i in range(len(r) - 1):
                bar = r[i]
                # 逐根写入,需要判断当前数据库表中是否已经有该条数据,基于时间戳检测,如果有该条数据,则跳过,没有则写入
                retQuery = ex_DB_Records.find({"Time": bar["Time"]})
                if retQuery.count() > 0:
                    continue
                
                # 写入bar到数据库表
                ex_DB_Records.insert_one({"High": bar["High"], "Low": bar["Low"], "Open": bar["Open"], "Close": bar["Close"], "Time": bar["Time"], "Volume": bar["Volume"]})                
                index += 1
            preBarTime = r[-1]["Time"]
        elif preBarTime != r[-1]["Time"]:
            bar = r[-2]
            # 写入数据前检测,数据是否已经存在,基于时间戳检测
            retQuery = ex_DB_Records.find({"Time": bar["Time"]})
            if retQuery.count() > 0:
                continue
            
            ex_DB_Records.insert_one({"High": bar["High"], "Low": bar["Low"], "Open": bar["Open"], "Close": bar["Close"], "Time": bar["Time"], "Volume": bar["Volume"]})
            index += 1
            preBarTime = r[-1]["Time"]
        LogStatus(_D(), "preBarTime:", preBarTime, "_D(preBarTime):", _D(preBarTime/1000), "index:", index)
        # 增加画图展示
        ext.PlotRecords(r, "%s_%d" % ("records", period))
        Sleep(10000)
        

テスト

ロボットを設定する マーケットコレクターのバックテストカスタムデータソース機能をアップグレードする手順を説明します

ロボットを実行し、マーケットコレクターを実行します。 マーケットコレクターのバックテストカスタムデータソース機能をアップグレードする手順を説明します

テスト戦略を開き、このバックテスト戦略などのバックテストを実行してテストします。

function main() {
    Log(exchange.GetRecords())
    Log(exchange.GetRecords())
    Log(exchange.GetRecords())
    Log(exchange.GetRecords())
    Log(exchange.GetRecords())
    Log(exchange.GetRecords())
    Log(exchange.GetRecords().length)
}

バックテストオプションを設定し、取引所をBinanceに設定します。カスタムデータソースは現時点では取引所名を独自に設定できないためです。設定にはリスト内の取引所のみを使用できます。バックテスト時にはBinanceが表示されます。これはデータです。 wexApp シミュレーション ディスク。

マーケットコレクターのバックテストカスタムデータソース機能をアップグレードする手順を説明します

カスタム データ ソースとしてのマーケット コレクターに基づくバックテスト システムによって生成されたチャートと、wexApp 交換ページの 1 時間ローソク足チャートを比較して、同じかどうかを確認します。

マーケットコレクターのバックテストカスタムデータソース機能をアップグレードする手順を説明します

マーケットコレクターのバックテストカスタムデータソース機能をアップグレードする手順を説明します

このように、VPS 上のロボットは K ライン データを独自に収集することができ、収集したデータをいつでも取得してバックテスト システムで直接バックテストを行うことができます。 これはほんの一滴に過ぎません。専門家は、カスタム データ ソースのリアルタイム バックテストのサポート、多品種および複数市場のデータ収集などの機能のサポートなど、これをさらに拡張することができます。

メッセージを残すことを歓迎します。