Code Monkey home page Code Monkey logo

smart-money-concepts's People

Contributors

cosmictrader avatar jiak94 avatar joshyattridge avatar rafalsza avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

smart-money-concepts's Issues

Previous Candle High/Low

Create a new function to get the previous candles High and low.
You will be able to pass the timeframe of the previous candle like 1m,1H,1D,1W
This function will then get the high and low of that previous candle like the previous days high and low.
The function will then return the following data:
High - the pip the high is at.
HighBreach - When the high was breached if it has.
Low - the pip the low is at.
LowBreach - When the low was breached if it has.

Sessions Indicator

Create An Indicator that will determine if the candle is in a certain session.

This function must follow the sessions on https://www.babypips.com/learn/forex/forex-trading-sessions and it must account for the different time zones the data is in.

Parameters:

  • Type: the type of session (Sydney, Tokyo, London, New York and custom)
  • Custom Start: the starting time of the custom session
  • Custom End: the ending time of the custom session

Retuned values:

  • InSession = 0 or 1 - if the candle is in the session or not
  • Top = the highest high during the current session
  • Bottom = the lowest low during the current session

FVG - Liquidity

First of all, thank you for all your efforts for the SMC Python adaptation. I am experimenting with testing this package and applying it to different strategies. However, I am having problems calculating data related to FVG and Liquidity. No matter what threshold value I enter for Liquidity, I cannot get results on the chart or as data. I also get the following error on FVG. These might be simple questions with straightforward solutions. Unfortunately, my experience with Python is at the beginner level. Thank you in advance for your support.

line 129, in
fig = add_FVG(fig)
line 39, in add_FVG
fvg_data = smc.fvg(df)
smartmoneyconcepts\smc.py", line 35, in wrap
return func(*args, **kwargs)
smartmoneyconcepts\smc.py", line 87, in fvg
mask = np.zeros(len(ohlc), dtype=np.bool)
numpy_init_.py", line 338, in getattr
raise AttributeError(former_attrs[attr])
AttributeError: module 'numpy' has no attribute 'bool'.
np.bool was a deprecated alias for the builtin bool. To avoid this error in existing code, use bool by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use np.bool_ here.
The aliases was originally deprecated in NumPy 1.20; for more details and guidance see the original release note at:
https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations. Did you mean: 'bool_'?

#----------------Binance Data Fecth---------------------------------
bars = exchange.fetch_ohlcv('LINK/USDT', timeframe='4h', limit=1000)
df = pd.DataFrame(bars[:-1], columns=['timestamp', 'open', 'high', 'low', 'close', 'volume']).astype(float)
df['timestamp']=pd.to_datetime(df['timestamp'], unit='ms')

#----------------Bar Plot------------------------------------------
fig = go.Figure(
    data=[
        go.Candlestick(
            x=df["timestamp"],
            open=df["open"],
            high=df["high"],
            low=df["low"],
            close=df["close"],
        )
    ]
)
#----------------FVG Plot------------------------------------------
def add_FVG(fig):
    fvg_data = smc.fvg(df)
    # plot a rectangle for each fvg
    for i in range(len(fvg_data["FVG"])):
        if fvg_data["FVG"][i] != 0:
            x1 = (
                fvg_data["MitigatedIndex"][i]
                if fvg_data["MitigatedIndex"][i] != 0
                else len(df) - 1
            )
            fig.add_shape(
                # filled Rectangle
                type="rect",
                x0=df.index[i],
                y0=fvg_data["Top"][i],
                x1=df.index[x1],
                y1=fvg_data["Bottom"][i],
                line=dict(
                    width=0,
                ),
                fillcolor="yellow",
                opacity=0.5,
            )
    return fig
#----------------Highs & Lows------------------------------------------
def add_highs_lows(fig):
    highs_lows_data = smc.highs_lows(df,0.005)

    # remove from highs_lows_data
    indexs = []
    levels = []
    for i in range(len(highs_lows_data)):
        if highs_lows_data["HighsLows"][i] != 0:
            indexs.append(i)
            levels.append(highs_lows_data["Levels"][i])
    
    # plot these lines on a graph
    for i in range(len(indexs) - 1):
        fig.add_trace(
            go.Scatter(
                x=[df["timestamp"][indexs[i]], df["timestamp"][indexs[i + 1]]],
                y=[levels[i], levels[i+1]],
                mode="lines",
                line=dict(
                    color="green" if highs_lows_data["HighsLows"][indexs[i]] == -1 else "red",
                ),
            )
        )

    return fig
#----------------Plot Liquidity------------------------------------------
def add_liquidity(fig):
    liquidity_data = smc.liquidity(df)

    # draw a line horizontally for each liquidity level
    for i in range(len(liquidity_data["Liquidity"])):
        if liquidity_data["Liquidity"][i] != 0:
            fig.add_trace(
                go.Scatter(
                    x=[df["timestamp"][i], df["timestamp"][liquidity_data["End"][i]]],
                    y=[liquidity_data["Level"][i], liquidity_data["Level"][i]],
                    mode="lines",
                    line=dict(
                        color="orange",
                    ),
                )
            )
        if liquidity_data["Swept"][i] != 0:
            # draw a red line between the end and the swept point
            fig.add_trace(
                go.Scatter(
                    x=[
                        df["timestamp"][liquidity_data["End"][i]],
                        df["timestamp"][liquidity_data["Swept"][i]],
                    ],
                    y=[
                        liquidity_data["Level"][i],
                        (
                            df["high"][liquidity_data["Swept"][i]]
                            if liquidity_data["Liquidity"][i] == 1
                            else df["low"][liquidity_data["Swept"][i]]
                        ),
                    ],
                    mode="lines",
                    line=dict(
                        color="red",
                    ),
                )
            )
    return fig

fig = add_FVG(fig)
fig = add_highs_lows(fig)
fig = add_liquidity(fig)
fig.show()

daylight savings shifts are out of sync

for the sessions function, it would be better to specify the open and close time natively to the timezone that we are targeting using the pytz format. eg:

smc.sessions(df, 'New York', '09:30', '16:00', timezone= "America/New_York")

This is because the daylight savings shifts for each country is not in sync, which means that twice a year, there will be several weeks where New York is in daylight savings, but London isn't or vice versa. The same can be said of other timezones.

M

Lockaheaad methods

If using .shift(-X) and Series[+X], your inicaators take into account future candles data.

Unit Testing

Create a python script to perform unit tests on all of the functions.

Explanation on Order Block

Hey, thanks for your great work. I have a few questions.

  1. Can you please explain how order blocks are getting detected? I am unable to find the information on it in the README file.
  2. Can you please explain why the order block got detected in the following case? Pair is STPT/USDT and the timeframe is 15m. I have shared the code for it as well.

image


import pandas as pd
import plotly.graph_objects as go
import sys
import os
from binance.client import Client
from datetime import datetime
import numpy as np
import time

from smartmoneyconcepts.smc import smc


def add_swing_highs_lows(fig, swing_highs_lows_data):
    indexs = []
    level = []
    for i in range(len(swing_highs_lows_data)):
        if not np.isnan(swing_highs_lows_data["HighLow"][i]):
            indexs.append(i)
            level.append(swing_highs_lows_data["Level"][i])

    # plot these lines on a graph
    for i in range(len(indexs) - 1):
        fig.add_trace(
            go.Scatter(
                x=[df.index[indexs[i]], df.index[indexs[i + 1]]],
                y=[level[i], level[i + 1]],
                mode="lines",
                line=dict(
                    color=(
                        "green"
                        if swing_highs_lows_data["HighLow"][indexs[i]] == -1
                        else "red"
                    ),
                ),
            )
        )

    return fig



def add_OB(fig, ob_data):
    def format_volume(volume):
        if volume >= 1e12:
            return f"{volume / 1e12:.3f}T"
        elif volume >= 1e9:
            return f"{volume / 1e9:.3f}B"
        elif volume >= 1e6:
            return f"{volume / 1e6:.3f}M"
        elif volume >= 1e3:
            return f"{volume / 1e3:.3f}k"
        else:
            return f"{volume:.2f}"

    for i in range(len(ob_data["OB"])):
        if ob_data["OB"][i] == 1:
            x1 = int(
                ob_data["MitigatedIndex"][i]
                if ob_data["MitigatedIndex"][i] != 0
                else len(df) - 1
            )
            fig.add_shape(
                type="rect",
                x0=df.index[i],
                y0=ob_data["Bottom"][i],
                x1=df.index[x1],
                y1=ob_data["Top"][i],
                line=dict(color="Green"),
                fillcolor="Green",
                opacity=0.3,
                name="Bullish OB",
                legendgroup="bullish ob",
                showlegend=True,
            )

            if ob_data["MitigatedIndex"][i] > 0:
                x_center = df.index[int(i + (ob_data["MitigatedIndex"][i] - i) / 2)]
            else:
                x_center = df.index[int(i + (len(df) - i) / 2)]

            y_center = (ob_data["Bottom"][i] + ob_data["Top"][i]) / 2
            volume_text = format_volume(ob_data["OBVolume"][i])
            # Add annotation text
            annotation_text = f'{volume_text} ({ob_data["Percentage"][i]}%)'

            fig.add_annotation(
                x=x_center,
                y=y_center,
                xref="x",
                yref="y",
                align="center",
                text=annotation_text,
                font=dict(color="white", size=8),
                showarrow=False,
            )

    for i in range(len(ob_data["OB"])):
        if ob_data["OB"][i] == -1:
            x1 = int(
                ob_data["MitigatedIndex"][i]
                if ob_data["MitigatedIndex"][i] != 0
                else len(df) - 1
            )
            fig.add_shape(
                type="rect",
                x0=df.index[i],
                y0=ob_data["Bottom"][i],
                x1=df.index[x1],
                y1=ob_data["Top"][i],
                line=dict(color="Red"),
                fillcolor="Red",
                opacity=0.3,
                name="Bearish OB",
                legendgroup="bearish ob",
                showlegend=True,
            )

            if ob_data["MitigatedIndex"][i] > 0:
                x_center = df.index[int(i + (ob_data["MitigatedIndex"][i] - i) / 2)]
            else:
                x_center = df.index[int(i + (len(df) - i) / 2)]

            y_center = (ob_data["Bottom"][i] + ob_data["Top"][i]) / 2
            volume_text = format_volume(ob_data["OBVolume"][i])
            # Add annotation text
            annotation_text = f'{volume_text} ({ob_data["Percentage"][i]}%)'

            fig.add_annotation(
                x=x_center,
                y=y_center,
                xref="x",
                yref="y",
                align="center",
                text=annotation_text,
                font=dict(color="white", size=8),
                showarrow=False,
            )
    return fig

def import_data(symbol, start_str, timeframe):
    client = Client()
    start_str = str(start_str)
    end_str = f"{datetime.now()}"
    df = pd.DataFrame(
        client.get_historical_klines(
            symbol=symbol, interval=timeframe, start_str=start_str, end_str=end_str
        )
    ).astype(float)
    df = df.iloc[:, :6]
    df.columns = ["timestamp", "open", "high", "low", "close", "volume"]
    df = df.set_index("timestamp")
    df.index = pd.to_datetime(df.index, unit="ms").strftime("%Y-%m-%d %H:%M:%S")
    return df


df = import_data("STPTUSDT", "2024-05-12", "15m")

fig = go.Figure(
    data=[
        go.Candlestick(
            x=df.index,
            open=df["open"],
            high=df["high"],
            low=df["low"],
            close=df["close"],
        )
    ]
)

swing_highs_lows_data = smc.swing_highs_lows(df, swing_length=10)
ob_data = smc.ob(df, swing_highs_lows_data)


fig = add_OB(fig, ob_data)

fig.update_layout(xaxis_rangeslider_visible=False)
fig.update_layout(showlegend=False)
fig.update_layout(margin=dict(l=0, r=0, b=0, t=0))
fig.update_xaxes(visible=False, showticklabels=False)
fig.update_yaxes(visible=False, showticklabels=False)
fig.update_layout(plot_bgcolor="rgba(0,0,0,0)")
fig.update_layout(paper_bgcolor="rgba(94, 94, 134, 1)")
fig.update_layout(font=dict(color="white"))
fig.write_image("test_binance.png")
fig



Installation error (Failed building wheel for zigzag)

Thank you very much for your effort on this. It was a highly anticipated package for me. I am trying to install via pip however end up with an error:

ERROR: Failed building wheel for zigzag
Failed to build zigzag
ERROR: Could not build wheels for zigzag, which is required to install pyproject.toml-based projects

Do you have any suggestions?
Thank you in advance

Issue with bos_choch Function Returning Empty DataFrame

Hi,

I'm encountering an issue with the bos_choch function. Despite following the documentation and ensuring that the input dataframes are correctly formatted, the bos_choch function consistently returns an empty dataframe.

Here's a brief overview of my setup:

  • DataFrame Structure: Columns include date, open, high, low, close, volume.
  • Swing Highs and Lows: Generated using smc.swing_highs_lows(dataframe, swing_length=20).
  • Parameters: Passing the generated swing_highs_lows dataframe to bos_choch with close_break=False.

The intermediate outputs seem correct, but the final bos_choch result is empty. Here is a snippet of my code:

from smartmoneyconcepts import smc

dataframe.columns = [col.lower() for col in dataframe.columns]
swing_highs_lows = smc.swing_highs_lows(dataframe, swing_length=20)
if not swing_highs_lows.empty:
    breakOFStructure = smc.bos_choch(dataframe, swing_highs_lows, close_break=False)
    print(breakOFStructure.head())
else:
    print("Swing Highs and Lows DataFrame is empty.")

I've ensured that the dataframe and swing_highs_lows contain valid data.

dataframe is belong to BTCUSDT:USDT Binance and I'm sure its contain some Break of Structures

thank you

my chart screenshot :

hint : the double x is swings points
image

Consecutive FVG

Add a boolean parameter to the FVG function called join_consecutive.

If this is set to true then any FVG that follow after each other will be joined together.
So instead of having multiple small FVGs in a row they will be joined together and the top/bottom will be adjusted to cover all of them.

Request for Explanation of Order Block Detection Concept in Code

I am trying to understand the concept behind the order block detection as implemented in your code. I have reviewed the order block detection function would like to gain a deeper understanding of the logic it is based on. Could you explain the theory behind it? Additionally, I would also like to know how you define a "mitigation block" and a "breaker block" in your implementation.

Thank you for your assistance and for maintaining this amazing library.

Test Chart Clean up

The current chart produced by the tests is a bit messy and hard to understand.
This task is to clean up this chart make it look pretty and easy to read.
Then add the chart image to README.md file

OB Class Loops

Thank you for your great work. The library performs well overall, but there's one issue: the OB class is implemented using for loops, resulting in approximately 20 seconds of runtime. Typically, this isn't a problem, but since I'm attempting to develop a Freqtrade strategy with this library, the backtesting process takes about a day to yield results. I've attempted to use vectorized operations to improve performance, but I haven't succeeded. Could you help vectorize the classes to enhance speed? I would be extremely grateful.

very long waiting time for VOB

def add_VOB(fig):

    start_time = time.time()
    ob_data = smc.vob(df)
    volumized_ob_time = time.time() - start_time
    logger.debug(
        "volumized_ob processing time (for ohlc length={}): {:.2f} seconds",
        len(ob_data),
        volumized_ob_time,
    )
2024-02-23 12:48:40.440 | DEBUG    | __main__:add_VOB:194 - volumized_ob processing time (for ohlc length=1000): 5.01 seconds

Multiple orderblocks

Hi,
Thanks for a great starting point on building SMC concepts using Python. I am currently trying to use your library/code to find order blocks and I was wondering if you are planning to change the ob function so it returns multiple order blocks?
For instance when I run the code on FLOWUSDT (Bybit perpetual contract) 4H candle data it detects the following order block
image

However, when I use the most popular order-block indicator on TW there are more OB's being displayed
image

image

I'm still getting familiar with your codebase, if I am successful in understanding it properly I can try to contribute a PR.

Add mitigation level argument to FVG

Add to the FVG function an argument to specify what percentage should the FVG be mitigated:
0% - Price just has to touch the FVG.
50% - Price has to reach half way.
100% - Price has to cover the whole FVG.

index 0 is out of bounds for axis 0 with size 0

import ccxt
import pandas as pd
from smartmoneyconcepts import smc

exchange = ccxt.binanceusdm(
    {
        "apiKey": "1",
        "secret": "1",
        "enableRateLimit": True,
    }
)

# exchange.verbose = True
exchange.options["warnOnFetchOpenOrdersWithoutSymbol"] = False

klines = exchange.fetch_ohlcv("POLYX/USDT", "1h", limit=100)

# 转为 df
df = pd.DataFrame(
    klines, columns=["timestamp", "open", "high", "low", "close", "volume"]
)

swing_highs_lows = smc.swing_highs_lows(df, 50)
print(swing_highs_lows)

# fvg_data = smc.fvg(df)
# df = pd.concat([df, fvg_data], axis=1)

# swing_highs_lows = smc.swing_highs_lows(df)
# print(swing_highs_lows)

# print(df)

Questions regarding BOS/CHOCH function

Hi team,
Could you please help with some questions about bos_choch function:

  1. What does mean BrokenIndex and what its value means ? (some position(candle) number; it doesn't equal the candle number in the data frame)
  2. How can we show all Level values, not only when we have BOS or CHOCH ?
  3. As I understand and can see from testing the BOS or CHOCH, the price is showing for the candle that starts the breaking price and not closes. How we can show the BOS or CHOCH but on the candle that closes the breaking.
    I know that the decision is made based on the swing highs and lows but can we somehow show BOS or CHOCH on the candle which closes the price breaking even if this candle is not a swing high or low ?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.