Giter VIP home page Giter VIP logo

51bitquant / howtrader Goto Github PK

View Code? Open in Web Editor NEW
680.0 23.0 289.0 1.13 MB

Howtrader: A crypto quant framework for developing, backtesting, and executing your own trading strategies. Seamlessly integrates with TradingView and other third-party signals. Simply send a post request to automate trading and order placement. Supports Binance and Okex exchanges.

License: MIT License

Python 99.93% Shell 0.01% Dockerfile 0.07%
51bitquant vnpy cryptocurrency bitcoin eth quantitative algo trading python trader

howtrader's Introduction

HowTrader

中文文档

What does Howtrader means? It means how to be a trader, especially a quant trader.

HowTrader crypto quantitative trading framework, and was forked from VNPY, so the core codes、functions and useages are pretty similar to VNPY, but would be more easy to install and use. By the way, Howtrader fixes some bugs, add more functions and strategies to framework. We extend the TradingView signals and grid strategies to Howtrader and more codes.

Howtrader VS VNPY

  1. some classes' definition are pretty different: for OrderData 、TradeData、ContractData, we replace float with Decimal to meet the precision, theses classes are defined in howtrader.trader.object module.

  2. on_order and on_trade update sequence are different: in VNPY, ,the on_order is always updated before the on_trade if the order was traded. And in the cta strategy, the self.pos(the position data) was calculated in the on_trade callback. So if we want to get the latest self.pos value, we may need to define a variable to calculate the latest position data. To solve this issue, we push the on_trade before the on_order callback. check out the code to find out the details:

        
        def on_order(self, order: OrderData) -> None:
         """on order update"""
         order.update_time = generate_datetime(time.time() * 1000)
         last_order: OrderData = self.get_order(order.orderid)
         if not last_order:
             self.orders[order.orderid] = copy(order)
             super().on_order(copy(order))
    
         else:
             traded: Decimal = order.traded - last_order.traded
             if traded < 0: # filter the order is not in sequence
                 return None
    
             if traded > 0:
                 trade: TradeData = TradeData(
                     symbol=order.symbol,
                     exchange=order.exchange,
                     orderid=order.orderid,
                     direction=order.direction,
                     price=order.price,
                     volume=traded,
                     datetime=order.update_time,
                     gateway_name=self.gateway_name,
                 )
    
                 super().on_trade(trade)
    
             if traded == 0 and order.status == last_order.status:
                 return None
    
             self.orders[order.orderid] = copy(order)
             super().on_order(copy(order))
    
     def get_order(self, orderid: str) -> OrderData:
         """get order by order id"""
         return self.orders.get(orderid, None)
  3. gateways are different: solve issues like disconnecting from exchange, and reconnecting.

  4. TradingView app to receive other 3rd party signals and algo trading strategies, checkout the module: howtrader.app.tradingview

Installation

the framework depends on pandas, Numpy libraries, so we higly recommend you to install Anaconda.

  1. Install Anaconda, the Anaconda download website is here, remember to click "Add Conda to System Path" in the process of Anaconda Installation. If you forget to do so, you might need to unistall and reinstall the Anaconda, or just search how to add conda to you system path, if you encounter the problem of "not found conda command".

    If you already install the anaconda before, you can simply update your conda by runing the following command:

    conda update conda

    conda update anaconda

  2. install git

Install git is pretty simple, just download git from [https://git-scm.com/downloads], then install it, remember to add git to your system path. If you're using MacOX, git was integrated into the system, so you may not need to install git. 3. create virtual env by conda

conda create -n mytrader python==3.9

mytrader is the name of your virtual env, if you have the mytrader virtual env before and the version is not 3.9, you can unistall it by following command:

conda remove -n mytrader --all

if you encounter an error, you may need to deactivate the mytrader by the command:

conda deactivate

then remove it:

conda remove -n mytrader --all

  1. activate your virtual env:

conda activate mytrader

  1. install howtrader

run the command:

pip install git+https://github.com/51bitquant/howtrader.git

if you want to update to the latest version, use the command:

pip install git+https://github.com/51bitquant/howtrader.git -U

if encounter the failure of installation TA-Lib, checkout the next step.

Install TA-Lib

If you can't install the howtrader in Window system, the main reason may be the TA-Lib, here we go in to the detail of installing TA-Lib:

  1. open this url in your browser:https://www.lfd.uci.edu/~gohlke/pythonlibs/#ta-lib

  2. search ta-lib in the website and download the TA-Lib.whl file: here we found the TA_Lib‑0.4.24‑cp39‑cp39‑win_amd64.whl in the website and we click download, for the TA_Lib-0.4.24, it means TA-Lib version is 0.4.24, cp39 is the python version is 3.9, amd64 your system version is 64 bit, choose the right one and download it.

  3. change your directory to your TA-Lib folder, and remember to activate your virtual env to mytrader(if you use mytrader as your vitrual env), then execute the following command:

pip install TA_Lib‑0.4.24‑cp39‑cp39‑win_amd64.whl

how-to-use

create a python proejct, and create a main.py file,and set your project's interpreter to the mytrader(the virtual env you just create and config).

then copy and paste the following code to main.py and run it, and you will see a howtrader folder beside the main.py, the howtrader folder contains the configs data(like exchange api key)、 your strategy settings and datas etc.

from howtrader.event import EventEngine, Event
from howtrader.trader.event import EVENT_TV_SIGNAL
from howtrader.trader.engine import MainEngine
from howtrader.trader.ui import MainWindow, create_qapp
from howtrader.trader.setting import SETTINGS
from howtrader.gateway.binance import BinanceUsdtGateway, BinanceSpotGateway, BinanceInverseGateway

from howtrader.app.cta_strategy import CtaStrategyApp
# from howtrader.app.data_manager import DataManagerApp
# from howtrader.app.data_recorder import DataRecorderApp
# from howtrader.app.algo_trading import AlgoTradingApp
# from howtrader.app.risk_manager import RiskManagerApp
# from howtrader.app.spread_trading import SpreadTradingApp
from howtrader.app.tradingview import TradingViewApp
from threading import Thread
import json
from flask import Flask, request

# create global event_engine
event_engine: EventEngine = EventEngine()
passphrase = SETTINGS.get("passphrase", "")
port = SETTINGS.get("port", 9999)

app = Flask(__name__)

@app.route('/', methods=['GET'])
def welcome():
    return "Hi, this is tv server!"

@app.route('/webhook', methods=['POST'])
def webhook():
    try:
        data = json.loads(request.data)
        if data.get('passphrase', None) != passphrase:
            return {"status": "failure", "msg": "passphrase is incorrect"}
        del data['passphrase'] # del it for safety.
        event:Event = Event(type=EVENT_TV_SIGNAL, data=data)
        event_engine.put(event)
        return {"status": "success", "msg": ""}
    except Exception as error:
        return {"status": "error", "msg": str(error)}

def start_tv_server():
    app.run(host="127.0.0.1", port=port)

def main():
    """"""
    qapp = create_qapp()
    main_engine = MainEngine(event_engine)

    main_engine.add_gateway(BinanceSpotGateway)
    main_engine.add_gateway(BinanceUsdtGateway)
    main_engine.add_gateway(BinanceInverseGateway)
    main_engine.add_app(CtaStrategyApp)
    main_engine.add_app(TradingViewApp)

    # if you don't use
    # main_engine.add_app(DataManagerApp)
    # main_engine.add_app(AlgoTradingApp)
    # main_engine.add_app(DataRecorderApp)
    # main_engine.add_app(RiskManagerApp)
    # main_engine.add_app(SpreadTradingApp)

    main_window = MainWindow(main_engine, event_engine)
    main_window.showMaximized()

    t1 = Thread(target=start_tv_server)
    t1.daemon = True
    t1.start()

    qapp.exec()


if __name__ == "__main__":
    main()

how-to-crawl binance kline data

howdtrader use sliqte database as default, and also support mongodb and mysql if you want to use it. If you want to use other database, you can change the configuration in howtrader/vt_setting.json, here is the full configuration key, you can just config the corresponding values.

{
    "font.family": "", # set font family if display error
    "font.size": 12,

    "log.active": True,
    "log.level": CRITICAL,
    "log.console": True,
    "log.file": True,

    "email.server": "smtp.qq.com",
    "email.port": 465,
    "email.username": "",
    "email.password": "",
    "email.sender": "",
    "email.receiver": "",

    "order_update_interval": 600, # securing correct orders' status by synchronizing/updating orders through rest api
    "update_server_time_interval": 300,  # sync with server time
    "passphrase": "howtrader",  # tv passphrase
    "port": 9999, # tv server port

    "datafeed.name": "",
    "datafeed.username": "",
    "datafeed.password": "",

    "database.timezone": get_localzone_name(),
    "database.name": "sqlite",
    "database.database": "database.db",
    "database.host": "",
    "database.port": 0,
    "database.user": "",
    "database.password": ""
}


to crawl the Binance exchange kline data for backtesting, you just need to create a crawl_data.py file, just in the main.py directory. copy and paste the following codes:

"""
use the binance api to crawl data then save into the sqlite database.

"""

import pandas as pd
import time
from datetime import datetime
import requests
import pytz
from howtrader.trader.database import get_database, BaseDatabase

pd.set_option('expand_frame_repr', False)  #
from howtrader.trader.object import BarData, Interval, Exchange

BINANCE_SPOT_LIMIT = 1000
BINANCE_FUTURE_LIMIT = 1500

from howtrader.trader.constant import LOCAL_TZ

from threading import Thread
database: BaseDatabase = get_database()

def generate_datetime(timestamp: float) -> datetime:
    """
    :param timestamp:
    :return:
    """
    dt = datetime.fromtimestamp(timestamp / 1000)
    dt = LOCAL_TZ.localize(dt)
    return dt


def get_binance_data(symbol: str, exchange: str, start_time: str, end_time: str):
    """
    crawl binance exchange data
    :param symbol: BTCUSDT.
    :param exchange: spot、usdt_future, inverse_future.
    :param start_time: format :2020-1-1 or 2020-01-01 year-month-day
    :param end_time: format: 2020-1-1 or 2020-01-01 year-month-day
    :param gate_way the gateway name for binance is:BINANCE_SPOT, BINANCE_USDT, BINANCE_INVERSE
    :return:
    """

    api_url = ''
    save_symbol = symbol
    gateway = "BINANCE_USDT"
    if exchange == 'spot':
        print("spot")
        limit = BINANCE_SPOT_LIMIT
        save_symbol = symbol.lower()
        gateway = 'BINANCE_SPOT'
        api_url = f'https://api.binance.com/api/v3/klines?symbol={symbol}&interval=1m&limit={limit}'

    elif exchange == 'usdt_future':
        print('usdt_future')
        limit = BINANCE_FUTURE_LIMIT
        gateway = "BINANCE_USDT"
        api_url = f'https://fapi.binance.com/fapi/v1/klines?symbol={symbol}&interval=1m&limit={limit}'

    elif exchange == 'inverse_future':
        print("inverse_future")
        limit = BINANCE_FUTURE_LIMIT
        gateway = "BINANCE_INVERSE"
        f'https://dapi.binance.com/dapi/v1/klines?symbol={symbol}&interval=1m&limit={limit}'

    else:
        raise Exception('the exchange name should be one of :spot, usdt_future, inverse_future')

    start_time = int(datetime.strptime(start_time, '%Y-%m-%d').timestamp() * 1000)
    end_time = int(datetime.strptime(end_time, '%Y-%m-%d').timestamp() * 1000)

    while True:
        try:
            print(start_time)
            url = f'{api_url}&startTime={start_time}'
            print(url)
            datas = requests.get(url=url, timeout=10, proxies=proxies).json()

            """
            [
                [
                    1591258320000,      // open time
                    "9640.7",           // open price
                    "9642.4",           // highest price
                    "9640.6",           // lowest price
                    "9642.0",           // close price(latest price if the kline is not close)
                    "206",              // volume
                    1591258379999,      // close time
                    "2.13660389",       // turnover
                    48,                 // trade count 
                    "119",              // buy volume
                    "1.23424865",       //  buy turnover
                    "0"                 // ignore
                ]

            """

            buf = []

            for row in datas:
                bar: BarData = BarData(
                    symbol=save_symbol,
                    exchange=Exchange.BINANCE,
                    datetime=generate_datetime(row[0]),
                    interval=Interval.MINUTE,
                    volume=float(row[5]),
                    turnover=float(row[7]),
                    open_price=float(row[1]),
                    high_price=float(row[2]),
                    low_price=float(row[3]),
                    close_price=float(row[4]),
                    gateway_name=gateway
                )
                buf.append(bar)

            database.save_bar_data(buf)

            # exit the loop, if close time is greater than the current time
            if (datas[-1][0] > end_time) or datas[-1][6] >= (int(time.time() * 1000) - 60 * 1000):
                break

            start_time = datas[-1][0]

        except Exception as error:
            print(error)
            time.sleep(10)


def download_spot(symbol):
    """
    download binance spot data, config your start date and end date(format: year-month-day)
    :return:
    """
    t1 = Thread(target=get_binance_data, args=(symbol, 'spot', "2018-1-1", "2018-6-1"))
    t2 = Thread(target=get_binance_data, args=(symbol, 'spot', "2018-6-1", "2018-12-1"))

    t3 = Thread(target=get_binance_data, args=(symbol, 'spot', "2018-12-1", "2019-6-1"))
    t4 = Thread(target=get_binance_data, args=(symbol, 'spot', "2019-6-1", "2019-12-1"))

    t5 = Thread(target=get_binance_data, args=(symbol, 'spot', "2019-12-1", "2020-6-1"))
    t6 = Thread(target=get_binance_data, args=(symbol, 'spot', "2020-6-1", "2020-12-1"))

    t7 = Thread(target=get_binance_data, args=(symbol, 'spot', "2020-12-1", "2021-6-1"))
    t8 = Thread(target=get_binance_data, args=(symbol, 'spot', "2021-6-1", "2021-12-1"))
    t9 = Thread(target=get_binance_data, args=(symbol, 'spot', "2021-12-1", "2022-6-28"))

    t1.start()
    t2.start()
    t3.start()
    t4.start()
    t5.start()
    t6.start()
    t7.start()
    t8.start()
    t9.start()

    t1.join()
    t2.join()
    t3.join()
    t4.join()
    t5.join()
    t6.join()
    t7.join()
    t8.join()
    t9.join()


def download_future(symbol):
    """
    download binance future data, config your start date and end date(format: year-month-day)
    :return:

    """

    t1 = Thread(target=get_binance_data, args=(symbol, 'usdt_future', "2020-1-1", "2020-6-1"))
    t2 = Thread(target=get_binance_data, args=(symbol, 'usdt_future', "2020-6-1", "2020-12-1"))
    t3 = Thread(target=get_binance_data, args=(symbol, 'usdt_future', "2020-12-1", "2021-6-1"))
    t4 = Thread(target=get_binance_data, args=(symbol, 'usdt_future', "2021-6-1", "2021-12-1"))
    t5 = Thread(target=get_binance_data, args=(symbol, 'usdt_future', "2021-12-1", "2022-6-28"))

    t1.start()
    t2.start()
    t3.start()
    t4.start()
    t5.start()

    t1.join()
    t2.join()
    t3.join()
    t4.join()
    t5.join()



if __name__ == '__main__':

    """
    read the code before run it. the software crawl the binance data then save into the sqlite database.
    you may need to change the start date and end date.
    """

    # proxy_host , if you can directly connect to the binance exchange, then set it to None or empty string "",如果没有你就设置为 None 或者空的字符串 "",
    # you can use the command  ping api.binance.com to check whether your network work well: 你可以在终端运行 ping api.binance.com 查看你的网络是否正常。
    proxy_host = "127.0.0.1"  # set it to your proxy_host 如果没有就设置为"", 如果有就设置为你的代理主机如:127.0.0.1
    proxy_port = 1087  # set it to your proxy_port  设置你的代理端口号如: 1087, 没有你修改为0,但是要保证你能访问api.binance.com这个主机。

    proxies = None
    if proxy_host and proxy_port:
        proxy = f'http://{proxy_host}:{proxy_port}'
        proxies = {'http': proxy, 'https': proxy}

    download_future(symbol="BTCUSDT")  # crawl usdt_future data. 下载合约的数据

    download_spot(symbol="BTCUSDT") # crawl binance spot data.




if you want to change start date or end date, you check out the codes. And the data will be stored in howtrader/database.db file.

backtesting

for backtesting, here is the example. vt_symbol format like BTCUSDT.BINANCE, the first part is symbol, and other part is exchange name. Howtrader uses lower case for spot market, and upper case for future market.

from howtrader.app.cta_strategy.backtesting import BacktestingEngine, OptimizationSetting
from howtrader.trader.object import Interval
from datetime import datetime
from strategies.atr_rsi_strategy import AtrRsiStrategy  # import your strategy.

engine = BacktestingEngine()
engine.set_parameters(
    vt_symbol="BTCUSDT.BINANCE",
    interval=Interval.MINUTE,
    start=datetime(2020, 1, 1),
    end=datetime(2020, 5, 1),
    rate=4/10000,
    slippage=0,
    size=1,
    pricetick=0.01,
    capital=1000000,
)

engine.add_strategy(AtrRsiStrategy, {})


engine.load_data()
engine.run_backtesting()
df = engine.calculate_result()
engine.calculate_statistics()
engine.show_chart()

setting = OptimizationSetting()
setting.set_target("sharpe_ratio")
setting.add_parameter("atr_length", 3, 39, 1)
setting.add_parameter("atr_ma_length", 10, 30, 1)

result = engine.run_ga_optimization(setting)  # optimization result
print(result) # you can print the result.


for more example codes, checkout the examples: https://github.com/51bitquant/howtrader/tree/main/examples

material codes:

you can check out my github profile: https:github.com/51bitquant

howtrader course_codes: https://github.com/51bitquant/course_codes

Contact

Twitter: 51bitquant.eth

discord-community: https://discord.gg/fgySfwG9eJ

Binance Invite Link: https://www.binancezh.pro/cn/futures/ref/51bitquant

howtrader's People

Contributors

51bitquant avatar fimh avatar hatawong avatar koujun2012 avatar xcycharles avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

howtrader's Issues

ImportError: cannot import name 'get_localzone_name' from 'tzlocal' (C:\QGB\Anaconda3\lib\site-packages\tzlocal\__init__.py)

In [199]: pip install git+https://github.com/51bitquant/howtrader.git
Collecting git+https://github.com/51bitquant/howtrader.git
  Cloning https://github.com/51bitquant/howtrader.git to c:\users\qgb\appdata\local\temp\pip-req-build-ylsqf3y3
  Running command git clone -q https://github.com/51bitquant/howtrader.git 'C:\Users\qgb\AppData\Local\Temp\pip-req-build-ylsqf3y3'
Collecting simplejson
  Downloading simplejson-3.18.3-cp37-cp37m-win_amd64.whl (74 kB)
     |████████████████████████████████| 74 kB 126 kB/s
Requirement already satisfied: flask in c:\qgb\anaconda3\lib\site-packages (from howtrader==3.3.0) (1.1.1)
Collecting PySide6
  Downloading PySide6-6.4.2-cp37-abi3-win_amd64.whl (7.2 kB)
Collecting pyqtgraph
  Downloading pyqtgraph-0.12.4-py3-none-any.whl (995 kB)
     |████████████████████████████████| 995 kB 251 kB/s
Collecting qdarkstyle
  Downloading QDarkStyle-3.1-py2.py3-none-any.whl (870 kB)
     |████████████████████████████████| 870 kB 152 kB/s
Requirement already satisfied: requests in c:\qgb\anaconda3\lib\site-packages (from howtrader==3.3.0) (2.25.1)
Requirement already satisfied: aiohttp in c:\users\qgb\appdata\roaming\python\python37\site-packages (from howtrader==3.3.0) (3.6.2)
Requirement already satisfied: pytz in c:\qgb\anaconda3\lib\site-packages (from howtrader==3.3.0) (2021.3)
Collecting peewee
  Downloading peewee-3.15.4.tar.gz (860 kB)
     |████████████████████████████████| 860 kB 163 kB/s
Collecting pymongo
  Downloading pymongo-4.3.3-cp37-cp37m-win_amd64.whl (382 kB)
     |████████████████████████████████| 382 kB 285 kB/s
Requirement already satisfied: numpy in c:\qgb\anaconda3\lib\site-packages (from howtrader==3.3.0) (1.21.6)
Requirement already satisfied: pandas in c:\qgb\anaconda3\lib\site-packages (from howtrader==3.3.0) (0.25.3)
Requirement already satisfied: matplotlib in c:\qgb\anaconda3\lib\site-packages (from howtrader==3.3.0) (3.5.1)
Collecting seaborn
  Downloading seaborn-0.12.2-py3-none-any.whl (293 kB)
     |████████████████████████████████| 293 kB 261 kB/s
Collecting deap
  Downloading deap-1.3.3-cp37-cp37m-win_amd64.whl (108 kB)
     |████████████████████████████████| 108 kB 225 kB/s
Requirement already satisfied: tzlocal in c:\qgb\anaconda3\lib\site-packages (from howtrader==3.3.0) (2.0.0)
Collecting plotly
  Downloading plotly-5.13.0-py2.py3-none-any.whl (15.2 MB)
     |████████████████████████████████| 15.2 MB 656 kB/s
Requirement already satisfied: importlib-metadata in c:\users\qgb\appdata\roaming\python\python37\site-packages (from howtrader==3.3.0) (4.12.0)
Requirement already satisfied: Jinja2>=2.10.1 in c:\qgb\anaconda3\lib\site-packages (from flask->howtrader==3.3.0) (2.10.3)
Requirement already satisfied: itsdangerous>=0.24 in c:\qgb\anaconda3\lib\site-packages (from flask->howtrader==3.3.0) (1.1.0)
Requirement already satisfied: Werkzeug>=0.15 in c:\qgb\anaconda3\lib\site-packages (from flask->howtrader==3.3.0) (0.16.0)
Requirement already satisfied: click>=5.1 in c:\qgb\anaconda3\lib\site-packages (from flask->howtrader==3.3.0) (8.1.3)
Collecting PySide6-Essentials==6.4.2
  Downloading PySide6_Essentials-6.4.2-cp37-abi3-win_amd64.whl (77.2 MB)
     |████████████████████████████████| 77.2 MB 3.3 MB/s
Collecting PySide6-Addons==6.4.2
  Downloading PySide6_Addons-6.4.2-cp37-abi3-win_amd64.whl (98.8 MB)
     |████████████████████████████████| 98.8 MB 43 kB/s
Collecting shiboken6==6.4.2
  Downloading shiboken6-6.4.2-cp37-abi3-win_amd64.whl (1.5 MB)
     |████████████████████████████████| 1.5 MB 182 kB/s
Requirement already satisfied: qtpy>=1.9 in c:\qgb\anaconda3\lib\site-packages (from qdarkstyle->howtrader==3.3.0) (1.9.0)
Requirement already satisfied: chardet<5,>=3.0.2 in c:\qgb\anaconda3\lib\site-packages (from requests->howtrader==3.3.0) (3.0.4)
Requirement already satisfied: certifi>=2017.4.17 in c:\qgb\anaconda3\lib\site-packages (from requests->howtrader==3.3.0) (2022.6.15)
Requirement already satisfied: idna<3,>=2.5 in c:\qgb\anaconda3\lib\site-packages (from requests->howtrader==3.3.0) (2.8)
Requirement already satisfied: urllib3<1.27,>=1.21.1 in c:\qgb\anaconda3\lib\site-packages (from requests->howtrader==3.3.0) (1.25.10)
Requirement already satisfied: yarl<2.0,>=1.0 in c:\users\qgb\appdata\roaming\python\python37\site-packages (from aiohttp->howtrader==3.3.0) (1.3.0)
Requirement already satisfied: async-timeout<4.0,>=3.0 in c:\users\qgb\appdata\roaming\python\python37\site-packages (from aiohttp->howtrader==3.3.0) (3.0.1)
Requirement already satisfied: multidict<5.0,>=4.5 in c:\users\qgb\appdata\roaming\python\python37\site-packages (from aiohttp->howtrader==3.3.0) (4.5.2)
Requirement already satisfied: attrs>=17.3.0 in c:\qgb\anaconda3\lib\site-packages (from aiohttp->howtrader==3.3.0) (19.3.0)
Requirement already satisfied: dnspython<3.0.0,>=1.16.0 in c:\qgb\anaconda3\lib\site-packages (from pymongo->howtrader==3.3.0) (2.1.0)
Requirement already satisfied: python-dateutil>=2.6.1 in c:\qgb\anaconda3\lib\site-packages (from pandas->howtrader==3.3.0) (2.8.0)
Requirement already satisfied: packaging>=20.0 in c:\qgb\anaconda3\lib\site-packages (from matplotlib->howtrader==3.3.0) (21.3)
Requirement already satisfied: fonttools>=4.22.0 in c:\qgb\anaconda3\lib\site-packages (from matplotlib->howtrader==3.3.0) (4.22.1)
Requirement already satisfied: pyparsing>=2.2.1 in c:\qgb\anaconda3\lib\site-packages (from matplotlib->howtrader==3.3.0) (3.0.9)
Requirement already satisfied: kiwisolver>=1.0.1 in c:\qgb\anaconda3\lib\site-packages (from matplotlib->howtrader==3.3.0) (1.1.0)
Requirement already satisfied: pillow>=6.2.0 in c:\qgb\anaconda3\lib\site-packages (from matplotlib->howtrader==3.3.0) (8.3.1)
Requirement already satisfied: cycler>=0.10 in c:\qgb\anaconda3\lib\site-packages (from matplotlib->howtrader==3.3.0) (0.10.0)
Requirement already satisfied: typing_extensions; python_version < "3.8" in c:\qgb\anaconda3\lib\site-packages (from seaborn->howtrader==3.3.0) (4.3.0)
Collecting tenacity>=6.2.0
  Downloading tenacity-8.2.1-py3-none-any.whl (24 kB)
Requirement already satisfied: zipp>=0.5 in c:\qgb\anaconda3\lib\site-packages (from importlib-metadata->howtrader==3.3.0) (0.6.0)
Requirement already satisfied: MarkupSafe>=0.23 in c:\qgb\anaconda3\lib\site-packages (from Jinja2>=2.10.1->flask->howtrader==3.3.0) (1.1.1)
Requirement already satisfied: colorama; platform_system == "Windows" in c:\qgb\anaconda3\lib\site-packages (from click>=5.1->flask->howtrader==3.3.0) (0.4.5)
Requirement already satisfied: six>=1.5 in c:\qgb\anaconda3\lib\site-packages (from python-dateutil>=2.6.1->pandas->howtrader==3.3.0) (1.15.0)
Requirement already satisfied: setuptools in c:\qgb\anaconda3\lib\site-packages (from kiwisolver>=1.0.1->matplotlib->howtrader==3.3.0) (41.6.0.post20191030)
Requirement already satisfied: more-itertools in c:\qgb\anaconda3\lib\site-packages (from zipp>=0.5->importlib-metadata->howtrader==3.3.0) (7.2.0)
Building wheels for collected packages: howtrader, peewee
  Building wheel for howtrader (setup.py) ... done
  Created wheel for howtrader: filename=howtrader-3.3.0-py3-none-any.whl size=413806 sha256=1edfd9c8768602e47cf25fdc6dd2d26e9b79579fc32e6673a3a5510874df59f9
  Stored in directory: C:\Users\qgb\AppData\Local\Temp\pip-ephem-wheel-cache-25fpjn8c\wheels\2c\24\2f\b6952a64d3b9a28ed8501709df290eb4c7f8a198940eb7c495
  Building wheel for peewee (setup.py) ... done
  Created wheel for peewee: filename=peewee-3.15.4-py3-none-any.whl size=134778 sha256=693e0dfb20f33a76d56e2d342025b80b4f11fef9d6906c204632a516d4a5aada
  Stored in directory: c:\users\qgb\appdata\local\pip\cache\wheels\54\74\ab\677da1f27ba931a5004373dbe2663fc82023b8dc9dd2ad603c
Successfully built howtrader peewee
Installing collected packages: simplejson, shiboken6, PySide6-Essentials, PySide6-Addons, PySide6, pyqtgraph, qdarkstyle, peewee, pymongo, seaborn, deap, tenacity, plotly, howtrader
Successfully installed PySide6-6.4.2 PySide6-Addons-6.4.2 PySide6-Essentials-6.4.2 deap-1.3.3 howtrader-3.3.0 peewee-3.15.4 plotly-5.13.0 pymongo-4.3.3 pyqtgraph-0.12.4 qdarkstyle-3.1 seaborn-0.12.2 shiboken6-6.4.2 simplejson-3.18.3 tenacity-8.2.1
Note: you may need to restart the kernel to use updated packages.

In [200]: !python C:\test\tv\howtraderT.py
Traceback (most recent call last):
  File "C:\test\tv\howtraderT.py", line 3, in <module>
    from howtrader.trader.engine import MainEngine
  File "C:\QGB\Anaconda3\lib\site-packages\howtrader\trader\engine.py", line 26, in <module>
    from .gateway import BaseGateway
  File "C:\QGB\Anaconda3\lib\site-packages\howtrader\trader\gateway.py", line 18, in <module>
    from .object import (
  File "C:\QGB\Anaconda3\lib\site-packages\howtrader\trader\object.py", line 10, in <module>
    from .constant import Direction, Exchange, Interval, Offset, Status, Product, OptionType, OrderType
  File "C:\QGB\Anaconda3\lib\site-packages\howtrader\trader\constant.py", line 7, in <module>
    from tzlocal import get_localzone_name
ImportError: cannot import name 'get_localzone_name' from 'tzlocal' (C:\QGB\Anaconda3\lib\site-packages\tzlocal\__init__.py)



第6课运行 main.py 的时候报错

您好,我在class 6 运行main.py 的时候报错,麻烦帮着看看,谢谢。
(mytrader) PS E:\07个人材料\量化学习\19bitquant\VNPY数字货币量化交易从零到实盘\course_codes-main\class_06> python main.py
Traceback (most recent call last):
File "F:\anaconda\envs\mytrader\lib\site-packages\aiohttp\client_reqrep.py", line 70, in
import cchardet as chardet
ModuleNotFoundError: No module named 'cchardet'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "E:\07个人材料\量化学习\19bitquant\VNPY数字货币量化交易从零到实盘\course_codes-main\class_06\main.py", line 7, in
from howtrader.gateway.binance import BinanceUsdtGateway, BinanceSpotGateway, BinanceInverseGateway
File "F:\anaconda\envs\mytrader\lib\site-packages\howtrader\gateway\binance_init_.py", line 1, in
from .binance_spot_gateway import BinanceSpotGateway
File "F:\anaconda\envs\mytrader\lib\site-packages\howtrader\gateway\binance\binance_spot_gateway.py", line 41, in
from howtrader.api.rest import RestClient, Request, Response
File "F:\anaconda\envs\mytrader\lib\site-packages\howtrader\api\rest_init_.py", line 1, in
from .rest_client import RestClient, Request, Response
File "F:\anaconda\envs\mytrader\lib\site-packages\howtrader\api\rest\rest_client.py", line 19, in
from aiohttp import ClientSession, ClientResponse
File "F:\anaconda\envs\mytrader\lib\site-packages\aiohttp_init_.py", line 6, in
from .client import (
File "F:\anaconda\envs\mytrader\lib\site-packages\aiohttp\client.py", line 59, in
from .client_reqrep import (
File "F:\anaconda\envs\mytrader\lib\site-packages\aiohttp\client_reqrep.py", line 72, in
import charset_normalizer as chardet # type: ignore[no-redef]
File "F:\anaconda\envs\mytrader\lib\site-packages\charset_normalizer_init_.py", line 23, in
from charset_normalizer.api import from_fp, from_path, from_bytes, normalize
File "F:\anaconda\envs\mytrader\lib\site-packages\charset_normalizer\api.py", line 10, in
from charset_normalizer.md import mess_ratio
AttributeError: partially initialized module 'charset_normalizer' has no attribute 'md__mypyc' (most likely due to a circular import)

使用新增的okx接口,登录时调用query_open_orders函数,总是报超时的错误

登录时会调用query_open_orders函数,总是报错超时,初步debug发现是sign中的msg不对,修改sign函数如下
def sign(self, request: Request) -> Request:
"""signature"""

    now: datetime = datetime.utcnow()
    now = now - timedelta(milliseconds=self.time_offset_ms)
    timestamp: str = now.isoformat("T", "milliseconds") + "Z"


    if request.params:
        path: str = request.path + "?" + urlencode(request.params)
    else:
        path: str = request.path

    if request.data:
        request.data = json.dumps(request.data)
        msg: str = timestamp + request.method + path + request.data
    else:
        msg: str = timestamp + request.method + path

    signature: bytes = generate_signature(msg, self.secret)

问题依然没有解决,怀疑取到timestamp之后过了很久才向服务器发送请求

按教程安装的qt报错,找不到问题在哪,请指教!

Traceback (most recent call last):
File "C:\Users\Administrator\Desktop\learnhowtrader\main_window.py", line 80, in
main()
File "C:\Users\Administrator\Desktop\learnhowtrader\main_window.py", line 52, in main
qapp = create_qapp()
File "C:\ProgramData\Anaconda3\envs\mytrader\lib\site-packages\howtrader\trader\ui\qt.py", line 28, in create_qapp
qapp.setStyleSheet(qdarkstyle.load_stylesheet(qt_api="pyside6"))
File "C:\ProgramData\Anaconda3\envs\mytrader\lib\site-packages\qdarkstyle_init_.py", line 364, in load_stylesheet
stylesheet = load_stylesheet(qt_api=qt_api, palette=palette)
File "C:\ProgramData\Anaconda3\envs\mytrader\lib\site-packages\qdarkstyle_init
.py", line 237, in _load_stylesheet
from qtpy.QtCore import QCoreApplication, QFile, QTextStream
File "C:\ProgramData\Anaconda3\envs\mytrader\lib\site-packages\qtpy\QtCore.py", line 116, in
Qt.MidButton = Qt.MouseButton.MiddleButton = Qt.MiddleButton
File "shibokensupport/enum_310.py", line 529, in setattr
AttributeError: Cannot reassign members.

cannot import name 'get_localzone_name' from 'tzlocal' 老师麻烦问下这个问题怎么解决 谢谢

C:\Users\admin\anaconda3\envs\howtrader-main\python.exe C:/Users/admin/strategies/btctest.py Traceback (most recent call last): File "C:\Users\admin\strategies\btctest.py", line 1, in <module> from howtrader.app.cta_strategy import ( File "E:\howtrader-main\howtrader\app\cta_strategy\__init__.py", line 4, in <module> from .base import APP_NAME, StopOrder File "E:\howtrader-main\howtrader\app\cta_strategy\base.py", line 11, in <module> from howtrader.trader.constant import Direction, Offset, Interval File "E:\howtrader-main\howtrader\trader\constant.py", line 7, in <module> from tzlocal import get_localzone_name ImportError: cannot import name 'get_localzone_name' from 'tzlocal' (C:\Users\admin\anaconda3\envs\howtrader-main\lib\site-packages\tzlocal\__init__.py)

可以支持“双向持仓模式“吗

51bitquant老师,您好

在您的"howtrader-gateway-binance_usdt_gateway.py"文件里有一个on_query_position_side()函数,具体代码如下:

def on_query_position_side(self, data: dict, request: Request) -> None:

if data.get("dualSidePosition", False): # true will means dual position side

self.set_position_side() # set dualSidePosition to False

这段代码表示如果我原先的dualSidePosition为True的话也会通过set_position_side()函数被设置成False, 我想请教一下howtrader是否支持双向持仓模式呢?因为有的时候策略需要在同一个标的上持有反向仓位(同时持有一个多仓和一个空仓),而在单向持仓模式下就会变成不持有任何方向上的仓位。

提前感谢您的回答,
祝好~~~

回测时遇到了问题,提示如下

17:30:06 策略初始化完成
17:30:06 策略回测失败,触发异常:
Traceback (most recent call last):
File "D:\Anaconda\envs\vnpy\lib\site-packages\howtrader\app\cta_backtester\engine.py", line 161, in run_backtesting
engine.run_backtesting()
File "D:\Anaconda\envs\vnpy\lib\site-packages\howtrader\app\cta_strategy\backtesting.py", line 295, in run_backtesting
self.strategy.on_start()
File "D:\Anaconda\envs\vnpy\lib\site-packages\howtrader\app\cta_strategy\strategies\spot_simple_grid_strategy.py", line 64, in on_start
self.cta_engine.event_engine.register(EVENT_TIMER, self.process_timer_event)
AttributeError: 'BacktestingEngine' object has no attribute 'event_engine'

VNPY更新

请问如何在Ubuntu下更新VNPY版本?

回测导入日K线,会出现丢失数据的情况。

1。开始时间为20190102,这种情况会丢失20192/1、2019/3/4、2019/4/4、2019/5/5等数据,每隔30天丢失一下。
engine.set_parameters(
vt_symbol="btcusdt.BINANCE", #交易的标的, 现货的数据
interval=Interval.DAILY,
start=datetime(2019,1,2), # 开始时间
end=datetime(2020,7,1), # 结束时间
rate=1/1000, # 手续费, 币安手续费千分之1, BNB 万7.5 7.5/10000
slippage=0, # 交易滑点
size=1, # 合约乘数
pricetick=0.01, # 价格精度.
capital=1_000_000) # 初始资金

2。开始时间为20190101,这种情况会丢失2019/1/31、2019/3/3、2019/4/3、2019/5/4等数据,每隔30天丢失一下。
engine.set_parameters(
vt_symbol="btcusdt.BINANCE", #交易的标的, 现货的数据
interval=Interval.DAILY,
start=datetime(2019,1,1), # 开始时间
end=datetime(2020,7,1), # 结束时间
rate=1/1000, # 手续费, 币安手续费千分之1, BNB 万7.5 7.5/10000
slippage=0, # 交易滑点
size=1, # 合约乘数
pricetick=0.01, # 价格精度.
capital=1_000_000) # 初始资金

PortfolioStrategyApp不能正常使用的问题

背景:希望在策略中订阅多个交易对的信息,cta策略不能支持;尝试使用PortfolioStrategyApp模块,不能正常使用。
暂时的处理:发现主要原因是以下库的缺失:from howtrader.trader.datafeed import BaseDatafeed, get_datafeed。故将代码中的 BaseDatafeed去掉,通过ui成功点进PortfolioStrategyApp模块,script端未测试。
问题:这样子的魔改是否可以正常使用PortfolioStrategyApp模块;魔改代码前该模块不能运行,是因为笔误文件缺失,还是因为什么原因将该模块移除呢?
以上,望解答

python main.py启动似乎异常

您好,我使用的操作系统是ubuntu20.04 server版本的,安装过程参考您的文档,最后启动的是这样的,这样是正常的吗
image
image

backtester

你好,新代码为什么把ui的backtester删掉了,是因为有bug吗

启动图形化界面后,会不停的403 forbidden错误

您好,在我启动图形化界面后,成功连接现货和合约账号后,在pycharm的运行界面会一直报错,如下图,同时不能够获取交易对的行情和下单,symbol那一项点不动,无法输入。
image

最开始以为是代理的问题,但使用这个代理能够在shell里ping通api.binancn.com

启动main_window 报某个包内错误

报错:
Traceback (most recent call last):
File "C:\work\my_howtrade\main.py", line 80, in
main()
File "C:\work\my_howtrade\main.py", line 68, in main
main_window = MainWindow(main_engine, event_engine)
File "C:\Users\64278\anaconda3\envs\mytrader\lib\site-packages\howtrader\trader\ui\mainwindow.py", line 51, in init
self.init_ui()
File "C:\Users\64278\anaconda3\envs\mytrader\lib\site-packages\howtrader\trader\ui\mainwindow.py", line 56, in init_ui
self.init_dock()
File "C:\Users\64278\anaconda3\envs\mytrader\lib\site-packages\howtrader\trader\ui\mainwindow.py", line 63, in init_dock
self.trading_widget, trading_dock = self.create_dock(
File "C:\Users\64278\anaconda3\envs\mytrader\lib\site-packages\howtrader\trader\ui\mainwindow.py", line 234, in create_dock
dock.setFeatures(dock.DockWidgetFloatable | dock.DockWidgetMovable)
AttributeError: 'PySide6.QtWidgets.QDockWidget' object has no attribute 'DockWidgetFloatable'

具体出问题的包:from howtrader.trader.ui import MainWindow
具体出问题的源码:
def create_dock(
self,
widget_class: QtWidgets.QWidget,
name: str,
area: int
) -> Tuple[QtWidgets.QWidget, QtWidgets.QDockWidget]:
"""
Initialize a dock widget.
"""
widget: QtWidgets.QWidget = widget_class(self.main_engine, self.event_engine)

    dock: QtWidgets.QDockWidget = QtWidgets.QDockWidget(name)
    dock.setWidget(widget)
    dock.setObjectName(name)
    **dock.setFeatures(dock.DockWidgetFloatable | dock.DockWidgetMovable)**
    self.addDockWidget(area, dock)
    return widget, dock

send_order失败后的处理(没有重试?)

hello,我看到很多基础下单函数(buy、short等)最后都会调用send_order函数。而send_order如果失败(eg. Timestamp for this request is outside of the recvWindow.),好像并不会重试,这块有考虑过优化吗。

mainengine

mainengine主引擎代码中少了一个get_contract的方法,converter.py里就有调用主引擎的get_contract方法

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.