MFI Indicator — Day Trading Strategies for Crypto Coins with Python by using Binance Data
Greetings fellow cryptocurrency traders and algotrading fans! I’m excited to share with you my latest experimentation in the world of day trading strategies. This time, I’ve delved into the realm of the Money Flow Index (MFI) indicator, and I’m thrilled to report my findings.
If you’re a fan of my previous article on testing day trading strategies with the Relative Strength Index (RSI) indicator, then you’re in for a real treat. In this article, I’ll walk you through my process of testing MFI strategies with the power of Python and Binance data.
So, buckle up and get ready to dive into the data-driven world of cryptocurrency day trading!
Disclaimer: Please note that I am not a professional trading advisor, and the information provided in this article is based on my personal experience and opinions. The crypto market is highly volatile and subject to unpredictable changes, and there is a risk of losing your investment. Please do your own research and seek professional advice before making any investment decisions. The information presented in this article should not be treated as investment advice, and all readers are responsible for their own investment decisions.
Foundations
I have decided to use Binance trading data for the top 20 cryptocurrencies based on their market cap. The data range I have chosen covers the last 100 days and I will be using 30-minute candle intervals to calculate technical indicators.
The assumption of the tests is that I’m spending the same amount of money on each BUY action (let’s say 100 dollars)
As we embark on this journey together, I want to assure you that I’ll be following the same script structure as in my previous article. However, I’ve made some tweaks to make the simulation even more informative and insightful. I’ve selected the Money Flow Index (MFI) as my test subject, as I’m particularly fond of this indicator. It takes into consideration not only the price of the asset, but also the volume dynamics, which I believe provides a more comprehensive picture of market activity.
The MFI indicator is a technical analysis tool that uses both price and volume data to measure buying and selling pressure. By combining these two factors, the MFI provides a more in-depth look into market sentiment and helps traders identify potential trend reversals. In this article, we’ll explore how the MFI can be used in the world of cryptocurrency day trading, and how Python and Binance data can be leveraged to test MFI-based trading strategies.
I will be utilizing several Python modules, including python-binance, pandas, pandas-ta, and matplotlib. These modules are essential tools for traders and offer a wealth of functionality for data analysis and visualization.
To install these modules, you can simply run the following command in your terminal or command prompt:
pip install python-binance pandas pandas-ta matplotlib
And that’s it! So, let’s get started!
First Test
For our first test, we’ll be utilizing various MFI values as triggers for BUY or SELL activities. This means that we’ll be setting certain MFI levels as entry or exit points for our simulated trades. By doing this, we can observe how different MFI values affect the performance of our trading strategies and make informed decisions based on the data.
MFI parameters:
mfi_lengths = [20, 30, 40]
buy_limits = [50, 60, 70] # BUY SIGNAL if the indicated value is crossed in positive direction
sell_limits = [75, 85,95] # SELL SIGNAL if the indicated value is crossed in negative direction
loss_stop_limits = [15, 20, 25] # SELL SIGNAL if the indicated value is crossed in negative direction
Python code:
import pandas as pd
import matplotlib.pyplot as plt
import time
import pandas_ta as pta
from binance.client import Client
from pprint import pprint
api_key = "YOUR_BINANCE_API_KEY"
api_secret = "YOUR_BINANCE_API_SECRET"
client = Client(api_key, api_secret)
def get_data_frame(symbol='BTCUSDT', period='30m', timeframe='1 hours ago UTC'):
try:
bars = client.get_historical_klines(symbol, period, timeframe)
except Exception as e:
print('GET Data error', symbol)
print(e)
time.sleep(5)
bars = client.get_historical_klines(symbol, period, timeframe)
for line in bars:
del line[7:]
df = pd.DataFrame(bars, columns=['open_time', 'open',
'high', 'low', 'close',
'volume', 'close_time'])
df['close'] = df['close'].apply(pd.to_numeric)
df['open'] = df['open'].apply(pd.to_numeric)
df['high'] = df['high'].apply(pd.to_numeric)
df['low'] = df['low'].apply(pd.to_numeric)
df['volume'] = df['volume'].apply(pd.to_numeric)
df['close_time'] = df['close_time'].apply(pd.to_numeric) / 1000
return df
top_coins = ['BTCUSDT', 'ETHUSDT', 'BNBUSDT', 'XRPUSDT',
'ADAUSDT', 'DOGEUSDT', 'MATICUSDT', 'SOLUSDT',
'DOTUSDT', 'LTCUSDT', 'SHIBUSDT', 'AVAXUSDT',
'DAIUSDT', 'TRXUSDT', 'UNIUSDT', 'ATOMUSDT',
'LINKUSDT', 'ETCUSDT', 'XMRUSDT', 'APTUSDT']
trading_data = {}
# retrieve Binance trade data
for coin in top_coins:
trading_data[coin] = get_data_frame(symbol=coin, period='30m',
timeframe='100 days ago UTC')
# placeholder variable
winner_config = {'profit_ave':False, 'parameters':''}
# Generate trading Signals
mfi_lengths = [20, 30, 40]
buy_limits = [50, 60, 70] # BUY SIGNAL if the indicated value is crossed in positive direction
sell_limits = [75, 85,95] # SELL SIGNAL if the indicated value is crossed in negative direction
loss_stop_limits = [15, 20, 25] # SELL SIGNAL if the indicated value is crossed in negative direction
for length in mfi_lengths:
# adding trading indicator to the trading data set
for coin in top_coins:
trading_data[coin]['mfi'] = pta.mfi(high=trading_data[coin]['high'],
low=trading_data[coin]['low'],
close=trading_data[coin]['close'],
volume=trading_data[coin]['volume'], length=length)
for buy_limit in buy_limits:
for sell_limit in sell_limits:
for loss_stop_limit in loss_stop_limits:
total_profit = []
total_profit_coin_ref = []
for coin in top_coins:
trading_data[coin]['trading_signal'] = '-'
# generate BUY and SELL signals
try:
trading_data[coin].loc[(trading_data[coin]['mfi'] > buy_limit) &
(trading_data[coin]['mfi'].shift() < buy_limit),
'trading_signal'] = 'BUY'
trading_data[coin].loc[((trading_data[coin]['mfi'] < sell_limit) &
(trading_data[coin]['mfi'].shift() > sell_limit)) |
((trading_data[coin]['mfi'] < loss_stop_limit) &
(trading_data[coin]['mfi'].shift() > loss_stop_limit)),
'trading_signal'] = 'SELL'
except:
continue
purchase_price = 0
profit_list = []
# run trading simulation across the data set and use trading signals as triggers
for i in range(len(trading_data[coin])):
if trading_data[coin].iloc[i]['trading_signal'] == 'BUY' and purchase_price == 0:
purchase_price = trading_data[coin].iloc[i]['close']
if purchase_price != 0:
profit = round(((trading_data[coin].iloc[i]['close'] / purchase_price) * 100) - 100, 2)
# Sell if Profit drops below set limit or trading signal indicates SELL
if trading_data[coin].iloc[i]['trading_signal'] == 'SELL':
profit_list.append(profit)
purchase_price = 0
total_profit.append(round(sum(profit_list),2))
total_profit_coin_ref.append(f'{coin} {round(sum(profit_list),2)}%')
if winner_config['profit_ave'] == False:
winner_config['profit_ave'] = round(sum(total_profit)/len(total_profit),2)
winner_config['parameters'] = f'MFI Parameters: LENGTH: {length}, ' \
f'BUY: {buy_limit}, SELL: {sell_limit}, ' \
f'LOSS STOP: {loss_stop_limit}'
elif round(sum(total_profit)/len(total_profit),2) > winner_config['profit_ave']:
winner_config['profit_ave'] = round(sum(total_profit) / len(total_profit), 2)
winner_config['parameters'] = f'MFI Parameters: LENGTH: {length}, ' \
f'BUY: {buy_limit}, SELL: {sell_limit}, ' \
f'LOSS STOP: {loss_stop_limit}'
print(f'Overall Average Profit: {round(sum(total_profit)/len(total_profit),2)}%, '
f'MFI Parameters: LENGTH: {length}, BUY: {buy_limit}, SELL: {sell_limit}, '
f'LOSS STOP: {loss_stop_limit},\nDetails: {total_profit_coin_ref}\n')
print(f'WINNER! with average profit {winner_config["profit_ave"]}%')
print(winner_config['parameters'])
Output:
---
Truncated output... feel free to run it yourself for more details
---
Overall Average Profit: 7.77%, MFI Parameters: LENGTH: 40, BUY: 70, SELL: 85, LOSS STOP: 20,
Details: ['BTCUSDT 0%', 'ETHUSDT 0%', 'BNBUSDT -25.7%', 'XRPUSDT -23.77%', 'ADAUSDT -13.38%', 'DOGEUSDT 15.06%', 'MATICUSDT -8.18%', 'SOLUSDT 24.66%', 'DOTUSDT 0.11%', 'LTCUSDT 30.12%', 'SHIBUSDT 37.59%', 'AVAXUSDT -14.88%', 'DAIUSDT 0%', 'TRXUSDT -28.96%', 'UNIUSDT -6.23%', 'ATOMUSDT 6.4%', 'LINKUSDT -15.07%', 'ETCUSDT -4.64%', 'XMRUSDT 0%', 'APTUSDT 182.21%']
Overall Average Profit: 19.35%, MFI Parameters: LENGTH: 40, BUY: 70, SELL: 85, LOSS STOP: 25,
Details: ['BTCUSDT 0%', 'ETHUSDT 13.78%', 'BNBUSDT 15.66%', 'XRPUSDT -21.5%', 'ADAUSDT -5.58%', 'DOGEUSDT 28.07%', 'MATICUSDT 20.02%', 'SOLUSDT 53.02%', 'DOTUSDT 5.05%', 'LTCUSDT 36.49%', 'SHIBUSDT 32.66%', 'AVAXUSDT 19.12%', 'DAIUSDT 0%', 'TRXUSDT -14.19%', 'UNIUSDT 13.95%', 'ATOMUSDT -2.48%', 'LINKUSDT -17.25%', 'ETCUSDT -8.51%', 'XMRUSDT 9.15%', 'APTUSDT 209.5%']
Overall Average Profit: -3.01%, MFI Parameters: LENGTH: 40, BUY: 70, SELL: 95, LOSS STOP: 15,
Details: ['BTCUSDT 0%', 'ETHUSDT 0%', 'BNBUSDT 0%', 'XRPUSDT -25.04%', 'ADAUSDT 0%', 'DOGEUSDT 23.08%', 'MATICUSDT 0%', 'SOLUSDT 0%', 'DOTUSDT 0%', 'LTCUSDT 0%', 'SHIBUSDT 0%', 'AVAXUSDT -24.85%', 'DAIUSDT 0%', 'TRXUSDT -25.26%', 'UNIUSDT -8.07%', 'ATOMUSDT 0%', 'LINKUSDT 0%', 'ETCUSDT 0%', 'XMRUSDT 0%', 'APTUSDT 0%']
Overall Average Profit: -13.86%, MFI Parameters: LENGTH: 40, BUY: 70, SELL: 95, LOSS STOP: 20,
Details: ['BTCUSDT 0%', 'ETHUSDT 0%', 'BNBUSDT -20.77%', 'XRPUSDT -23.77%', 'ADAUSDT -44.91%', 'DOGEUSDT 15.06%', 'MATICUSDT -8.18%', 'SOLUSDT -60.44%', 'DOTUSDT -32.63%', 'LTCUSDT 22.1%', 'SHIBUSDT 0%', 'AVAXUSDT 8.18%', 'DAIUSDT 0%', 'TRXUSDT -28.96%', 'UNIUSDT -0.27%', 'ATOMUSDT -33.22%', 'LINKUSDT -16.22%', 'ETCUSDT -15.23%', 'XMRUSDT 0%', 'APTUSDT -38.01%']
Overall Average Profit: 25.27%, MFI Parameters: LENGTH: 40, BUY: 70, SELL: 95, LOSS STOP: 25,
Details: ['BTCUSDT 0%', 'ETHUSDT 13.78%', 'BNBUSDT 21.91%', 'XRPUSDT -21.5%', 'ADAUSDT -1.46%', 'DOGEUSDT 28.07%', 'MATICUSDT 20.02%', 'SOLUSDT 71.69%', 'DOTUSDT 6.37%', 'LTCUSDT 15.44%', 'SHIBUSDT -27.04%', 'AVAXUSDT 42.7%', 'DAIUSDT 0%', 'TRXUSDT -14.19%', 'UNIUSDT 8.46%', 'ATOMUSDT -7.23%', 'LINKUSDT -18.09%', 'ETCUSDT -6.34%', 'XMRUSDT 9.15%', 'APTUSDT 363.72%']
WINNER! with average profit 31.21%
MFI Parameters: LENGTH: 30, BUY: 60, SELL: 95, LOSS STOP: 25
WINNER! with average profit: 31.21%
MFI Parameters: LENGTH: 30, BUY: 60, SELL: 95, LOSS STOP: 25
Second Test
For our next test, we’ll be introducing a fixed stop loss at a 5% loss (forced sell). A stop loss is a critical component of any trading strategy, as it helps to minimize potential losses and protect your capital. By setting a fixed stop loss, we can ensure that our trades are automatically closed if they reach a certain level of loss, reducing the risk of a significant financial hit.
MFI parameters:
mfi_lengths = [20, 30, 40]
buy_limits = [50, 60, 70] # BUY SIGNAL if the indicated value is crossed in positive direction
sell_limits = [75, 85,95] # SELL SIGNAL if the indicated value is crossed in negative direction
loss_stop_limits = [15, 20, 25] # SELL SIGNAL if the indicated value is crossed in negative direction
loss_stop_in_percent = -5
Python code:
import pandas as pd
import matplotlib.pyplot as plt
import time
import pandas_ta as pta
from binance.client import Client
from pprint import pprint
api_key = "YOUR_BINANCE_API_KEY"
api_secret = "YOUR_BINANCE_API_SECRET"
client = Client(api_key, api_secret)
def get_data_frame(symbol='BTCUSDT', period='30m', timeframe='1 hours ago UTC'):
try:
bars = client.get_historical_klines(symbol, period, timeframe)
except Exception as e:
print('GET Data error', symbol)
print(e)
time.sleep(5)
bars = client.get_historical_klines(symbol, period, timeframe)
for line in bars:
del line[7:]
df = pd.DataFrame(bars, columns=['open_time', 'open',
'high', 'low', 'close',
'volume', 'close_time'])
df['close'] = df['close'].apply(pd.to_numeric)
df['open'] = df['open'].apply(pd.to_numeric)
df['high'] = df['high'].apply(pd.to_numeric)
df['low'] = df['low'].apply(pd.to_numeric)
df['volume'] = df['volume'].apply(pd.to_numeric)
df['close_time'] = df['close_time'].apply(pd.to_numeric) / 1000
return df
top_coins = ['BTCUSDT', 'ETHUSDT', 'BNBUSDT', 'XRPUSDT',
'ADAUSDT', 'DOGEUSDT', 'MATICUSDT', 'SOLUSDT',
'DOTUSDT', 'LTCUSDT', 'SHIBUSDT', 'AVAXUSDT',
'DAIUSDT', 'TRXUSDT', 'UNIUSDT', 'ATOMUSDT',
'LINKUSDT', 'ETCUSDT', 'XMRUSDT', 'APTUSDT']
trading_data = {}
# retrieve Binance trade data
for coin in top_coins:
trading_data[coin] = get_data_frame(symbol=coin, period='30m',
timeframe='100 days ago UTC')
# placeholder variable
winner_config = {'profit_ave':False, 'parameters':''}
# Generate trading Signals
mfi_lengths = [20, 30, 40]
buy_limits = [50, 60, 70] # BUY SIGNAL if the indicated value is crossed in positive direction
sell_limits = [75, 85,95] # SELL SIGNAL if the indicated value is crossed in negative direction
loss_stop_limits = [15, 20, 25] # SELL SIGNAL if the indicated value is crossed in negative direction
loss_stop_in_percent = -5
for length in mfi_lengths:
# adding trading indicator to the trading data set
for coin in top_coins:
trading_data[coin]['mfi'] = pta.mfi(high=trading_data[coin]['high'],
low=trading_data[coin]['low'],
close=trading_data[coin]['close'],
volume=trading_data[coin]['volume'], length=length)
for buy_limit in buy_limits:
for sell_limit in sell_limits:
for loss_stop_limit in loss_stop_limits:
total_profit = []
total_profit_coin_ref = []
for coin in top_coins:
trading_data[coin]['trading_signal'] = '-'
# generate BUY and SELL signals
try:
trading_data[coin].loc[(trading_data[coin]['mfi'] > buy_limit) &
(trading_data[coin]['mfi'].shift() < buy_limit),
'trading_signal'] = 'BUY'
trading_data[coin].loc[((trading_data[coin]['mfi'] < sell_limit) &
(trading_data[coin]['mfi'].shift() > sell_limit)) |
((trading_data[coin]['mfi'] < loss_stop_limit) &
(trading_data[coin]['mfi'].shift() > loss_stop_limit)),
'trading_signal'] = 'SELL'
except:
continue
purchase_price = 0
profit_list = []
# run trading simulation across the data set and use trading signals as triggers
for i in range(len(trading_data[coin])):
if trading_data[coin].iloc[i]['trading_signal'] == 'BUY' and purchase_price == 0:
purchase_price = trading_data[coin].iloc[i]['close']
if purchase_price != 0:
profit = round(((trading_data[coin].iloc[i]['close'] / purchase_price) * 100) - 100, 2)
# Sell if Profit drops below set limit or trading signal indicates SELL
if trading_data[coin].iloc[i]['trading_signal'] == 'SELL' or profit < loss_stop_in_percent:
if profit < loss_stop_in_percent:
profit = loss_stop_in_percent
profit_list.append(profit)
purchase_price = 0
total_profit.append(round(sum(profit_list),2))
total_profit_coin_ref.append(f'{coin} {round(sum(profit_list),2)}%')
if winner_config['profit_ave'] == False:
winner_config['profit_ave'] = round(sum(total_profit)/len(total_profit),2)
winner_config['parameters'] = f'MFI Parameters: LENGTH: {length}, ' \
f'BUY: {buy_limit}, SELL: {sell_limit}, ' \
f'LOSS STOP: {loss_stop_limit}'
elif round(sum(total_profit)/len(total_profit),2) > winner_config['profit_ave']:
winner_config['profit_ave'] = round(sum(total_profit) / len(total_profit), 2)
winner_config['parameters'] = f'MFI Parameters: LENGTH: {length}, ' \
f'BUY: {buy_limit}, SELL: {sell_limit}, ' \
f'LOSS STOP: {loss_stop_limit}'
print(f'Overall Average Profit: {round(sum(total_profit)/len(total_profit),2)}%, '
f'MFI Parameters: LENGTH: {length}, BUY: {buy_limit}, SELL: {sell_limit}, '
f'LOSS STOP: {loss_stop_limit},\nDetails: {total_profit_coin_ref}\n')
print(f'WINNER! with average profit {winner_config["profit_ave"]}%')
print(winner_config['parameters'])
Output:
---
Truncated output... feel free to run it yourself for more details
---
Overall Average Profit: 13.87%, MFI Parameters: LENGTH: 40, BUY: 70, SELL: 85, LOSS STOP: 20,
Details: ['BTCUSDT -5%', 'ETHUSDT -10%', 'BNBUSDT -8.73%', 'XRPUSDT -35%', 'ADAUSDT -1.52%', 'DOGEUSDT 29.9%', 'MATICUSDT -16.9%', 'SOLUSDT 61.01%', 'DOTUSDT 0.33%', 'LTCUSDT 15.82%', 'SHIBUSDT 22.33%', 'AVAXUSDT 21.81%', 'DAIUSDT 0%', 'TRXUSDT -22.11%', 'UNIUSDT 6.08%', 'ATOMUSDT 14.41%', 'LINKUSDT 17.14%', 'ETCUSDT 2.7%', 'XMRUSDT -5%', 'APTUSDT 190.22%']
Overall Average Profit: 22.01%, MFI Parameters: LENGTH: 40, BUY: 70, SELL: 85, LOSS STOP: 25,
Details: ['BTCUSDT -5%', 'ETHUSDT 18.87%', 'BNBUSDT 21.94%', 'XRPUSDT -32.76%', 'ADAUSDT -0.52%', 'DOGEUSDT 41.53%', 'MATICUSDT 16.05%', 'SOLUSDT 36.34%', 'DOTUSDT 7.88%', 'LTCUSDT 15.82%', 'SHIBUSDT 22.69%', 'AVAXUSDT 28.58%', 'DAIUSDT 0%', 'TRXUSDT -8.36%', 'UNIUSDT 25.71%', 'ATOMUSDT 4.69%', 'LINKUSDT 20.03%', 'ETCUSDT 1.04%', 'XMRUSDT 19.92%', 'APTUSDT 205.78%']
Overall Average Profit: -18.41%, MFI Parameters: LENGTH: 40, BUY: 70, SELL: 95, LOSS STOP: 15,
Details: ['BTCUSDT -5%', 'ETHUSDT -10%', 'BNBUSDT -15%', 'XRPUSDT -35%', 'ADAUSDT -35%', 'DOGEUSDT 13.08%', 'MATICUSDT -25%', 'SOLUSDT -15%', 'DOTUSDT -45%', 'LTCUSDT -15%', 'SHIBUSDT -25%', 'AVAXUSDT -29.04%', 'DAIUSDT 0%', 'TRXUSDT -27.79%', 'UNIUSDT -4.38%', 'ATOMUSDT -20%', 'LINKUSDT -15%', 'ETCUSDT -30%', 'XMRUSDT -5%', 'APTUSDT -25%']
Overall Average Profit: -7.37%, MFI Parameters: LENGTH: 40, BUY: 70, SELL: 95, LOSS STOP: 20,
Details: ['BTCUSDT -5%', 'ETHUSDT -10%', 'BNBUSDT -15%', 'XRPUSDT -35%', 'ADAUSDT -33.05%', 'DOGEUSDT 29.9%', 'MATICUSDT -16.9%', 'SOLUSDT -11.36%', 'DOTUSDT -38.35%', 'LTCUSDT 1.13%', 'SHIBUSDT -25%', 'AVAXUSDT 44.87%', 'DAIUSDT 0%', 'TRXUSDT -22.11%', 'UNIUSDT 13.56%', 'ATOMUSDT -20%', 'LINKUSDT 20.06%', 'ETCUSDT 4.88%', 'XMRUSDT -5%', 'APTUSDT -25%']
Overall Average Profit: 29.53%, MFI Parameters: LENGTH: 40, BUY: 70, SELL: 95, LOSS STOP: 25,
Details: ['BTCUSDT -5%', 'ETHUSDT 18.87%', 'BNBUSDT 23.53%', 'XRPUSDT -32.76%', 'ADAUSDT 3.6%', 'DOGEUSDT 41.53%', 'MATICUSDT 16.05%', 'SOLUSDT 62.65%', 'DOTUSDT 9.2%', 'LTCUSDT -5.36%', 'SHIBUSDT -28.3%', 'AVAXUSDT 52.16%', 'DAIUSDT 0%', 'TRXUSDT -8.36%', 'UNIUSDT 20.22%', 'ATOMUSDT 0.08%', 'LINKUSDT 23.34%', 'ETCUSDT 3.21%', 'XMRUSDT 19.92%', 'APTUSDT 375.93%']
WINNER! with average profit 36.92%
MFI Parameters: LENGTH: 30, BUY: 50, SELL: 95, LOSS STOP: 25
WINNER! with average profit: 36.92%
MFI Parameters: LENGTH: 30, BUY: 50, SELL: 95, LOSS STOP: 25 Loss Stop Profit Drop: -5%
Final Test
For our next and final test, we’ll be focusing on fine-tuning the winning parameters to see if we can find an even sweeter spot for better profits. This means that we’ll be taking the most successful strategies from our previous tests and making small adjustments to see if we can further optimize their performance.
MFI parameters:
mfi_lengths = [27, 30, 33]
buy_limits = [45, 50, 55] # BUY SIGNAL if the indicated value is crossed in positive direction
sell_limits = [90,95,99] # SELL SIGNAL if the indicated value is crossed in negative direction
loss_stop_limits = [23, 25, 27] # SELL SIGNAL if the indicated value is crossed in negative direction
loss_stop_in_percent = -5
Python code:
import pandas as pd
import matplotlib.pyplot as plt
import time
import pandas_ta as pta
from binance.client import Client
from pprint import pprint
api_key = "YOUR_BINANCE_API_KEY"
api_secret = "YOUR_BINANCE_API_SECRET"
client = Client(api_key, api_secret)
def get_data_frame(symbol='BTCUSDT', period='30m', timeframe='1 hours ago UTC'):
try:
bars = client.get_historical_klines(symbol, period, timeframe)
except Exception as e:
print('GET Data error', symbol)
print(e)
time.sleep(5)
bars = client.get_historical_klines(symbol, period, timeframe)
for line in bars:
del line[7:]
df = pd.DataFrame(bars, columns=['open_time', 'open',
'high', 'low', 'close',
'volume', 'close_time'])
df['close'] = df['close'].apply(pd.to_numeric)
df['open'] = df['open'].apply(pd.to_numeric)
df['high'] = df['high'].apply(pd.to_numeric)
df['low'] = df['low'].apply(pd.to_numeric)
df['volume'] = df['volume'].apply(pd.to_numeric)
df['close_time'] = df['close_time'].apply(pd.to_numeric) / 1000
return df
top_coins = ['BTCUSDT', 'ETHUSDT', 'BNBUSDT', 'XRPUSDT',
'ADAUSDT', 'DOGEUSDT', 'MATICUSDT', 'SOLUSDT',
'DOTUSDT', 'LTCUSDT', 'SHIBUSDT', 'AVAXUSDT',
'DAIUSDT', 'TRXUSDT', 'UNIUSDT', 'ATOMUSDT',
'LINKUSDT', 'ETCUSDT', 'XMRUSDT', 'APTUSDT']
trading_data = {}
# retrieve Binance trade data
for coin in top_coins:
trading_data[coin] = get_data_frame(symbol=coin, period='30m',
timeframe='100 days ago UTC')
# placeholder variable
winner_config = {'profit_ave':False, 'parameters':''}
# Generate trading Signals
mfi_lengths = [27, 30, 33]
buy_limits = [45, 50, 55] # BUY SIGNAL if the indicated value is crossed in positive direction
sell_limits = [90,95,99] # SELL SIGNAL if the indicated value is crossed in negative direction
loss_stop_limits = [23, 25, 27] # SELL SIGNAL if the indicated value is crossed in negative direction
loss_stop_in_percent = -5
for length in mfi_lengths:
# adding trading indicator to the trading data set
for coin in top_coins:
trading_data[coin]['mfi'] = pta.mfi(high=trading_data[coin]['high'],
low=trading_data[coin]['low'],
close=trading_data[coin]['close'],
volume=trading_data[coin]['volume'], length=length)
for buy_limit in buy_limits:
for sell_limit in sell_limits:
for loss_stop_limit in loss_stop_limits:
total_profit = []
total_profit_coin_ref = []
for coin in top_coins:
trading_data[coin]['trading_signal'] = '-'
# generate BUY and SELL signals
try:
trading_data[coin].loc[(trading_data[coin]['mfi'] > buy_limit) &
(trading_data[coin]['mfi'].shift() < buy_limit),
'trading_signal'] = 'BUY'
trading_data[coin].loc[((trading_data[coin]['mfi'] < sell_limit) &
(trading_data[coin]['mfi'].shift() > sell_limit)) |
((trading_data[coin]['mfi'] < loss_stop_limit) &
(trading_data[coin]['mfi'].shift() > loss_stop_limit)),
'trading_signal'] = 'SELL'
except:
continue
purchase_price = 0
profit_list = []
# run trading simulation across the data set and use trading signals as triggers
for i in range(len(trading_data[coin])):
if trading_data[coin].iloc[i]['trading_signal'] == 'BUY' and purchase_price == 0:
purchase_price = trading_data[coin].iloc[i]['close']
if purchase_price != 0:
profit = round(((trading_data[coin].iloc[i]['close'] / purchase_price) * 100) - 100, 2)
# Sell if Profit drops below set limit or trading signal indicates SELL
if trading_data[coin].iloc[i]['trading_signal'] == 'SELL' or profit < loss_stop_in_percent:
if profit < loss_stop_in_percent:
profit = loss_stop_in_percent
profit_list.append(profit)
purchase_price = 0
total_profit.append(round(sum(profit_list),2))
total_profit_coin_ref.append(f'{coin} {round(sum(profit_list),2)}%')
if winner_config['profit_ave'] == False:
winner_config['profit_ave'] = round(sum(total_profit)/len(total_profit),2)
winner_config['parameters'] = f'MFI Parameters: LENGTH: {length}, ' \
f'BUY: {buy_limit}, SELL: {sell_limit}, ' \
f'LOSS STOP: {loss_stop_limit}'
elif round(sum(total_profit)/len(total_profit),2) > winner_config['profit_ave']:
winner_config['profit_ave'] = round(sum(total_profit) / len(total_profit), 2)
winner_config['parameters'] = f'MFI Parameters: LENGTH: {length}, ' \
f'BUY: {buy_limit}, SELL: {sell_limit}, ' \
f'LOSS STOP: {loss_stop_limit}'
print(f'Overall Average Profit: {round(sum(total_profit)/len(total_profit),2)}%, '
f'MFI Parameters: LENGTH: {length}, BUY: {buy_limit}, SELL: {sell_limit}, '
f'LOSS STOP: {loss_stop_limit},\nDetails: {total_profit_coin_ref}\n')
print(f'WINNER! with average profit {winner_config["profit_ave"]}%')
print(winner_config['parameters'])
Output:
---
Truncated output... feel free to run it yourself for more details
---
Overall Average Profit: 35.59%, MFI Parameters: LENGTH: 33, BUY: 55, SELL: 95, LOSS STOP: 27,
Details: ['BTCUSDT 31.06%', 'ETHUSDT 20.42%', 'BNBUSDT 3.32%', 'XRPUSDT 4.13%', 'ADAUSDT -14.77%', 'DOGEUSDT 81.95%', 'MATICUSDT 1.67%', 'SOLUSDT 70.49%', 'DOTUSDT -1.82%', 'LTCUSDT 62.71%', 'SHIBUSDT 4.09%', 'AVAXUSDT 41.13%', 'DAIUSDT 0%', 'TRXUSDT 6.95%', 'UNIUSDT 2.66%', 'ATOMUSDT 6.16%', 'LINKUSDT 28.23%', 'ETCUSDT -8.48%', 'XMRUSDT 7.67%', 'APTUSDT 364.24%']
Overall Average Profit: 11.09%, MFI Parameters: LENGTH: 33, BUY: 55, SELL: 99, LOSS STOP: 23,
Details: ['BTCUSDT -6.7%', 'ETHUSDT 31.56%', 'BNBUSDT 7.19%', 'XRPUSDT -20.29%', 'ADAUSDT -1.29%', 'DOGEUSDT 64.12%', 'MATICUSDT -13.94%', 'SOLUSDT 85.33%', 'DOTUSDT -1.64%', 'LTCUSDT 27.57%', 'SHIBUSDT 5.36%', 'AVAXUSDT 42.06%', 'DAIUSDT 0%', 'TRXUSDT 3.51%', 'UNIUSDT 24.54%', 'ATOMUSDT 9.24%', 'LINKUSDT 25.65%', 'ETCUSDT -8.29%', 'XMRUSDT 5.45%', 'APTUSDT -57.66%']
Overall Average Profit: 33.27%, MFI Parameters: LENGTH: 33, BUY: 55, SELL: 99, LOSS STOP: 25,
Details: ['BTCUSDT -8.87%', 'ETHUSDT 32.65%', 'BNBUSDT 10.0%', 'XRPUSDT -6.09%', 'ADAUSDT -0.08%', 'DOGEUSDT 82.97%', 'MATICUSDT -5.66%', 'SOLUSDT 76.45%', 'DOTUSDT 3.04%', 'LTCUSDT 26.2%', 'SHIBUSDT 12.3%', 'AVAXUSDT 40.85%', 'DAIUSDT 0%', 'TRXUSDT 6.52%', 'UNIUSDT -0.06%', 'ATOMUSDT 6.03%', 'LINKUSDT 19.21%', 'ETCUSDT -3.76%', 'XMRUSDT 6.9%', 'APTUSDT 366.83%']
Overall Average Profit: 35.59%, MFI Parameters: LENGTH: 33, BUY: 55, SELL: 99, LOSS STOP: 27,
Details: ['BTCUSDT 31.06%', 'ETHUSDT 20.42%', 'BNBUSDT 3.32%', 'XRPUSDT 4.13%', 'ADAUSDT -14.77%', 'DOGEUSDT 81.95%', 'MATICUSDT 1.67%', 'SOLUSDT 70.49%', 'DOTUSDT -1.82%', 'LTCUSDT 62.71%', 'SHIBUSDT 4.09%', 'AVAXUSDT 41.13%', 'DAIUSDT 0%', 'TRXUSDT 6.95%', 'UNIUSDT 2.66%', 'ATOMUSDT 6.16%', 'LINKUSDT 28.23%', 'ETCUSDT -8.48%', 'XMRUSDT 7.67%', 'APTUSDT 364.24%']
WINNER! with average profit 40.35%
MFI Parameters: LENGTH: 27, BUY: 55, SELL: 95, LOSS STOP: 25
WINNER! with average profit: 40.35%
MFI Parameters: LENGTH: 27, BUY: 55, SELL: 95, LOSS STOP: 25 Profit Loss Stop: -5%
Summary
I hope you’ve enjoyed this journey into the world of cryptocurrency day trading and MFI-based strategies. I’ve shared with you the power of Python and Binance data, and how these tools can be used to test and evaluate trading strategies. And I hope that this article has helped to shed some light on this topic.
If you’ve found this article to be informative and helpful, I’d love it if you would follow my channel and join the newsletter. I’ll be sharing more articles and insights into the world of crypto trading, and I’d be honored to have you along for the ride.