BotVS趋势交易策略-MACD

MACD低买高卖自动跟单滑动止损策略 , 基于Python实现。

交叉后前一柱指金叉后的第一柱的值, 交叉后前一柱指金叉前的最后一个柱的值, 滑动价格指下单时加的价格,比如买单会现价加上这个价格,卖单会减去这个价格

参数

BotVS趋势交易策略-MACD

代码

import math
import time
import datetime

def Fixed(v):
    return math.floor(v*1000)/1000

# 取消指定ID号的订单
def WaitOrder(exchange, orderId, timeoutToCancel):
    t = time.time()
    ts = int(round(t * 1000))
    while True:
        Sleep(3000);
        orderInfo = exchange.GetOrder(orderId);
        if (not orderInfo):
            continue;

        if (orderInfo.Status == ORDER_STATE_CLOSED or orderInfo.Status == ORDER_STATE_CANCELED):
            return orderInfo;

        t = time.time()
        if ((int(round(t * 1000)) - ts) > timeoutToCancel):
            exchange.CancelOrder(orderId);

# 买入
def Buy(exchange, maxPrice, slidePrice, balanceRatio, timeoutS):
    t = time.time()
    ts = int(round(t * 1000))
    account = None;
    dealAmount = 0.0;
    usedBlance = 0.0;
    maxBalanceUse = 0.0;
    isFirst = True;
    while True:
        if (isFirst):
            isFirst = False;
        else:
            Sleep(3000);

        ticker = exchange.GetTicker();
        if (not ticker):
            continue;

        buyPrice = ticker.Sell + slidePrice;

        # Price too high, wait...
        if (buyPrice > maxPrice):
            continue;

        # Initialize at first
        if (account is None):
            account = exchange.GetAccount();
            if (not account):
                continue;

            # Initialize maxBalanceUse
            maxBalanceUse = account.Balance * balanceRatio;

        buyAmount = Fixed((maxBalanceUse - usedBlance) / buyPrice);
        if (buyAmount < exchange.GetMinStock()):
            break;

        orderId = exchange.Buy(buyPrice, buyAmount);
        if (not orderId):
            Log(buyPrice, buyAmount, maxBalanceUse, usedBlance);
            continue;

        orderInfo = WaitOrder(exchange, orderId, timeoutS);
        dealAmount += orderInfo.DealAmount;
        usedBlance += orderInfo.Price * orderInfo.DealAmount;
        if (orderInfo.Status == ORDER_STATE_CLOSED):
            break;

        t = time.time()
        if ((int(round(t * 1000)) - ts) < timeoutS):
            break

    return {'amount': dealAmount, 'price': (usedBlance / dealAmount  if dealAmount > 0  else 0)};

# 卖出
def Sell(exchange, sellAmount, slidePrice):
    # Account info must set
    account = exchange.GetAccount();
    while (not account):
        Sleep(2000);
        account = exchange.GetAccount();

    sellAmount = min(sellAmount, account.Stocks);

    cash = 0.0;
    remain = sellAmount;

    while (remain >= exchange.GetMinStock()):
        ticker = exchange.GetTicker();
        if (not ticker):
            Sleep(2000);
            continue;

        sellPrice = ticker.Buy - slidePrice;
        sellOrderId = exchange.Sell(sellPrice, remain);
        if (not sellOrderId):
            Sleep(2000);
            continue;

        orderInfo = WaitOrder(exchange, sellOrderId, 10000);
        remain -= orderInfo.DealAmount;
        cash += orderInfo.Price * orderInfo.DealAmount;

    return {'amount': sellAmount, 'price': (cash / sellAmount if sellAmount > 0 else 0)};

BuyInfo = None;
BanlanceRatio = 1.0;
Profit = 0.0;
timeAtBuy = 0;

def onTick(exchange):
    global BuyInfo, BanlanceRatio, Profit, timeAtBuy
    ticker = exchange.GetTicker();
    records = exchange.GetRecords();
    if (not ticker or not records or len(records) < 45):
        return;

    ticks = [];
    for i in range(len(records)):
        ticks.append(records[i].Close);

    macd = TA.MACD(records, 12, 26, 9);
    dif = macd[0];
    dea = macd[1];
    his = macd[2];

    op = 0;
    if (BuyInfo is None):
        # 判断买入条件, macd柱由下翻上(由红转绿)
        if (dif[len(ticks)-1] > 0 and his[len(ticks)-1] > ac1 and his[len(ticks)-2] < bc1):
            op = 1;
    else:
        # 卖出条件,昨天跌、今天跌、今天低于昨天
        if (records[len(records)-2].Time > timeAtBuy and records[len(records)-1].Close < records[len(records)-1].Open - 0.5
                and records[len(records)-2].Close < records[len(records)-2].Open - 0.5
                and records[len(records)-1].Close < records[len(records)-2].Close - 0.5):
            op = 2;
        # 当前价跌破成本价、今天跌
        elif (records[len(records)-2].Time > timeAtBuy and BuyInfo['price'] > records[len(records)-1].Close and records[len(records)-1].Close < records[len(records)-1].Open - 0.5):
            op = 2;
        # 成本价低于最新价 或者 dif 小于0  、his小于0 ???
        elif ((BuyInfo['price'] < ticker.Last or dif[len(ticks)-1] < 0) and his[len(ticks)-1] <= 0):
            op = 2;
        # 当前价跌破成本价、达到止损点
        elif ((BuyInfo['price'] > ticker.Last) and ((BuyInfo['price'] - ticker.Last) / BuyInfo['price'] > TrailingStop)):
            op = 2;

    if (op == 1):       # 买入
        info = Buy(exchange, ticker.Sell + (SlidePrice * 3), SlidePrice, BanlanceRatio, orderTimeout * 1000);
        # Log(info);
        # Log(ticker);
        # Log(type(info));
        # Log(type(ticker));
        if (info['amount'] > 0):
            BuyInfo = info;
            timeAtBuy = records[len(records)-1].Time;

    elif (op == 2):    # 卖出
        info = Sell(exchange, BuyInfo['amount'], SlidePrice);
        if (info['amount'] > 0):
            Profit += info['amount'] * (info['price'] - BuyInfo['price']);
            LogProfit(Profit);
            BuyInfo = null;

def main():
    account = exchange.GetAccount();
    if (account):
        Log(exchange.GetName(), exchange.GetCurrency(), account);

    while (True):
        onTick(exchange);
        Sleep(30000);
上一篇:Metricbeat 轻量型指标采集器


下一篇:多周期MACD趋势共振制作的方法