SkillAgentSearch skills...

Pyjuque

⚡ Open Source Algorithmic Trading Bot for Python.

Install / Use

/learn @tudorelu/Pyjuque

README

! This repo has been DEPRECATED, it is not maintained anymore !

.

.

.

.

.

Python Juju Quant Engine

PYJUQUE     (pai-jook) (Py-thon Ju-ju Qu-ant E-ngine)

This project implements the basic functionality required to engage in algorithmic trading. It can be regarded as a starting point for more complex trading bots.

Installation

<details> <summary> Expand installation details. </summary> <br/>

Make sure you have pip installed. To install the latest version run:

pip install -U git+https://github.com/tudorelu/pyjuque

To install an older (stable) version, run:

pip install pyjuque

Should be good to go! Now check out the example section.

</details>

Examples

Checkout these examples to get started stratght away: strategy 1, strategy 2. Below are the simplest scripts on how to get started with pyjuque (just code, with comments). Read the next section to understand the thinking behind them.

<details> <summary> Backtesting a Strategy. </summary>
# Import the Strategy template
from pyjuque.Strategies import StrategyTemplate
# Import the CcxtWrapper to connect to a cryptocurrency exchange (data provider)
from pyjuque.Exchanges.CcxtExchange import CcxtExchange
# Import the Backtester class
from pyjuque.Backtester import Backtester

# Define Momentum Strategy
class MomentumStrategy(StrategyTemplate):
    ### If the last `momentum_period` candles are monotonically increasing, 
    ### it is a long signal, and if they are monotonically decreasing 
    ### it's a short signal.
    def __init__(self, momentum_period=3):
        if momentum_period < 1:
            raise ValueError("momentum_period should be greater than 1.")
        self.momentum_period = momentum_period
        self.minimum_period = max(100, momentum_period)

    # this function computes all long and short signals
    # that happened on this dataframe (df) 
    def setUp(self, df):
        # the signals on the first `momentum_period` candles are false
        # because we don't have enough data yet to compute
        long_signals = [0] * self.momentum_period
        short_signals = [0] * self.momentum_period
        l_df = len(df)
        close = df['close']
        # for the rest of the candles check out if they were monotonically 
        # increasing or decreasing
        for i in range(self.momentum_period, l_df):
            all_increasing = True
            all_decreasing = True
            # Go through the last 'momentum_period' candles 
            # to see if they're all increasing, decreasing, or not
            for j in range(i + 1 - self.momentum_period, i + 1):
                all_increasing = all_increasing and (close[j] > close[j-1])
                all_decreasing = all_decreasing and (close[j] < close[j-1])
            # if they're all increasing it's a long signal
            long_signals.append(int(all_increasing))
            # if they're all decreasing it's a short signal
            short_signals.append(int(all_decreasing))
        self.long_signals = long_signals
        self.short_signals = short_signals
        self.dataframe = df

    # the bot will call this function with the latest data and if this 
    # returns 1, our bot will place a long order
    def checkLongSignal(self, i = None):
        return self.long_signals[i], None

    # if your exit settings contain 'exit on signal', the bot will exit if it 
    # currently has an open order and it receives a short signal 
    # (IE this function returns 1)
    def checkShortSignal(self, i = None):
        return self.short_signals[i], None

# Define the config file
bot_config = {
    'strategy': {
        'class': MomentumStrategy,
        'params': {'momentum_period' : 2}
    },
    'entry_settings' : {
        'trade_amount': 1_000,      # 1_000 Units per trade
        'go_long' : True,           # Go long
        'go_short' : False,         # Don't go short
        'fee': 0.1                  # 0.1% fee per trade
    },
    'exit_settings' : {
        'exit_on_signal': True    # Exit when you receive opposite signal (we're
                                  # in a LONG position and we get SHORT signal)
    }
}

if __name__ == '__main__':
    # Connect to exchange and get data (last 1000 1h candles for BTC/USDT)
    exchange = CcxtExchange('binance', {'enableRateLimit':True})
    df = exchange.getOHLCVHistorical("BTC/USDT", '1h', 1000)
    # Backtest bot on this data given the previously defined parameters
    bt = Backtester(bot_config)
    bt.backtest(df)
    # Show graph 
    bt.get_fig().show()

</details> <details> <summary> Running a Bot. </summary> <br/>
from pyjuque.Bot import defineBot
import time

def customEntryStrategy(bot_controller, symbol):
    # signal = will_moon(symbol)          # bool
    # last_price = get_price(symbol)      # float
    return signal, last_price

## Defines the overall configuration of the bot 
bot_config = {
    'name' : 'my_bot',
    'test_run' : False                    # set to True to run in simulation mode
    'exchange' : {
        'name' : 'binance',
        'params' : {                      # put here any param that ccxt accepts
            'api_key': 'YOUR_API_KEY',
            'secret' : 'YOUR_API_SECRET'
        },
    },
    'symbols' : ['LINK/BTC', 'ETH/BTC'],  # !! all symbols must trade against same coin
                                          # !! IE: [XX/BTC, YY/BTC] OR [AA/EUR, CC/EUR]
    'starting_balance' : 0.0005,          # denominated in the quote asset against which 
                                          # the symbols are trading (BTC in this case)
    'strategy': {
        'custom': True,
        'entry_function': customEntryStrategy,
    },
    'entry_settings' : {
        'initial_entry_allocation': 100,  # 100% of starting_balance goes in every trade
        'signal_distance': 0.3            # upon receiving an entry_signal, entry order
                                          # is placed 0.3% away from market price
    },
    'exit_settings' : {
        'take_profit' : 3,                # take profit 3% above entry orders
        'stop_loss_value': 10             # stop loss 10% below entry orders
    },
}


## Runs the bot in an infinite loop that executes every 60 seconds 
## stoppable from the terminal with CTRL + C
def Main():
    bot_controller = defineBot(bot_config)
    while True:
        try:
            bot_controller.executeBot()
        except KeyboardInterrupt:
            return
        time.sleep(60)


if __name__ == '__main__':
    Main()
</details>

Detailed Explanation

<details> <summary> Expand bot explanation. </summary> <br/> The idea behind this library is to allow you to implement whatever trading strategy you want, without having to worry about how to connect to the different exchanges via apis, or how to place, cancel and keep track of orders. You simply provide the signals and pyjuque does the rest.

There are a number of settings that you define, like what symbols to trade on, how much money to place per trade and what exchange to use. You also get to set exit settings such as a take profit value and a stop loss value. All these settings get specified in a config dict. Below is a complete example of a config dict:

## Defines the overall configuration of the bot 
bot_config = {
    # Name of the bot, as stored in the database
    'name' : 'my_bot',

    # exchange information (fill with your api key and secret)
    'exchange' : {
        'name' : 'binance', # or 'okex'
        'params' : {  # any parameter accepted by ccxt can go here
            'api_key': 'your_api_key_here',
            'secret' : 'your_secret_here',
            # 'password' : 'your_password_here' # if using 'okex'
        },
    },

    # starting balance for bot
    'starting_balance' : 0.0005,

    # symbols to trade on
    # !IMPORTANT! all symbols must trade against the same coin
    # !! IE: [AAA/BTC, BBB/BTC] OR [AAA/USDT, CCC/USDT]
    'symbols' : ['LINK/BTC', 'ETH/BTC'],  

    # strategy class / function (here we define the entry and exit strategies.)
    # this bot places an entry order when 'customEntryFunction' retruns true
    'strategy': { 
       'custom': True,
       'entry_function' : customEntryFunction 
    },

    # when the bot receives the buy signal, the order is placed according 
    # to the settings specified below
    'entry_settings' : {

        # between 0 and 100, the % of the starting_balance to put in an order
        'initial_entry_allocation': 100,

        # number between 0 and 100 - 1% means that when we get a buy signal, 
        # we place buy order 1% below current price. if 0, we place a market 
        # order immediately upon receiving signal
        'signal_distance': 0.3
    },

    # This bot exits when our filled orders have reached a take_profit % above 
    # the buy price, or a stop_loss_value % below it
    'exit_settings' : {

        # take profit value between 0 and infinity, 3% means we place our sell 
        # orders 3% above the prices that our buy orders filled at
        'take_profit' : 3,

        # stop loss value in percent - 10% means stop loss at 10% below our 
        # buy order's filled price
        'stop_loss_value': 10
    },
}

Besides these settings, you need to provide an entry strategy. It can be as simple as a function, or a more complex strategy class. We'll go over the simple example:


# This is our signal function.
# It receives two parameters - the bot_controller,
# which gives us access to the exchange and to the 
# database, and the symbol on which the bot is 
# currently checking entry signals.
#
# It must return two values, a boolean and a number.
# The boolean is the signal, and the number is the 
# latest price of that symbol 
#
def customEntryFunction(bot_controller, symbol):
  # ... do some stuff here .
View on GitHub
GitHub Stars456
CategoryDevelopment
Updated5d ago
Forks90

Languages

Python

Security Score

100/100

Audited on Mar 19, 2026

No findings