BotVS趨勢交易策略-MACD


 MACD低買高賣自動跟單滑動止損策略 , 基於Python實現。

 

交叉后前一柱指金叉后的第一柱的值, 交叉后前一柱指金叉前的最后一個柱的值, 滑動價格指下單時加的價格,比如買單會現價加上這個價格,賣單會減去這個價格

 

參數

 

 

代碼

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);

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM