Altn
Altn

Reputation: 19

Fixing a python bot for making it suitable for futures trading on Binance

I am a novice coder who tries to learn and definitely struggle. I trade for almost 10 years and now trying to automate it. Encountered generous "Part Time Larry" and tried to update his code to make it suitable for futures. It can generate signals perfectly but I am having problems with the Long(buy)/Short(sell) orders (a def check_buy_sell_signals( df ) part). Any help will be highly appreciated. All credits to "Part Time Larry"

import ccxt
import config
import schedule
import pandas as pd
pd.set_option('display.max_rows', None)
from datetime import datetime
import time
import numpy as np
import warnings
warnings.filterwarnings('ignore')
#binancefutures
exchange = ccxt.binanceusdm({
    'apiKey': 'apiKey',
    'secret': 'secret',
})
lev = exchange.set_leverage(10, 'ETH/USDT')
def tr(data):
    data['previous_close']=data['close'].shift(1)
    data['high-low']=abs(data['high'] - data['low'])
    data['high-pc']=abs(data['high'] - data['previous_close'])
    data['low-pc']=abs(data['low']-data['previous_close'])
    tr=data[['high-low', 'high-pc', 'low-pc']].max(axis=1)
    return tr
def atr(data, period=10):#supertrend variables
    data['tr']=tr(data)
    print("calculate average true range")
    atr=data['tr'].rolling(period).mean()
    return atr
def supertrend(df, period=10, atr_multiplier=1.4):
    hl2=(df['high']+df['low'])/2
    print("calculating supertrend")
    df['atr']=atr(df, period=period)
    df['upperband']= hl2 + (atr_multiplier*df['atr'])
    df['lowerband']= hl2 -(atr_multiplier*df['atr'])
    df['in_uptrend']=True
    for current in range(1, len(df.index)):
        previous=current-1
        if df['close'][current] > df['upperband'][previous]:
            df['in_uptrend'][current]=True
        elif df['close'][current] < df['lowerband'][previous]:
            df['in_uptrend'][current]=False
        else:
            df['in_uptrend'][current] = df['in_uptrend'][previous]
            if df['in_uptrend'][current] and df['lowerband'][current] < df['lowerband'][previous]:
                df['lowerband'][current] = df['lowerband'][previous]
            if not df['in_uptrend'][current] and df['upperband'][current] > df['upperband'][previous]:
                df['upperband'][current] = df['upperband'][previous]
    return(df)
global in_position
def check_buy_sell_signals(df):
    in_position = False
    to_use = (exchange.fetch_balance().get('USDT').get('free'))
    price = ((exchange.fetchTicker('ETH/USDT').get('last')))-10
    bal = to_use / price
    print("Checking for buy or sell signals")
    print(df.tail(5))
    last_row_index = len(df.index)- 1
    previous_row_index = last_row_index - 1
    if not df['in_uptrend'][previous_row_index] and df['in_uptrend'][last_row_index]:
            print("changed to uptrend, buy")
            if not in_position:
                order = exchange.create_market_buy_order('ETH/USDT', bal)
                print(order)
                in_position = True
    if df['in_uptrend'][previous_row_index] and not df['in_uptrend'][last_row_index]:
            print("changed to downtrend, sell")
            if not in_position:
                order = exchange.create_market_sell_order('ETH/USDT', bal)
                print(order)
                in_position = True
    if df['in_uptrend'][previous_row_index] and not df['in_uptrend'][last_row_index]:
            print("trend changed")
            if in_position:
                close_position = binance.create_order(symbol=symbol, type="MARKET", side="sell", amount=pos['positionAmt'], params={"reduceOnly": True})
                print(order)
                in_position = False
    if not df['in_uptrend'][previous_row_index] and df['in_uptrend'][last_row_index]:
            print("trend changed")
            if in_position:
                order = exchange.create_market_buy_order('ETH/USDT', bal)
                close_position = binance.create_order(symbol=symbol, type="MARKET", side="buy", amount=pos['positionAmt'], params={"reduceOnly": True})
                print(order)
                in_position = False
def run_bot():
    print("Fetching new bars for", datetime.now())
    bars = exchange.fetch_ohlcv('ETH/USDT', timeframe='1h', limit=100)
    df = pd.DataFrame(bars[:-1], columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
    df['timestamp']=pd.to_datetime(df['timestamp'], unit='ms')
    supertrend_data = supertrend(df)
    check_buy_sell_signals(supertrend_data)
schedule.every(1).minutes.do(run_bot)
while True:
    schedule.run_pending()
    time.sleep(1)

Upvotes: 1

Views: 1001

Answers (1)

user3666197
user3666197

Reputation: 1

This answer removes the cardinal error, from the as-is code, to avoid its flawed operation ( original losing its STATEFUL-ness due to such a hidden error ) :

import ccxt
import time
import config
import schedule
import numpy  as np
import pandas as pd; pd.set_option( 'display.max_rows', None )
import warnings;     warnings.filterwarnings( 'ignore' )

from   datetime import datetime
from   my_code  import tr, atr, supertrend, run_bot
from   fut_sig  import check_buy_sell_signals

#binancefutures
exchange = ccxt.binanceusdm( { 'apiKey': 'apiKey',
                               'secret': 'secret',
                                }
                             )
lev = exchange.set_leverage( 10, 'ETH/USDT' )
#----------------------------------#
global in_position                 # it does not save you here
#----------------------------------# on global scope

schedule.every( 1 ).minutes.do( run_bot )

while True:
    schedule.run_pending()
    time.sleep( 1 )

The problem is here, inside the function-scope, if it were not declared global here, a new symbol in_trade will get associated with a value of False and within the scope of such function, all changes thereof will be related to such local-scope symbol - i.e. effectively masking the "global" variable, as was defined on the global-scope. Explicit notation of respecting a global one - as in a statement global in_position here, provides the Python Interpreter an explicit direction not to try to do anything else, but operate with the already existing, defined global symbol(s) whenever it meets a symbol-name "having a same name" :

fut_sig.py :

def check_buy_sell_signals(df):
    #------------------------------# it would get masked here
    global in_position             # if not DECLARED to be a global
    #------------------------------# so avoiding a new, local one from masking it
    in_position = False
    to_use = (exchange.fetch_balance().get('USDT').get('free'))
    price = ((exchange.fetchTicker('ETH/USDT').get('last')))-10
    bal = to_use / price
    print("Checking for buy or sell signals")
    print(df.tail(5))
    last_row_index = len(df.index)- 1
    previous_row_index = last_row_index - 1
    if not df['in_uptrend'][previous_row_index] and df['in_uptrend'][last_row_index]:
            print("changed to uptrend, buy")
            if not in_position:
                order = exchange.create_market_buy_order('ETH/USDT', bal)
                print(order)
                in_position = True
    if df['in_uptrend'][previous_row_index] and not df['in_uptrend'][last_row_index]:
            print("changed to downtrend, sell")
            if not in_position:
                order = exchange.create_market_sell_order('ETH/USDT', bal)
                print(order)
                in_position = True
    if df['in_uptrend'][previous_row_index] and not df['in_uptrend'][last_row_index]:
            print("trend changed")
            if in_position:
                close_position = binance.create_order(symbol=symbol, type="MARKET", side="sell", amount=pos['positionAmt'], params={"reduceOnly": True})
                print(order)
                in_position = False
    if not df['in_uptrend'][previous_row_index] and df['in_uptrend'][last_row_index]:
            print("trend changed")
            if in_position:
                order = exchange.create_market_buy_order('ETH/USDT', bal)
                close_position = binance.create_order(symbol=symbol, type="MARKET", side="buy", amount=pos['positionAmt'], params={"reduceOnly": True})
                print(order)
                in_position = False


my_code.py :

def run_bot():
    print("Fetching new bars for", datetime.now())
    bars = exchange.fetch_ohlcv('ETH/USDT', timeframe='1h', limit=100)
    df = pd.DataFrame(bars[:-1], columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
    df['timestamp']=pd.to_datetime(df['timestamp'], unit='ms')
    supertrend_data = supertrend(df)
    check_buy_sell_signals(supertrend_data)

def tr(data):
    data['previous_close']=data['close'].shift(1)
    data['high-low']=abs(data['high'] - data['low'])
    data['high-pc']=abs(data['high'] - data['previous_close'])
    data['low-pc']=abs(data['low']-data['previous_close'])
    tr=data[['high-low', 'high-pc', 'low-pc']].max(axis=1)
    return tr

def atr(data, period=10):#supertrend variables
    data['tr']=tr(data)
    print("calculate average true range")
    atr=data['tr'].rolling(period).mean()
    return atr

def supertrend(df, period=10, atr_multiplier=1.4):
    hl2=(df['high']+df['low'])/2
    print("calculating supertrend")
    df['atr']=atr(df, period=period)
    df['upperband']= hl2 + (atr_multiplier*df['atr'])
    df['lowerband']= hl2 -(atr_multiplier*df['atr'])
    df['in_uptrend']=True
    for current in range(1, len(df.index)):
        previous=current-1
        if df['close'][current] > df['upperband'][previous]:
            df['in_uptrend'][current]=True
        elif df['close'][current] < df['lowerband'][previous]:
            df['in_uptrend'][current]=False
        else:
            df['in_uptrend'][current] = df['in_uptrend'][previous]
            if df['in_uptrend'][current] and df['lowerband'][current] < df['lowerband'][previous]:
                df['lowerband'][current] = df['lowerband'][previous]
            if not df['in_uptrend'][current] and df['upperband'][current] > df['upperband'][previous]:
                df['upperband'][current] = df['upperband'][previous]
    return(df)

Upvotes: 3

Related Questions