Automating Cryptocurrency Trading with Python

·

Unlike traditional stock exchanges such as the New York Stock Exchange, which operate during fixed trading hours, cryptocurrency markets run 24/7. This constant activity makes it impossible for anyone to monitor the markets manually at all times.

Many traders face common questions:

The typical solution is to use a crypto trading bot that executes trades on your behalf while you sleep, spend time with family, or enjoy leisure activities. While numerous commercial options exist, this guide focuses on an open-source approach using a tool called Pythonic.

Getting Started with Automated Trading

Pythonic is a graphical programming tool that enables users to build Python applications easily using ready-made function modules. Originally designed as a cryptocurrency trading bot, it includes an extensible logging engine and well-tested reusable components like schedulers and timers.

This tutorial will guide you through setting up an automated trading strategy using Pythonic. We’ll use the Tron (TRX) and Bitcoin (BTC) trading pair on the Binance exchange as an example—selected for its high volatility rather than personal preference.

The bot will make decisions based on Exponential Moving Averages (EMA), a weighted moving average that assigns greater importance to recent price data. Though simple, EMAs are effective and widely used.

The Core Strategy

The bot monitors the gap between the current EMA-25 value (t₀) and the previous one (t₋₁). If the difference exceeds a certain threshold, it signals a price increase, and the bot places a buy order. If the difference falls below a specific value, the bot places a sell order. This difference, referred to as the trading parameter, drives the decision-making process.

Toolchain

We’ll use the following tools:

Data Mining and Management

Reliable data is the foundation of any trading bot. We need to fetch Open-High-Low-Close (OHLC) data for our chosen asset pair robustly, even during downtime or disconnections.

The general workflow:

  1. Synchronize with Binance server time
  2. Download OHLC data
  3. Load existing OHLC data from a local file
  4. Compare and update the dataset with new data

This approach ensures resilience and continuity.

Fetching Data with Pythonic

Start by using the Binance OHLC Query element paired with a Basic Operation element to execute custom code.

The OHLC query is configured to fetch TRXBTC data at 1-hour intervals. The output is a Pandas DataFrame, which you can access via the input variable in the Basic Operation element.

Here’s a sample code snippet for the Basic Operation element:

import pickle, pathlib, os
import pandas as pd

output = None

if isinstance(input, pd.DataFrame):
    file_name = 'TRXBTC_1h.bin'
    home_path = str(pathlib.Path.home())
    data_path = os.path.join(home_path, file_name)
    
    try:
        df = pickle.load(open(data_path, 'rb'))
        n_row_cnt = df.shape[0]
        df = pd.concat([df, input], ignore_index=True).drop_duplicates(['close_time'])
        df.reset_index(drop=True, inplace=True)
        n_new_rows = df.shape[0] - n_row_cnt
        log_txt = '{}: {} new rows written'.format(file_name, n_new_rows)
    except Exception as e:
        log_txt = 'File error - writing new one: {}'.format(e)
        df = input
        pickle.dump(df, open(data_path, "wb"))
    
    output = df

This code checks if the input is a DataFrame, then looks for a local file TRXBTC_1h.bin in the user’s home directory. If the file exists, it appends new data and removes duplicates; if not, it creates a new file.

Log output can be monitored using:

tail -f ~/Pythonic_2020/Feb/log_2020_02_19.txt

Data Preparation and Technical Analysis

Pass the DataFrame from Grid 1 to Grid 2 using a Return Element. In Grid 2, use the Basic Technical Analysis element to add an EMA-25 column to the DataFrame.

Configure the technical analysis element to calculate the 25-period EMA. Although the debug output may show rounded values, the actual data retains full floating-point precision.

Dump the extended DataFrame to a file using another Basic Operation element so you can load it into a Jupyter Notebook for further analysis.

Strategy Evaluation and Backtesting

In Jupyter Notebook, develop and test your evaluation strategy. Load the DataFrame and access the latest EMA-25 values using .iloc and .at methods.

Define a validation function to simulate trades based on your strategy. For example:

def validate(buy_factor, sell_factor):
    # Simulation logic here
    return profit

Use nested loops to brute-force the best buy_factor and sell_factor:

trading_factors = []

for buy_factor in [0.001, 0.002, 0.003, 0.004, 0.005, 0.006, 0.007, 0.008, 0.009]:
    for sell_factor in [0.001, 0.002, 0.003, 0.004, 0.005, 0.006, 0.007, 0.008, 0.009]:
        profit = validate(buy_factor, sell_factor)
        trading_factors.append((buy_factor, sell_factor, profit))

# Sort by profit descending
trading_factors.sort(key=lambda x: x[2], reverse=True)

Print the sorted list to identify the most profitable parameters.

Execution Paths and Order Placement

Create a new grid (Grid 3) to keep the logic clean. Use a Basic Operation element to implement the evaluation logic:

output = 0  # Default: no action

ema_gap = df.at[df.shape[0] - 1, 'EMA_25'] - df.at[df.shape[0] - 2, 'EMA_25']

if ema_gap > 0.002:  # Buy signal
    output = 1
elif ema_gap < -0.002:  # Sell signal
    output = 2

Use a Branch Element to direct the flow based on the output. Since the same action may be taken for multiple outputs (e.g., 0 and -1), structure your branches accordingly.

Managing State with a Stack

Use a Stack Element to persist state between cycles—specifically, whether you’ve already bought in the current cycle. Initialize the stack with False.

Configure the stack to “Do nothing” with the input to avoid overwriting the boolean value. After the stack, add another branch element to evaluate its value and route to the Binance Order element if necessary.

Placing Orders on Binance

Configure the Binance Order element with your API key and secret (generated in your Binance account settings). Execute market orders for 10,000 TRX (adjust based on your capital and risk tolerance).

Note: Market orders are used here for simplicity; consider using limit orders in live trading for better control.

If an order fails (e.g., due to network issues or insufficient funds), subsequent elements won’t trigger. A successful order will output details like order ID and status.

After placing an order, use a Basic Operation element to output True and update the stack to reflect the new state.

Scheduling and Synchronization

Place the entire workflow behind a Binance Scheduler element in Grid 1. Since the scheduler runs only once, split the execution path at the end of Grid 1 and feed back into the scheduler to force resynchronization.

Deployment

Run the bot locally or deploy it to a low-cost cloud server (e.g., a $5/month Linux instance). Use PythonicDaemon for headless operation:

PythonicDaemon trading_bot_one

Add to crontab for auto-start on boot:

crontab -e

Add the line:

@reboot PythonicDaemon trading_bot_one

Next Steps and Enhancements

Programming a trading bot is about 10% coding and 90% testing. Always prioritize simplicity and clarity when dealing with financial algorithms.

Consider adding:


Frequently Asked Questions

What is an exponential moving average (EMA)?

An EMA is a type of moving average that places greater weight on recent data points. It reacts more quickly to price changes than a simple moving average (SMA), making it popular among traders for identifying trends and generating signals.

Why use Python for automated trading?

Python offers extensive libraries for data analysis, machine learning, and web connectivity. Its simplicity and readability make it ideal for prototyping and deploying trading strategies quickly. Many exchanges also provide Python SDKs for easy integration.

How much capital do I need to start?

This depends on the exchange and trading pair. Some platforms allow trading with as little as $10, but it’s advisable to start with a small amount you’re comfortable risking while testing and refining your strategy.

Can I run this bot on a Raspberry Pi?

Yes, Pythonic and PythonicDaemon can run on ARM-based devices like Raspberry Pi, provided you install the necessary dependencies. Ensure stable internet connectivity and consider the device’s limitations for intensive computations.

How do I secure my API keys?

Never hardcode API keys in your scripts. Use environment variables or secure configuration files with restricted permissions. Most cloud platforms offer secret management services for added security.

What are the risks of automated trading?

Automated trading carries risks including technical failures, network latency, and unexpected market conditions. Always monitor your bot initially, set stop-losses, and never invest more than you can afford to lose. View real-time tools to help manage these risks.