数字货币MACD指标自动化交易策略实现(含源代码)

前情回顾

在前面我们实现了2中方法进行数字货币交易,同时还能获取到实时行情。数字货币交易接口实现(含源代码)

在此基础上,我们今天实现一个指标策略自动化交易的功能(以MACD指标为例),并进行2次优化,增加仓位管理以及风险控制的功能,实现一个完成的交易策略。

MACD 策略逻辑

  1. 获取 5 分钟的 K 线数据
  2. 计算 MACD 指标
  3. 买入条件:MACD 越过零线
  4. 卖出条件:MACD 低于零线

代码实现

import ccxt
import pandas as pd
import ta
import time

# 初始化 Binance 交易所实例
exchange = ccxt.binance({
    'apiKey': 'YOUR_API_KEY',        # 替换为你的 API Key
    'secret': 'YOUR_SECRET_KEY',     # 替换为你的 Secret Key
})

# 获取 5 分钟的 K 线数据
def fetch_ohlcv(symbol, timeframe='5m', limit=100):
    ohlcv = exchange.fetch_ohlcv(symbol, timeframe, limit=limit)
    df = pd.DataFrame(ohlcv, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
    df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
    df.set_index('timestamp', inplace=True)
    return df

# 计算 MACD 指标
def calculate_macd(df):
    macd = ta.trend.MACD(df['close'])
    df['macd'] = macd.macd()
    df['macd_signal'] = macd.macd_signal()
    df['macd_diff'] = macd.macd_diff()

# 检查交易信号
def check_trade_signals(df):
    last_row = df.iloc[-1]
    previous_row = df.iloc[-2]
    
    # 买入条件:MACD 越过零线
    if previous_row['macd'] < 0 and last_row['macd'] > 0:
        return 'buy'
    
    # 卖出条件:MACD 低于零线
    if previous_row['macd'] > 0 and last_row['macd'] < 0:
        return 'sell'
    
    return 'hold'

# 执行交易
def execute_trade(signal, symbol='BTC/USDT', amount=0.001):
    if signal == 'buy':
        order = exchange.create_market_buy_order(symbol, amount)
        print('Buy order executed:', order)
    elif signal == 'sell':
        order = exchange.create_market_sell_order(symbol, amount)
        print('Sell order executed:', order)

# 主循环
def main():
    symbol = 'BTC/USDT'
    while True:
        df = fetch_ohlcv(symbol)
        calculate_macd(df)
        calculate_ema(df)
        calculate_kdj(df)
        signal = check_trade_signals(df)
        execute_trade(signal)
        time.sleep(300)  # 每5分钟运行一次

if __name__ == "__main__":
    main()

代码说明

1、初始化 Binance 交易所实例:使用你的 API Key 和 Secret Key 初始化 ccxt 库中的 Binance 实例。

2、获取 5 分钟的 K 线数据:定义 fetch_ohlcv 函数,从 Binance 获取指定交易对的 5 分钟 K 线数据,并将其转换为 Pandas DataFrame。

3、计算 MACD 指标:定义相应的函数计算这些技术指标,并将其添加到 DataFrame 中。

4、检查交易信号:定义 check_trade_signals 函数,根据 MACD 越过零线和低于零线的条件检查交易信号。

5、执行交易:定义 execute_trade 函数,根据交易信号执行买入或卖出操作。

6、主循环:在 main 函数中,每隔5分钟获取最新数据,计算指标,检查信号,并执行交易。

请注意,这段代码仅为示例,实际交易时应考虑更多因素,例如交易量、手续费、风控等,后面分两步进行完善。

增加仓位管理逻辑

上述执行交易函数存在明显的漏洞,只有开仓动作,没有平仓动作。所以新增一条交易逻辑:当没有持有信号方向的持仓时才进行开仓;如果有信号方向的持仓就进行平仓。

这就需要增加仓位管理的逻辑,实现获取仓位的接口。

代码实现

import ccxt
import pandas as pd
import ta
import time

# 初始化 Binance 交易所实例
exchange = ccxt.binance({
    'apiKey': 'YOUR_API_KEY',        # 替换为你的 API Key
    'secret': 'YOUR_SECRET_KEY',     # 替换为你的 Secret Key
})

# 获取 5 分钟的 K 线数据
def fetch_ohlcv(symbol, timeframe='5m', limit=100):
    ohlcv = exchange.fetch_ohlcv(symbol, timeframe, limit=limit)
    df = pd.DataFrame(ohlcv, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
    df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
    df.set_index('timestamp', inplace=True)
    return df

# 计算 MACD 指标
def calculate_macd(df):
    macd = ta.trend.MACD(df['close'])
    df['macd'] = macd.macd()
    df['macd_signal'] = macd.macd_signal()
    df['macd_diff'] = macd.macd_diff()

# 检查交易信号
def check_trade_signals(df):
    last_row = df.iloc[-1]
    previous_row = df.iloc[-2]
    
    # 买入条件:MACD 越过零线
    if previous_row['macd'] < 0 and last_row['macd'] > 0:
        return 'buy'
    
    # 卖出条件:MACD 低于零线
    if previous_row['macd'] > 0 and last_row['macd'] < 0:
        return 'sell'
    
    return 'hold'

# 获取当前持仓方向和数量
def get_position(symbol):
    balance = exchange.fetch_balance()
    if symbol in balance['total']:
        return balance['total'][symbol]
    return 0

# 执行交易
def execute_trade(signal, symbol='BTC/USDT', amount=0.001):
    base_currency = symbol.split('/')[0]
    position = get_position(base_currency)
    
    if signal == 'buy':
        if position <= 0:
            order = exchange.create_market_buy_order(symbol, amount)
            print('Buy order executed:', order)
        else:
            print('Already holding a buy position. No action taken.')
    elif signal == 'sell':
        if position > 0:
            order = exchange.create_market_sell_order(symbol, amount)
            print('Sell order executed:', order)
        else:
            print('No buy position to sell. No action taken.')

# 主循环
def main():
    symbol = 'BTC/USDT'
    while True:
        df = fetch_ohlcv(symbol)
        calculate_macd(df)
        calculate_ema(df)
        calculate_kdj(df)
        signal = check_trade_signals(df)
        execute_trade(signal, symbol)
        time.sleep(300)  # 每5分钟运行一次

if __name__ == "__main__":
    main()

修改说明

1、获取当前持仓方向和数量:添加 get_position 函数,获取当前账户的持仓情况。如果持有目标资产(如 BTC),返回持有数量,否则返回 0。

2、修改交易逻辑:在 execute_trade 函数中,根据信号检查当前持仓:

  • 如果是买入信号(‘buy’),且当前没有持有或持有空头仓位,则进行买入操作。
  • 如果是卖出信号(‘sell’),且当前持有多头仓位,则进行卖出操作。

3、主循环:保持不变,每隔 5 分钟获取最新数据,计算指标,检查信号,并执行交易。

请注意,这段代码仍然是一个简化的示例。在实际交易中,还需要考虑更多的细节和异常处理,例如 API 调用失败、交易失败、网络问题等。另外,务必在模拟环境中进行充分测试,确保策略的可靠性和安全性。

增加风险控制功能

增加风险控制功能也就是止盈止损的逻辑:

  • 持仓盈利超过5%,则平仓
  • 持仓亏损超过3%,则平仓

代码实现

import ccxt
import pandas as pd
import ta
import time

# 初始化 Binance 交易所实例
exchange = ccxt.binance({
    'apiKey': 'YOUR_API_KEY',        # 替换为你的 API Key
    'secret': 'YOUR_SECRET_KEY',     # 替换为你的 Secret Key
})

# 获取 5 分钟的 K 线数据
def fetch_ohlcv(symbol, timeframe='5m', limit=100):
    ohlcv = exchange.fetch_ohlcv(symbol, timeframe, limit=limit)
    df = pd.DataFrame(ohlcv, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
    df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
    df.set_index('timestamp', inplace=True)
    return df

# 计算 MACD 指标
def calculate_macd(df):
    macd = ta.trend.MACD(df['close'])
    df['macd'] = macd.macd()
    df['macd_signal'] = macd.macd_signal()
    df['macd_diff'] = macd.macd_diff()

# 检查交易信号
def check_trade_signals(df):
    last_row = df.iloc[-1]
    previous_row = df.iloc[-2]
    
    # 买入条件:MACD 越过零线
    if previous_row['macd'] < 0 and last_row['macd'] > 0:
        return 'buy'
    
    # 卖出条件:MACD 低于零线
    if previous_row['macd'] > 0 and last_row['macd'] < 0:
        return 'sell'
    
    return 'hold'

# 获取当前持仓方向和数量
def get_position(symbol):
    balance = exchange.fetch_balance()
    base_currency = symbol.split('/')[0]
    if base_currency in balance['total']:
        return balance['total'][base_currency]
    return 0

# 计算持仓盈亏比例
def calculate_profit_loss(entry_price, current_price):
    return (current_price - entry_price) / entry_price

# 执行交易
def execute_trade(signal, symbol='BTC/USDT', amount=0.001, entry_price=None):
    base_currency = symbol.split('/')[0]
    position = get_position(symbol)
    
    if signal == 'buy':
        if position <= 0:
            order = exchange.create_market_buy_order(symbol, amount)
            print('Buy order executed:', order)
            entry_price = order['price']
        else:
            print('Already holding a buy position. No action taken.')
    elif signal == 'sell':
        if position > 0:
            order = exchange.create_market_sell_order(symbol, amount)
            print('Sell order executed:', order)
            entry_price = None
        else:
            print('No buy position to sell. No action taken.')

    # 止盈止损逻辑
    if entry_price:
        ticker = exchange.fetch_ticker(symbol)
        current_price = ticker['last']
        profit_loss_ratio = calculate_profit_loss(entry_price, current_price)

        if profit_loss_ratio >= 0.05:  # 止盈条件
            if position > 0:
                order = exchange.create_market_sell_order(symbol, amount)
                print('Take profit order executed:', order)
                entry_price = None
        elif profit_loss_ratio <= -0.03:  # 止损条件
            if position > 0:
                order = exchange.create_market_sell_order(symbol, amount)
                print('Stop loss order executed:', order)
                entry_price = None

# 主循环
def main():
    symbol = 'BTC/USDT'
    entry_price = None
    while True:
        df = fetch_ohlcv(symbol)
        calculate_macd(df)
        calculate_ema(df)
        calculate_kdj(df)
        signal = check_trade_signals(df)
        execute_trade(signal, symbol, entry_price=entry_price)
        time.sleep(300)  # 每5分钟运行一次

if __name__ == "__main__":
    main()

修改说明

1、计算持仓盈亏比例:添加 calculate_profit_loss 函数,计算当前持仓的盈亏比例。

2、止盈止损逻辑:在 execute_trade 函数中,添加止盈和止损逻辑:

  • 如果当前持仓的盈利比例大于等于 5% (profit_loss_ratio >= 0.05),则执行止盈平仓操作。
  • 如果当前持仓的亏损比例小于等于 -3% (profit_loss_ratio <= -0.03),则执行止损平仓操作。

3、更新 execute_trade 函数:在买入和卖出操作中记录或清除 entry_price,以便在止盈止损逻辑中使用。

4、主循环中传递 entry_price:在 main 函数中,每次调用 execute_trade 函数时传递 entry_price 参数。

如果说还要继续优化的话,可能增加动态止盈的功能,后面有时间在进一步优化。

  • 26
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值