Skip to content
Rafael Far edited this page Jul 8, 2019 · 2 revisions

bellow I've used renko charts and your api to show me better analyses.

let me share the code:

first of all create a folder create file called pyrenko.py:

this is based on: https://github.com/quantroom-pro/pyrenko/blob/master/pyrenko.py

with little changes I added ema 22 periods.

TODO: this renko has no wicks so it need be developed. To see renko with wicks look at tradingview site.

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import talib

class renko:
    def __init__(self):
        self.source_prices = []
        self.renko_prices = []
        self.renko_directions = []

    # Setting brick size. Auto mode is preferred, it uses history
    def set_brick_size(self, HLC_history = None, auto = True, brick_size = 10.0):
        if auto == True:
            self.brick_size = self.__get_optimal_brick_size(HLC_history.iloc[:, [0, 1, 2]])
        else:
            self.brick_size = brick_size
        return self.brick_size

    def __renko_rule(self, last_price):
        # Get the gap between two prices
        gap_div = int(float(last_price - self.renko_prices[-1]) / self.brick_size)
        is_new_brick = False
        start_brick = 0
        num_new_bars = 0

        # When we have some gap in prices
        if gap_div != 0:
            # Forward any direction (up or down)
            if (gap_div > 0 and (self.renko_directions[-1] > 0 or self.renko_directions[-1] == 0)) or (gap_div < 0 and (self.renko_directions[-1] < 0 or self.renko_directions[-1] == 0)):
                num_new_bars = gap_div
                is_new_brick = True
                start_brick = 0
            # Backward direction (up -> down or down -> up)
            elif np.abs(gap_div) >= 2: # Should be double gap at least
                num_new_bars = gap_div
                num_new_bars -= np.sign(gap_div)
                start_brick = 2
                is_new_brick = True
                self.renko_prices.append(self.renko_prices[-1] + 2 * self.brick_size * np.sign(gap_div))
                self.renko_directions.append(np.sign(gap_div))
            #else:
                #num_new_bars = 0

            if is_new_brick:
                # Add each brick
                for d in range(start_brick, np.abs(gap_div)):
                    self.renko_prices.append(self.renko_prices[-1] + self.brick_size * np.sign(gap_div))
                    self.renko_directions.append(np.sign(gap_div))

        return num_new_bars

    # Getting renko on history
    def build_history(self, prices):
        if len(prices) > 0:
            # Init by start values
            self.source_prices = prices
            self.renko_prices.append(prices.iloc[0])
            self.renko_directions.append(0)

            # For each price in history
            for p in self.source_prices[1:]:
                self.__renko_rule(p)

        return len(self.renko_prices)

    # Getting next renko value for last price
    def do_next(self, last_price):
        if len(self.renko_prices) == 0:
            self.source_prices.append(last_price)
            self.renko_prices.append(last_price)
            self.renko_directions.append(0)
            return 1
        else:
            self.source_prices.append(last_price)
            return self.__renko_rule(last_price)

    # Simple method to get optimal brick size based on ATR
    def __get_optimal_brick_size(self, HLC_history, atr_timeperiod = 14):
        brick_size = 0.0

        # If we have enough of data
        if HLC_history.shape[0] > atr_timeperiod:
            brick_size = np.median(talib.ATR(high = np.double(HLC_history.iloc[:, 0]),
                                             low = np.double(HLC_history.iloc[:, 1]),
                                             close = np.double(HLC_history.iloc[:, 2]),
                                             timeperiod = atr_timeperiod)[atr_timeperiod:])

        return brick_size

    def evaluate(self, method = 'simple'):
        balance = 0
        sign_changes = 0
        leng = len(self.renko_prices)
        price_ratio = len(self.source_prices) / leng if leng else 0

        if method == 'simple':
            for i in range(2, len(self.renko_directions)):
                if self.renko_directions[i] == self.renko_directions[i - 1]:
                    balance = balance + 1
                else:
                    balance = balance - 2
                    sign_changes = sign_changes + 1

            if sign_changes == 0:
                sign_changes = 1

            score = balance / sign_changes
            if score >= 0 and price_ratio >= 1:
                score = np.log(score + 1) * np.log(price_ratio)
            else:
                score = -1.0

            return {'balance': balance, 'sign_changes:': sign_changes,
                    'price_ratio': price_ratio, 'score': score}

    def get_renko_prices(self):
        return self.renko_prices

    def get_renko_directions(self):
        return self.renko_directions

    def plot_renko(self, col_up = 'g', col_down = 'r'):
        fig, ax = plt.subplots(1, figsize=(20, 10))
        ax.set_title('Renko chart')
        ax.set_xlabel('Renko bars')
        ax.set_ylabel('Price')

        # Calculate the limits of axes
        ax.set_xlim(0.0,
                    len(self.renko_prices) + 1.0)
        ax.set_ylim(np.min(self.renko_prices) - 3.0 * self.brick_size,
                    np.max(self.renko_prices) + 3.0 * self.brick_size)

        # exponential
        ema = talib.EMA(np.array(self.renko_prices,dtype='f8'),timeperiod=22)
        ax.plot(ema, color='blue', lw=2, label='EMA (22)')

        # Plot each renko bar
        for i in range(1, len(self.renko_prices)):
            # Set basic params for patch rectangle
            col = col_up if self.renko_directions[i] == 1 else col_down
            x = i
            y = self.renko_prices[i] - self.brick_size if self.renko_directions[i] == 1 else self.renko_prices[i]
            height = self.brick_size

            # Draw bar with params
            ax.add_patch(
                patches.Rectangle(
                    (x, y),   # (x,y)
                    1.0,     # width
                    self.brick_size, # height
                    facecolor = col
                )
            )

        plt.show()

then create new file called userdata.py and set your credentials

mainUser = {
    'username': '',
    'password': ''
}

After that create new file called renko.py:

then just paste this code

import time
import os
import json
import datetime as dt
from iqoptionapi.stable_api import IQ_Option
from argparse import ArgumentParser
import pandas as pd
import userdata
import pyrenko


## How to use python renko.py -a USDJPY -i 300

parser = ArgumentParser()
parser.add_argument("-a", "--asset", dest="asset", required=True,
                    help="Pass the asset:(EURUSD, AUDUSD, XEMUSD-l ...)", metavar="ASSET")

parser.add_argument("-i", "--interval", dest="interval", required=False,
                    help="Pass interval in seconds: [1,5,10,15,30,60,120,300,600,900,1800,3600,7200,14400,28800,43200,86400,604800,2592000,'all']", metavar="TIME")

parser.add_argument("-f", "--file-sufix", dest="filesufix", required=False,
                    help="Pass sufix to file ", metavar="SUFIX")

args = parser.parse_args()

asset = args.asset or "USDJPY"
interval = args.interval or 60
sufix = args.filesufix or ""

## AUTH
user = userdata.mainUser
Iq= IQ_Option(user["username"],user["password"])

end_from_time=time.time()
ANS=[]

for i in range(3):
    candles=[]
    candles=Iq.get_candles(asset, int(interval), 1000, end_from_time)
    cds = []
    for candle in candles:
        cd_handle = {}
        if candle["open"]:
            cd_handle['open'] = candle["open"]
            cd_handle['high'] = candle["max"]
            cd_handle['low'] = candle["min"]
            cd_handle['close'] = candle["close"]
            cd_handle['created_at'] = dt.datetime.fromtimestamp(candle["from"]).isoformat()
            cd_handle['timestamp'] = candle["from"]
            cd_handle['volume'] = candle["volume"]
            cds.append(cd_handle)

    ANS =cds+ANS
    end_from_time=int(cds[0]["timestamp"])-1

try:
    df = pd.DataFrame(ANS)
    optimal_brick = pyrenko.renko().set_brick_size(auto = True, HLC_history = df[["high", "low", "close"]])

    # Build Renko chart
    renko_obj_atr = pyrenko.renko()
    renko_obj_atr.set_brick_size(auto = False, brick_size = optimal_brick)

    renko_obj_atr.build_history(prices = df.close)


    if len(renko_obj_atr.get_renko_prices()) > 1:
        renko_obj_atr.plot_renko()
except IOError:
    print("I/O error")

Don't forget to install all depencies in renko.py

after all just run

python renko.py -a USDJPY -i 300 

It means you are running with USDJPY and it will get 5 minutes per candles

It is not so accurate because to create renko you need each price change and not just closes

but it create an chart with a better precision then only candles

I hope it can contribute to raise up this project.

Clone this wiki locally