项目介绍
本文提供一种量化交易思路,震荡行情下表现优异。具体操作思路如下:
短线快速上冲或下砸时视为主力洗盘行为,超过临界值时反向开平仓,洗盘力度大小决定开平仓与否和数量。
临界值是一个随着时间增长的减函数,取值区间为1~60分钟,例如1分钟的临界值为2.5,5分钟的临界值约为4,而60分钟的临界值仅为10。如果行情波动超过这些临界值则计算多空指数。若指数大于预设值则发出开平仓指令。
import matplotlib.pyplot as plt
import pandas as pd
import MetaTrader5 as mt5
import pymt5
import time
from datetime import datetime
from datetime import timedelta
import pytz
import numpy as np
import math
import os
# 连接到MetaTrader 5
if not mt5.initialize():
print("initialize() failed")
# 登陆mt5
authorized = mt5.login(39304351, "heniu1me", "MetaQuotes-Demo")
if authorized:
print("MetaTrader5 package author: ", mt5.__author__)
print("MetaTrader5 package version: ", mt5.__version__)
else:
print("login failed")
exit(0)
# 创建当前订单csv文件
if not os.path.exists("current orders.csv"):
dataframe = pd.DataFrame(
columns=("Time", "Type", "Volume", "Price", "sl", "tp", "Note")
)
dataframe.to_csv("current orders.csv", index=False)
# 创建平仓单csv文件
if not os.path.exists("history records.csv"):
dataframe = pd.DataFrame(
columns=(
"Opentime",
"Closetime",
"Type",
"Volume",
"Openprice",
"Closeprice",
"sl",
"tp",
"Note",
)
)
dataframe.to_csv("history records.csv", index=False)
class TradingStratege(object):
"""docstring for TradingStratege
Args:
symbol:交易品种
timeframe:K线周期
period:用于策略分析的时间序列长度(单位hours)
target:止盈止损目标,与建仓价格的距离
index1~index3:触发开平仓指令的指数水平
vol1~vol3:对应的3个交易量
max_position:最大仓位
"""
def __init__(
self,
symbol,
timeframe,
period,
sl_target,
tp_target,
index1,
index2,
index3,
vol1,
vol2,
vol3,
max_position,
):
self.symbol = symbol
self.timeframe = timeframe
self.period = period
self.sl_target = sl_target
self.tp_target = tp_target
self.index1 = index1
self.index2 = index2
self.index3 = index3
self.vol1 = vol1
self.vol2 = vol2
self.vol3 = vol3
self.max_position = max_position
# 获取指定品种历史数据
def get_data(self, symbol, timeframe, period):
mt5_timeframe = mt5.TIMEFRAME_M1
if timeframe == "M1":
mt5_timeframe = mt5.TIMEFRAME_M1
elif timeframe == "M5":
mt5_timeframe = mt5.TIMEFRAME_M5
elif timeframe == "M15":
mt5_timeframe = mt5.TIMEFRAME_M15
elif timeframe == "M30":
mt5_timeframe = mt5.TIMEFRAME_M30
elif timeframe == "H1":
mt5_timeframe = mt5.TIMEFRAME_H1
elif timeframe == "H4":
mt5_timeframe = mt5.TIMEFRAME_H4
elif timeframe == "D1":
mt5_timeframe = mt5.TIMEFRAME_D1
# 将时区设置为GMT-2
timezone = pytz.timezone("Etc/GMT-2")
# 调节时间与mt5上的now相对应
now = datetime.now(timezone) + timedelta(hours=2)
time_from = now - timedelta(hours=period)
# 获取最新1小时内约60根一分钟K线数据
rates = mt5.copy_rates_range(symbol, mt5_timeframe, time_from, now)
# 获取指定品种最新报价
lasttick = mt5.symbol_info_tick(symbol)
# 将数据存储在数组中
Last_price = []
High_price = []
Low_price = []
for price_data in rates:
last_price = lasttick.bid
open_price = price_data[1]
high_price = price_data[2]
low_price = price_data[3]
close_price = price_data[4]
Last_price.append(last_price)
High_price.append(high_price)
Low_price.append(low_price)
Lasttick = np.array([lasttick[0], lasttick[1], lasttick[2]])
# 返回数组
return Last_price, High_price, Low_price, Lasttick
# 获取30s内最高和最低价,用于检查是否触发止损止盈
def getticks(self):
timezone = pytz.timezone("Etc/GMT-2")
now = datetime.now(timezone) + timedelta(hours=2)
time_from = now - timedelta(seconds=30)
# request 100 XAUUSD ticks starting from 30s before.
ticks = mt5.copy_ticks_from(self.symbol, time_from, 100, mt5.COPY_TICKS_ALL)
Bid = []
Ask = []
for x in ticks:
bid = x[1]
ask = x[2]
Bid.append(bid)
Ask.append(ask)
bid_min = min(Bid)
bid_max = max(Bid)
ask_min = min(Ask)
ask_max = max(Ask)
ticks = np.array([bid_min, bid_max, ask_min, ask_max])
return ticks
# 计算短线多空指数
def checkprice(self, last_price, high_price, low_price):
# 计算上涨和下跌幅度
decrease = np.array(high_price) - np.array(last_price)
increase = np.array(last_price) - np.array(low_price)
# 创建一个以时间距离为变量的减函数拟合出正常波动范围
refer = self.normal_fluctuation(increase)
time_len1 = np.arange(len(increase), 0, -1)
time_len2 = np.arange(len(decrease), 0, -1)
# 筛选出符合条件的数据
filter1 = increase > refer
filter2 = decrease > refer
fil_inc = increase[filter1]
fil_dec = decrease[filter2]
fil_time1 = time_len1[filter1]
fil_time2 = time_len2[filter2]
# 计算短线多空指数
index_delta1 = self.inc_warn(fil_inc, fil_time1, time_len1)
index_delta2 = self.dec_warn(fil_dec, fil_time2, time_len2)
return index_delta1, index_delta2
# 每个10分钟时间段选取一条提示信息,并返回短线做空指标
def inc_warn(self, fil_inc, fil_time, time_len):
# 判断是否为空数组
if not np.size(fil_inc) == 0:
i = 0
z = int(len(time_len) / 10)
index = 0
index_delta = 0
# 以10分钟为单位对时间进行切割
while i < z + 1:
# 将时间数组切割为z部分,得到索引数组
mask = np.logical_and(fil_time <= (i + 1) * 10, fil_time > i * 10)
j = fil_inc[mask]
if not np.size(j) == 0:
maxx = np.max(j)
# 用索引公式查找时间数组中的元素
point = fil_time