

# This file is generated by pto-pre-build.sh. Do not edit it manually.







# DONT EDIT THIS FILE MANUALLY. IT IS GENERATED BY pto-pre-build.sh








#DONT EDIT THIS FILE MANUALLY. IT IS GENERATED BY pto-pre-build.sh






# Fri 30 Aug 2024 04:31:23 PM EDT
# SOURCE NAME: jgtml_obsds_240515_TIDE_SIGNALS.py
########################
 

#%% Imports 


import pandas as pd
import sys
import subprocess

_DEVFLAG=False

_VERBOSE_ACTION=True

CLI_DESCRIPTION = 'Process financial market data to analyze the performance of SELL signals generated by the "Fractal Divergent Bar" indicator within the "Tide Alligator" technical analysis tool.'

EPILOG="""
This Python script is designed to analyze the effectiveness of signals in the context of the "Tide Alligator" technical analysis tool, specifically those generated by the "Fractal Divergent Bar" indicator. The script reads historical market data for a specified instrument and timeframe, calculates technical indicators, and identifies valid SELL and BUY signals based on predefined criteria. 

The script then evaluates the profitability of each valid signal's direction, analyzes the distribution of profit potential across different signal types, and compares their performance. The results of the analysis are outputted as a CSV file, and a markdown file summarizing the key findings is also generated.
"""
X_ABSTRACT="""
# Abstract"""+EPILOG+"""



The script leverages the `jgtpy` and `jgtml` Python packages for data analysis and machine learning. It is an early prototype made during my coding mastery and is somehow customizable, allowing for the analysis of different instruments, timeframes, and signal types using the CLI. This script is part of a broader research project exploring the use of technical indicators in trading.

Future work includes further data analysis to identify additional patterns and insights, the development of a trading strategy based on the analysis findings. This script serves as a experiment to find valuable tool for improving trading strategies and decision-making by providing insights into the effectiveness of fractal divergent signals generated by the "Fractal Divergent Bar" indicator and their relationship with the "Tide Alligator" tool.

The 6 types of signals analyzed in this script are:

- all_evalname_signals
- sig_normal_mouth_is_open
- sig_is_out_of_normal_mouth
- sig_is_in_ctx_teeth
- sig_ctx_mouth_is_open_and_in_ctx_teeth
- sig_ctx_mouth_is_open_and_in_ctx_lips

The script outputs the following metrics for each signal type:

- per_trade: Average profit per trade
- nb_entry: Number of valid signals for this type (could compare to the total number if signal of the "all_evalname_signals" column to learn how many signals are validated by this type of signal)
- tsum: Total profit across all signals
- title: Signal type

The script also generates a markdown file summarizing the key findings and a CSV file containing the detailed results of the analysis.

Details of each type of signals

- all_evalname_signals: All valid signals made by the jgtml.jtc.pto_target_calculation function
- sig_normal_mouth_is_open: Signals where the mouth of the "Regular Alligator" is open
- sig_is_out_of_normal_mouth: Signals where the price bar is out of the lips and teeth of the "Regular Alligator"
- sig_is_in_ctx_teeth: Signals where the price bar has came back in the big teeth of the "Big Alligator" without the mouth being open or not.
- sig_ctx_mouth_is_open_and_in_ctx_teeth: Signals where the price bar has came back in the big teeth and the mouth of the "Big Alligator" is open (Exploring a Strategic entry when the mouth is open and we want to enter at the end of a retracement.  This explores signals that pulled back in the big teeth(the middest of the big balancing lines system))
- sig_ctx_mouth_is_open_and_in_ctx_lips: Signals where the price bar has came back in the big lips and the mouth of the "Big Alligator" is open (Exploring a Strategic entry when the mouth is open and we want to enter at the end of a retracement. This explores signals that pulled back in the big lips (the smallest of the big balancing lines system) )

Further analysis and interpretation of the results are needed to draw meaningful conclusions and insights from the data. The script is intended to be a starting point for more in-depth research and exploration of technical indicators in trading.

"""

import os

import numpy as np
import pandas as pd
try:
    from jgtpy import JGTCDS as cds
except:
    print("pip install -U jgtpy")

import sys

sys.path.insert(0, os.path.abspath(os.path.dirname(__file__)))

try:
    from jgtml import jtc
except:
    import jtc

# Use jgtconstants column names from jgtutils
from jgtutils.jgtconstants import LOW,HIGH,FDBB,FDBS,BJAW,BLIPS,BTEETH,JAW,TEETH,LIPS,FDB_TARGET,VECTOR_AO_FDBS_COUNT,VECTOR_AO_FDBB_COUNT,VECTOR_AO_FDB_COUNT,TJAW,TLIPS,TTEETH


def crop_dataframe(df, crop_last_dt: str = None, crop_start_dt: str = None):
    if crop_last_dt is not None:
        df = df[df.index <= crop_last_dt]
    if crop_start_dt is not None:
        df = df[df.index >= crop_start_dt]
    return df

#%% Contexts 
# Contexts

i = 'GBP/USD'
i = 'SPX500'
t = "H4"
t = "D1"

use_env=os.getenv("JGTENV","0")

i=os.getenv("i",i)
t=os.getenv("t",t)

# FLAGS for the PROCESS we might want to configure or read from ENV
force_regenerate_mxfiles=False if os.getenv("force_regenerate_mxfiles") == "False" or os.getenv("force_regenerate_mxfiles") == "false" or os.getenv("force_regenerate_mxfiles") == "0" else True
mfi_flag=True
balligator_flag=True
talligator_flag=True
regenerate_cds=False if os.getenv("regenerate_cds") == "False" or os.getenv("regenerate_cds") == "false" or os.getenv("regenerate_cds") == "0" else True
use_fresh=False if os.getenv("use_fresh") == "False" or os.getenv("use_fresh") == "false" or os.getenv("use_fresh") == "0" else True
# use_fresh=True if os.getenv("use_fresh") == "True" or os.getenv("use_fresh") == "true" or os.getenv("use_fresh") == "1" else False
quiet=False if os.getenv("quiet") == "False" or os.getenv("quiet") == "false" or os.getenv("quiet") == "0" else True

# OUTPUTS Files
output_path_default="/b/Dropbox/jgt" #$jgtdroot
jgtdroot=os.getenv("jgtdroot",output_path_default)
#result_drop_base_default="/b/Dropbox/jgt/drop" #$jgtdroot
output_subdir = "drop"
result_file_basename_default = "jgtml_obsds_240515_SIGNALS.result"
result_file_basename_default = os.getenv("result_file_basename_default") if os.getenv("result_file_basename_default") is not None else result_file_basename_default
result_file_basename=result_file_basename_default

# Columns to select that are part of the settings in this whole process

def getBaseColumns():
    sel_columns_base=[HIGH,LOW,JAW,TEETH,LIPS]
    return sel_columns_base


def get_tide_alligator_columns():
    sel_columns_tide_alligator=[TJAW,TTEETH,TLIPS]
    return sel_columns_tide_alligator

def get_big_alligator_columns():
    sel_columns_big_alligator=[BJAW,BTEETH,BLIPS]
    return sel_columns_big_alligator

sel_columns_base = getBaseColumns()
sel_columns_tide_alligator = get_tide_alligator_columns()
sel_columns_big_alligator = get_big_alligator_columns()

eval_target_colname = FDB_TARGET # We will want to choose different target column in further analysis, for now we are using the FDB_TARGET
eval_signal_sell_colname=FDBS
eval_signal_buy_colname=FDBB

#@STCIssue How are these columns called in the process (future extra column that we can learn from) ? 
eval_extra_vector_signals_count_colname=VECTOR_AO_FDB_COUNT
eval_extra_vector_signal_sell_count_colname=VECTOR_AO_FDBS_COUNT
eval_extra_vector_signal_buy_count_colname=VECTOR_AO_FDBB_COUNT


# Select columns according to Flags (big alligator and tide alligator)
sel_columns_common=sel_columns_base + \
    (sel_columns_big_alligator if balligator_flag else None) +  \
        (sel_columns_tide_alligator if talligator_flag else None) + \
            [eval_target_colname,eval_extra_vector_signals_count_colname]

"""
FUTURE POSSIBLE COLUMN NAMES

    sell_signal_columns
    sell_indicator_fields
    sell_analysis_features
    sell_criteria_columns
    sell_trigger_attributes

"""

sel_columns_sell = sel_columns_common + [eval_signal_sell_colname,eval_extra_vector_signal_sell_count_colname ]
sel_columns_buy = sel_columns_common + [eval_signal_buy_colname,eval_extra_vector_signal_buy_count_colname ]

jgtpy_data_full_var_name = "JGTPY_DATA_FULL"

bs="S" # This prototype is for SELL signals only, we can extend it to BUY signals later
bs=os.getenv("bs",bs)

result_drop_base_override=None
source_dataset_archival_path_override=None
data_dir_override=None
archive_used_dataset=True
use_ttf_default = True




NB_CONTEXT_RUN=False
def _chg_logics_for_notebook_context():
    global use_fresh, regenerate_cds
    #TODO Chg logics for notebook context
    #regenerate_cds=False
    #use_fresh=False
    pass
    
NB_CONTEXT_RUN=False

#print(f"i:{i} t:{t} bs:{bs}")
try:
    import IPython

    if IPython.get_ipython() is not None:
        # Code is running in a Jupyter notebook
        print("Notebook context detected")
        NB_CONTEXT_RUN=True
    else:
        # Code is running outside a Jupyter notebook
        print("Notebook context not detected")
        NB_CONTEXT_RUN=False


except:
    print("Notebook context not detected")
    NB_CONTEXT_RUN=False



def print_context():
    #print("---BEFORE MAIN (Ignore when not using env (JGTENV=1))")
    print(f"i:{i} t:{t} bs:{bs}")
    print(f"regenerate_cds:{regenerate_cds}")
    print(f"Fresh:{use_fresh}")
    #print("----------------------------------------------")
    


def main():
    #global i,t,bs,print_abstract,regenerate_cds,result_drop_base_override,source_dataset_archival_path_override,quiet,data_dir_override,use_fresh,use_env
    import argparse
    parser = argparse.ArgumentParser(description=CLI_DESCRIPTION,epilog=EPILOG)
    if not use_env or use_env == "0":
        parser.add_argument('-i','--instrument', type=str, help='Instrument')
        parser.add_argument('-t','--timeframe', type=str, help='Timeframe')
        #bs
        parser.add_argument('-bs','--buysell', type=str, help='Buy or Sell',required=True)
        #regenerate_cds
        parser.add_argument('-nocds','--dont_regenerate_cds', help='Dont Regenerate CDS',action='store_true')
        #use_fresh
        parser.add_argument('-nf','--nofresh', help='Dont Use Fresh (Assuming you need CDS Already generated and available)',action='store_true')
    #parser.add_argument('-old','--not_fresh', help='Dont Use Fresh (Assuming you need CDS Already generated and available)',action='store_true')
        parser.add_argument('-q','--quiet', help='Quiet',action='store_true')

    #data_dir_override
    parser.add_argument('-dd','--data_dir_override', type=str, default=None, help='Data Directory Override path (JGTPY_DATA_FULL env var will be used if not provided)')
    #result_drop_base_override
    parser.add_argument('-rdb','--result_drop_base_override', type=str, default=None, help='Result Drop Base Override')
    #source_dataset_archival_path_override
    parser.add_argument('-sda','--source_dataset_archival_path_override', type=str, default=None, help='Source Dataset Archival Path Override')
    # quiet
    #print X_ABSTRACT
    parser.add_argument('-abstract','--print_abstract', action='store_true', help='Print Abstract')
    parser.add_argument('-ttf','--use_ttf_rather_than_cds', action='store_true', help='Force usage of TTF as source of data (CDS + HTF data)')
    #result_file_basename
    parser.add_argument('-rfb','--result_file_basename', type=str, default=result_file_basename_default, help='Result File Base Name')    
    
    parser.add_argument('-env','--use_env', help='Use environment variable instead of arguments',action='store_true')
    
    args = parser.parse_args()
    print_abstract = args.print_abstract
    
    if print_abstract:
        print(X_ABSTRACT,flush=True)
        exit(0)
        
    if not args.use_env or not use_env or use_env == "0":
        i = args.instrument
        t = args.timeframe
        bs = args.buysell
        regenerate_cds = not args.dont_regenerate_cds #default is to regenerate
        quiet = args.quiet
        use_fresh= False if args.nofresh else True
    else:
        i=os.getenv("i")
        t=os.getenv("t")
        bs=os.getenv("bs")
        dont_regenerate_cds_value=os.getenv("dont_regenerate_cds") #default is to regenerate
        regenerate_cds = True if dont_regenerate_cds_value is None or dont_regenerate_cds_value =="0" or dont_regenerate_cds_value == "False" else False

    result_drop_base_override = args.result_drop_base_override
    source_dataset_archival_path_override = args.source_dataset_archival_path_override
    data_dir_override = args.data_dir_override
        
    
    #@STCIssue We would do that by default
    use_ttf_rather_than_cds=args.use_ttf_rather_than_cds if args.use_ttf_rather_than_cds else False #@STCGoal Integration of all Signal Evaluation in one Script - We want HTF(ttf) data to be used in the evaluation so we can have a better understanding of the context of the signal with higher timeframes (Zone,MFI, etc)
    
    #return variables from args
    return i,t,bs,regenerate_cds,quiet,use_fresh,result_drop_base_override,source_dataset_archival_path_override,data_dir_override,use_ttf_rather_than_cds

if not NB_CONTEXT_RUN:
    if __name__ == "__main__":
        i,t,bs,regenerate_cds,quiet,use_fresh,result_drop_base_override,source_dataset_archival_path_override,data_dir_override,use_ttf_rather_than_cds=main()
else:
    _chg_logics_for_notebook_context()

print_context()

print("--------AFTER MAIN---------")
print(f"i:{i} t:{t} bs:{bs}")
print("regenerate_cds:",regenerate_cds)

# Where to save the results
def create_result_directory(jgtdroot, drop_subdir, result_drop_base_override):
    result_drop_base=os.path.join(jgtdroot, drop_subdir) if result_drop_base_override is None else result_drop_base_override

    if not os.path.exists(result_drop_base):
        result_drop_base=os.path.join(".", drop_subdir)
        os.makedirs(result_drop_base,exist_ok=True)
    return result_drop_base

    

#Where source dataset is archived 

def get_arch_tdir():
    return "jgtml_240516"

def get_source_dataset_archival_path(source_dataset_archival_path_override, result_drop_base, get_arch_tdir):
    source_dataset_archival_path= os.path.join(result_drop_base, "data", "arch", get_arch_tdir()) if source_dataset_archival_path_override is None else source_dataset_archival_path_override
    return source_dataset_archival_path



# Columns to select based on the direction    
def make_columns_list_from_bs(sel_columns_sell, sel_columns_buy, bs):
    if bs=="S" or bs=="SELL" or bs=="sell":
        sel_columns = sel_columns_sell
    else:
        if bs=="B" or bs=="BUY" or bs=="buy":
            sel_columns = sel_columns_buy
    return sel_columns


def prepare_result_files(result_file_basename, result_drop_base):
    result_file_base = os.path.join(result_drop_base, result_file_basename)

    result_file_md=result_file_base + ".md"
    result_file_csv=result_file_base + ".csv"
    return result_file_md,result_file_csv



def ensure_archival_directory_exists(source_dataset_archival_path):
    try:
        os.makedirs(source_dataset_archival_path,exist_ok=True)
    except:
    #exit the app with error about the directory
        print(f"Error creating directory {source_dataset_archival_path}")
        exit(1)


result_drop_base = create_result_directory(jgtdroot, output_subdir, result_drop_base_override)
source_dataset_archival_path = get_source_dataset_archival_path(source_dataset_archival_path_override, result_drop_base, get_arch_tdir)
sel_columns = make_columns_list_from_bs(sel_columns_sell, sel_columns_buy, bs)
result_file_md, result_file_csv = prepare_result_files(result_file_basename, result_drop_base)
ensure_archival_directory_exists(source_dataset_archival_path)



#




def write_to_result_csv(i,t,direction,nb_entry, tsum, eval_namespace,_df=None,ctx_name="",ctx_title="",csv_header="instrument,timeframe,direction,per_trade,nb_entry,tsum,eval_namespace,ctx_name,ctx_title"):
    per_trade=round(tsum/nb_entry,2)
    if direction == "sell" or direction=="Sell" or direction=="SELL":direction="S"
    if direction == "buy" or direction=="Buy" or direction=="BUY":direction="B"
    
    if not os.path.exists(result_file_csv):
        with open(result_file_csv, "a") as file_object:
            file_object.write(f"{csv_header}\n")
    with open(result_file_csv, "a") as file_object:
        tsum_rounded = round(tsum,2)
        file_object.write(f"{i},{t},{direction},{per_trade},{nb_entry},{tsum_rounded},{eval_namespace},{ctx_name},{ctx_title}\n")
    if _df is not None:
        save_df_archives(i, t, eval_namespace, _df)

def save_df_archives(i, t, title, _df,quiet=True):
    ifn = i.replace("/","-")
    csv_fn = f"{source_dataset_archival_path}/{ifn}_{t}_{title}.csv"
    if not quiet:
        print("Writing CSV to file:",csv_fn)
    _df.to_csv(csv_fn)


def write_to_result_md(entry_line):
    with open(result_file_md, "a") as file_object:
        file_object.write(f"{entry_line}\n")

def save_results(i,t,direction,nb_entry, tsum, title,_df=None,ctx_name="",ctx_title=""):
    per_trade=round(tsum/nb_entry,2)
    tsum_rounded = round(tsum,2)
    entry_line = f"{i}_{t} {direction} pt:{per_trade} t:{nb_entry} sum:{tsum_rounded} title:{title},ctx_name:{ctx_name},ctx_title:{ctx_title}"
    print(entry_line)
    write_to_result_md(entry_line)
    write_to_result_csv(i,t,direction,nb_entry, tsum, title,_df,ctx_name,ctx_title)



def get_pto_dataframe_mx_based_en_ttf(i, t, force_regenerate_mxfiles, mfi_flag, balligator_flag, talligator_flag, regenerate_cds, use_fresh, use_ttf_default):
    df=None
    try:
        if not force_regenerate_mxfiles:
            df = jtc.readMXFile(i,t)
    except:
        pass

#%pip install -U jgtpy

#set DF to None if column 'mfi' is not present (force regeneration)
    if df is not None and 'mfi' not in df.columns: #TMP to force regeneration if column mfi is not present
        df = None

    if df is None:
        df, sel1, sel2 = jtc.pto_target_calculation(i,t,
                                                mfi_flag=mfi_flag,talligator_flag=talligator_flag,
                                                balligator_flag=balligator_flag,
                                                regenerate_cds=regenerate_cds,
                                                use_fresh=use_fresh,
                                                use_ttf=use_ttf_default)
                                                    
    return df


# %%
#Remove invalid signal when column High < lips
#@STCGoal Valid Signals are bellow the lips and teeth 

# Base filtering
def filter_sig_is_out_of_normal_mouth_sell(dfsrc):
    df_sig_is_out_of_normal_mouth = dfsrc[dfsrc[LOW] > dfsrc[LIPS]].copy()
    df_sig_is_out_of_normal_mouth = df_sig_is_out_of_normal_mouth[df_sig_is_out_of_normal_mouth[LOW] > df_sig_is_out_of_normal_mouth[TEETH]]
    return df_sig_is_out_of_normal_mouth

def filter_sig_normal_mouth_is_open_sell(dfsrc):
    df_sig_normal_mouth_is_open = dfsrc[dfsrc[JAW] < dfsrc[TEETH]].copy()
    df_sig_normal_mouth_is_open = df_sig_normal_mouth_is_open[df_sig_normal_mouth_is_open[TEETH] < df_sig_normal_mouth_is_open[LIPS]]
    df_sig_normal_mouth_is_open = df_sig_normal_mouth_is_open[df_sig_normal_mouth_is_open[JAW] < df_sig_normal_mouth_is_open[LIPS]]
    return df_sig_normal_mouth_is_open

def filter_sig_is_out_of_normal_mouth_buy(dfsrc):
    df_sig_is_out_of_normal_mouth = dfsrc[dfsrc[HIGH] < dfsrc[LIPS]].copy()
    df_sig_is_out_of_normal_mouth = df_sig_is_out_of_normal_mouth[df_sig_is_out_of_normal_mouth[HIGH] < df_sig_is_out_of_normal_mouth[TEETH]]
    return df_sig_is_out_of_normal_mouth

def filter_sig_normal_mouth_is_open_buy(dfsrc):
    df_sig_normal_mouth_is_open = dfsrc[dfsrc[JAW] > dfsrc[TEETH]].copy()
    df_sig_normal_mouth_is_open = df_sig_normal_mouth_is_open[df_sig_normal_mouth_is_open[TEETH] > df_sig_normal_mouth_is_open[LIPS]]
    df_sig_normal_mouth_is_open = df_sig_normal_mouth_is_open[df_sig_normal_mouth_is_open[JAW] > df_sig_normal_mouth_is_open[LIPS]]
    return df_sig_normal_mouth_is_open


if _DEVFLAG:
    use_fresh=False
    regenerate_cds=False
    print("DEVFLAG: use_fresh:",use_fresh)
    print("DEVFLAG: regenerate_cds:",regenerate_cds)
 

#%%
if NB_CONTEXT_RUN:
    quiet=False if os.getenv("quiet") is None else quiet



#%% 
action_section_title="Filtering and Preparing Trading Signal Data for Context-Specific Analysis"
if _VERBOSE_ACTION:
    print(action_section_title)

section_details="""

From this point, we start evaluating the performance of the signals generated by the "Fractal Divergent Bar" indicator within the "Tide Alligator" technical analysis tool. We will analyze the effectiveness of the signals in the context of the "Tide Alligator" tool and evaluate the profitability of each signal type.
      
"""

regenerate_cds=False
use_fresh=False

df_ori_ttf = get_pto_dataframe_mx_based_en_ttf(i, t, force_regenerate_mxfiles, mfi_flag, balligator_flag, talligator_flag, regenerate_cds, use_fresh, use_ttf_default)

#%%


"""
This step focuses on reducing the dataset to relevant features.

This step removes data points that do not have a target signal.

removes data points that do not have a target signal and select relevant features for the analysis.

mastery #20
"""


def filter_relevant_features_with_targets(df, target_colname, selected_columns):
    """
    Filters the DataFrame to include only rows with non-zero target values and selected columns.

    Parameters:
    - df (DataFrame): The original DataFrame to filter.
    - target_colname (str): The name of the target column to filter by.
    - selected_columns (list): List of column names to retain in the filtered DataFrame.

    Returns:
    - DataFrame: Filtered DataFrame with only relevant features and non-zero target values.
    """
    # Filter rows where the target column is not 0
    df_filtered = df[df[target_colname] != 0].copy()
    # Select only the specified columns
    df_filtered = df_filtered[selected_columns].copy()
    return df_filtered

def filter_by_signal_bs_direction(df, signal_colname):
    """
    Filters the DataFrame to include only rows with non-zero values in the specified signal column.

    Parameters:
    - df (DataFrame): The DataFrame to filter.
    - signal_colname (str): The name of the signal column to filter by.

    Returns:
    - DataFrame: Filtered DataFrame with rows where the signal column is not 0.
    """
    return df[df[signal_colname] != 0].copy()


#  usage
df_filtered_features_n_targets = filter_relevant_features_with_targets(df_ori_ttf, eval_target_colname, sel_columns)
eval_signal_ctx_colname = eval_signal_buy_colname if bs == "B" else eval_signal_sell_colname
df_ctx_filtered_signals_bs_direction = filter_by_signal_bs_direction(df_filtered_features_n_targets, eval_signal_ctx_colname)





#%%


all_context_signal_count = len(df_ctx_filtered_signals_bs_direction)


all_evalname_signals_sum=df_ctx_filtered_signals_bs_direction[eval_target_colname].sum()


df_sig_is_out_of_normal_mouth = filter_sig_is_out_of_normal_mouth_sell(df_ctx_filtered_signals_bs_direction) if bs=="S" else filter_sig_is_out_of_normal_mouth_buy(df_ctx_filtered_signals_bs_direction)
df_sig_normal_mouth_is_open=filter_sig_normal_mouth_is_open_sell(df_sig_is_out_of_normal_mouth) if bs=="S" else filter_sig_normal_mouth_is_open_buy(df_sig_is_out_of_normal_mouth)


# INDEPENDENT OF DIRECTIONS
sig_is_out_of_normal_mouth_count = len(df_sig_is_out_of_normal_mouth)
sig_is_out_of_normal_mouth_sum=df_sig_is_out_of_normal_mouth[eval_target_colname].sum()

sig_normal_mouth_is_open_count = len(df_sig_normal_mouth_is_open)
sig_normal_mouth_is_open_sum=df_sig_normal_mouth_is_open[eval_target_colname].sum()



signal_title_part = f'FDB {"Sell" if bs == "S" else "Buy"} Signal'

ctx_title = f"Unfiltered {signal_title_part}"



ctx_evaltitle = "Tide Alligator"
ctx_name="tide"

out_all_evalname_signals_sum_colname = "all_evalname_signals"
out_sig_normal_mouth_is_open_sum_colname = "sig_normal_mouth_is_open"
out_sig_is_out_of_normal_mouth_sum_colname = "sig_is_out_of_normal_mouth"


out_sig_is_in_ctx_teeth_sum_colname = "sig_is_in_ctx_teeth_sum"
out_sig_ctx_mouth_is_open_and_signal_is_in_ctx_lips_sum_colname = "sig_ctx_mouth_is_open_and_in_ctx_lips"
out_sig_ctx_mouth_is_open_and_signal_is_in_ctx_teeth_sum_colname = "sig_ctx_mouth_is_open_and_in_ctx_teeth_sum"


def get_alligator_column_names_from_ctx_name(ctx_name):
    if ctx_name=="ripple" or ctx_name=="normal":
        cteeth_colname = TEETH
        clips_colname = LIPS
        cjaw_colname = JAW

    if ctx_name=="tide":
        cteeth_colname = TTEETH
        clips_colname = TLIPS
        cjaw_colname = TJAW


    if ctx_name=="big":
        cteeth_colname = BTEETH
        clips_colname = BLIPS
        cjaw_colname = BJAW
    return cteeth_colname,clips_colname,cjaw_colname


# CTX filtering

def filter_sig_is_in_ctx_teeth_sell(dfsrc, cteeth_colname, teval_colname):
    df_sig_is_in_ctx_teeth=dfsrc[
    dfsrc[teval_colname] > dfsrc[cteeth_colname]
    ].copy()
    return df_sig_is_in_ctx_teeth

def filter_sig_is_in_ctx_teeth_buy(df_sig_is_out_of_normal_mouth, cteeth_colname, teval_colname):
    df_sig_is_in_ctx_teeth=df_sig_is_out_of_normal_mouth[
    df_sig_is_out_of_normal_mouth[teval_colname] < df_sig_is_out_of_normal_mouth[cteeth_colname]
    ].copy()
    return df_sig_is_in_ctx_teeth


def filter_sig_ctx_mouth_is_open_and_in_ctx_teeth_sell(dfsrc, cteeth_colname, clips_colname, cjaw_colname, teval_colname):
    df_sig_ctx_mouth_is_open_and_in_ctx_teeth = dfsrc[
        dfsrc[teval_colname] > dfsrc[cteeth_colname]
        ].copy()

    df_sig_ctx_mouth_is_open_and_in_ctx_teeth = df_sig_ctx_mouth_is_open_and_in_ctx_teeth[  
        df_sig_ctx_mouth_is_open_and_in_ctx_teeth[clips_colname] < df_sig_ctx_mouth_is_open_and_in_ctx_teeth[cteeth_colname]
        ]
    df_sig_ctx_mouth_is_open_and_in_ctx_teeth = df_sig_ctx_mouth_is_open_and_in_ctx_teeth[  
        df_sig_ctx_mouth_is_open_and_in_ctx_teeth[cteeth_colname] < df_sig_ctx_mouth_is_open_and_in_ctx_teeth[cjaw_colname]
        ]
    return df_sig_ctx_mouth_is_open_and_in_ctx_teeth

def filter_sig_ctx_mouth_is_open_and_in_ctx_teeth_buy(dfsrc, cteeth_colname, clips_colname, cjaw_colname, teval_colname):
    df_sig_ctx_mouth_is_open_and_in_ctx_teeth = dfsrc[
        dfsrc[teval_colname] < dfsrc[cteeth_colname]
        ].copy()

    df_sig_ctx_mouth_is_open_and_in_ctx_teeth = df_sig_ctx_mouth_is_open_and_in_ctx_teeth[  
        df_sig_ctx_mouth_is_open_and_in_ctx_teeth[clips_colname] > df_sig_ctx_mouth_is_open_and_in_ctx_teeth[cteeth_colname]
        ]
    df_sig_ctx_mouth_is_open_and_in_ctx_teeth = df_sig_ctx_mouth_is_open_and_in_ctx_teeth[  
        df_sig_ctx_mouth_is_open_and_in_ctx_teeth[cteeth_colname] > df_sig_ctx_mouth_is_open_and_in_ctx_teeth[cjaw_colname]
        ]
        
    return df_sig_ctx_mouth_is_open_and_in_ctx_teeth


def filter_sig_ctx_mouth_is_open_and_in_ctx_lips_sell(dfsrc, cteeth_colname, clips_colname, cjaw_colname, teval_colname):
    df_sig_ctx_mouth_is_open_and_in_ctx_lips = dfsrc[
        dfsrc[teval_colname] < dfsrc[clips_colname]
        ].copy()

    # the CMouth is Openned
    df_sig_ctx_mouth_is_open_and_in_ctx_lips = df_sig_ctx_mouth_is_open_and_in_ctx_lips[
        df_sig_ctx_mouth_is_open_and_in_ctx_lips[clips_colname] < df_sig_ctx_mouth_is_open_and_in_ctx_lips[cteeth_colname]
        ]
    df_sig_ctx_mouth_is_open_and_in_ctx_lips = df_sig_ctx_mouth_is_open_and_in_ctx_lips[
        df_sig_ctx_mouth_is_open_and_in_ctx_lips[cteeth_colname] < df_sig_ctx_mouth_is_open_and_in_ctx_lips[cjaw_colname]
        ]
    return df_sig_ctx_mouth_is_open_and_in_ctx_lips

def filter_sig_ctx_mouth_is_open_and_in_ctx_lips_buy(df_sig_is_out_of_normal_mouth, cteeth_colname, clips_colname, cjaw_colname, teval_colname):
    df_sig_ctx_mouth_is_open_and_in_ctx_lips = df_sig_is_out_of_normal_mouth[
        df_sig_is_out_of_normal_mouth[teval_colname] > df_sig_is_out_of_normal_mouth[clips_colname]
        ].copy()

    # the BMouth is Openned
    df_sig_ctx_mouth_is_open_and_in_ctx_lips = df_sig_ctx_mouth_is_open_and_in_ctx_lips[
        df_sig_ctx_mouth_is_open_and_in_ctx_lips[clips_colname] > df_sig_ctx_mouth_is_open_and_in_ctx_lips[cteeth_colname]
        ]
    df_sig_ctx_mouth_is_open_and_in_ctx_lips = df_sig_ctx_mouth_is_open_and_in_ctx_lips[
        df_sig_ctx_mouth_is_open_and_in_ctx_lips[cteeth_colname] > df_sig_ctx_mouth_is_open_and_in_ctx_lips[cjaw_colname]
        ]
        
    return df_sig_ctx_mouth_is_open_and_in_ctx_lips


cteeth_colname, clips_colname, cjaw_colname = get_alligator_column_names_from_ctx_name(ctx_name)

teval_colname = LOW if bs=="S" else HIGH

df_sig_is_in_ctx_teeth = filter_sig_is_in_ctx_teeth_sell(df_sig_is_out_of_normal_mouth, cteeth_colname, teval_colname) if bs=="S" else filter_sig_is_in_ctx_teeth_buy(df_sig_is_out_of_normal_mouth, cteeth_colname, teval_colname)

df_sig_ctx_mouth_is_open_and_in_ctx_teeth=filter_sig_ctx_mouth_is_open_and_in_ctx_teeth_sell(df_sig_is_out_of_normal_mouth, cteeth_colname, clips_colname, cjaw_colname, teval_colname) if bs=="S" else filter_sig_ctx_mouth_is_open_and_in_ctx_teeth_buy(df_sig_is_out_of_normal_mouth, cteeth_colname, clips_colname, cjaw_colname, teval_colname)    

df_sig_ctx_mouth_is_open_and_in_ctx_lips=filter_sig_ctx_mouth_is_open_and_in_ctx_lips_sell(df_sig_is_out_of_normal_mouth, cteeth_colname, clips_colname, cjaw_colname, teval_colname)  if bs=="S" else filter_sig_ctx_mouth_is_open_and_in_ctx_lips_buy(df_sig_is_out_of_normal_mouth, cteeth_colname, clips_colname, cjaw_colname, teval_colname)
    

    



sig_is_in_ctx_teeth_count = len(df_sig_is_in_ctx_teeth)
sig_is_in_ctx_teeth_sum=df_sig_is_in_ctx_teeth[eval_target_colname].sum()


                                       
sig_ctx_mouth_is_open_and_in_ctx_teeth_count = len(df_sig_ctx_mouth_is_open_and_in_ctx_teeth)
sig_ctx_mouth_is_open_and_in_ctx_teeth_sum=df_sig_ctx_mouth_is_open_and_in_ctx_teeth[eval_target_colname].sum()

                                                                   
sig_ctx_mouth_is_open_and_in_ctx_lips_count = len(df_sig_ctx_mouth_is_open_and_in_ctx_lips)
sig_ctx_mouth_is_open_and_in_ctx_lips_sum=df_sig_ctx_mouth_is_open_and_in_ctx_lips[eval_target_colname].sum()











#save an archive the original df
if archive_used_dataset:
    save_df_archives(i, t, "original", df_ori_ttf)







write_to_result_md("  ")
write_to_result_md("----")
write_to_result_md("  ")
write_to_result_md("==============================================================")


save_results(i,t,bs,all_context_signal_count,all_evalname_signals_sum,out_all_evalname_signals_sum_colname,df_ctx_filtered_signals_bs_direction,"",ctx_title)


ctx_title = f"{signal_title_part} when Normal Mouth is Open"
save_results(i,t,bs,sig_normal_mouth_is_open_count,sig_normal_mouth_is_open_sum,out_sig_normal_mouth_is_open_sum_colname,df_sig_normal_mouth_is_open,"",ctx_title)
write_to_result_md("==============================================================")


ctx_title = f"{signal_title_part} is Out of Normal Mouth and Mouth is Open"
save_results(i,t,bs,sig_is_out_of_normal_mouth_count,sig_is_out_of_normal_mouth_sum,out_sig_is_out_of_normal_mouth_sum_colname,df_sig_is_out_of_normal_mouth,"",ctx_title)
write_to_result_md("==============================================================")

ctx_title = f"{signal_title_part} In the {ctx_evaltitle} Teeth"
save_results(i,t,bs,sig_is_in_ctx_teeth_count,sig_is_in_ctx_teeth_sum,out_sig_is_in_ctx_teeth_sum_colname,df_sig_is_in_ctx_teeth,ctx_name,ctx_title)

ctx_name="tide"
ctx_title = f"{ctx_evaltitle} Mouth is Open and {signal_title_part} is in the {ctx_evaltitle} Lips"
save_results(i,t,bs,sig_ctx_mouth_is_open_and_in_ctx_lips_count,sig_ctx_mouth_is_open_and_in_ctx_lips_sum,out_sig_ctx_mouth_is_open_and_signal_is_in_ctx_lips_sum_colname,df_sig_ctx_mouth_is_open_and_in_ctx_lips,ctx_name,ctx_title )
#pt:32.42 t:132 sum:4279.999999999999 title:count_sell2s2 Low is Above Big Lips and Big Mouth is Open

ctx_name="tide"
ctx_title = f"{ctx_evaltitle} Mouth is Open and {signal_title_part} is in the {ctx_evaltitle} Teeth"
save_results(i,t,bs,sig_ctx_mouth_is_open_and_in_ctx_teeth_count,sig_ctx_mouth_is_open_and_in_ctx_teeth_sum,out_sig_ctx_mouth_is_open_and_signal_is_in_ctx_teeth_sum_colname,df_sig_ctx_mouth_is_open_and_in_ctx_teeth,ctx_name,ctx_title)
write_to_result_md("==============================================================")


#@STCIssue SPX500 D1, sig_ctx_mouth_is_open_and_in_ctx_teeth_sum has an interesting value when the Signal bar is in the big mouth
#pt:83.2 t:99 sum:8237.0 title:sig_ctx_mouth_is_open_and_in_ctx_teeth_sum
# %%
print("Saved md: ",result_file_md)
print("Saved csv: ",result_file_csv)
print("Completed processing for ",i,t,bs)