# source: https://raw.githubusercontent.com/DerSalvador/ananda/7481ac5ebea50d08f471ef1e2a144d43588262f6/AnandaStrategy.py
from freqtrade.strategy.interface import IStrategy
from pandas import DataFrame
import argparse
import logging
import time
from utils.coinGeckoAPI import CoinGeckoAPI
import pandas as pd
from tabulate import tabulate
from binance.client import Client
from binance.exceptions import BinanceAPIException
import requests, decimal
import time
from freqtrade.strategy import IStrategy
from freqtrade.strategy import CategoricalParameter, IntParameter
from functools import reduce
from pandas import DataFrame
from datetime import datetime
from dateutil import parser
import os 
import sys
# import timeit
from freqtrade.persistence import Trade
import numpy as np
# Get rid of pandas warnings during backtesting
import pandas as pd
from attrs import exceptions
pd.options.display.float_format = '{:f}'.format
pd.set_option('display.max_columns', None)
pd.set_option('display.max_rows', 200)
from sqlalchemy import create_engine

import sqlite3
import urllib3

from pandas import DataFrame, Series
# --------------------------------
import talib.abstract as ta
import ta as taa
import freqtrade.vendor.qtpylib.indicators as qtpylib
import numpy  # noqa

import requests
import json
import pywt
import talib.abstract as ta
from utils.DataframeUtils import DataframeUtils, ScalerType

from sklearn.preprocessing import RobustScaler
from xgboost import XGBRegressor
from lightgbm import LGBMRegressor
from utils.FuturesPositionsFetcher import FuturesPositionsFetcher
# from utils.coinGeckoAPI import CoinGeckoAPI
from typing import Dict, List, Optional, Tuple, Union
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart

import threading

import logging
import warnings
from scipy.stats import linregress

import threading
from contextvars import ContextVar
from typing import Any, Dict, Final, Optional

from sqlalchemy import create_engine, inspect
from sqlalchemy.exc import NoSuchModuleError
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.pool import StaticPool
# from binance.client import Client
from freqtrade.exceptions import OperationalException
from freqtrade.persistence.base import ModelBase
from freqtrade.persistence.custom_data import _CustomData
from freqtrade.persistence.key_value_store import _KeyValueStoreModel
from freqtrade.persistence.migrations import check_migrate
from freqtrade.persistence.pairlock import PairLock
from freqtrade.persistence.trade_model import Order, Trade 
import traceback
from utils.DataframeUtils import DataframeUtils, ScalerType
import pywt
import talib.abstract as ta

from freqtrade.rpc import RPCManager
from freqtrade.rpc.external_message_consumer import ExternalMessageConsumer
from freqtrade.rpc.rpc_types import (ProfitLossStr, RPCCancelMsg, RPCEntryMsg, RPCExitCancelMsg,
                                     RPCExitMsg, RPCProtectionMsg, RPCMessageType)

from utils.dsHedging import dsHedging
import numpy as np
from enum import Enum


ATR_PERIOD = 14  # Number of periods for ATR calculation
COOLDOWN_PERIOD = 300  # 5 minutes

# Dictionary to track last reversal times
last_reversal_time = {}
# Configure logging
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")

# Global variables
COOLDOWN_PERIOD = 300  # 5 minutes
last_reversal_time = {}
sleep = 5
SLIPPAGE_PERCENT = 0.001  # 0.1% slippage for limit orders
precision_cache = {}
# Configure logging
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
coinGeckoAPI = CoinGeckoAPI()


class Github_DerSalvador_ananda__AnandaStrategy__20250326_150227(IStrategy):
    INTERFACE_VERSION = 3
    # ROI table:
    # fmt: off
    minimal_roi = {'0': 1, '100': 2, '200': 3, '300': -1}
    # fmt: on
    # Stoploss:
    stoploss = -0.2
    # Trailing stop:
    trailing_stop = False
    trailing_stop_positive = 0.005
    trailing_stop_positive_offset = 0.03
    trailing_only_offset_is_reached = True
    # Buy hypers
    timeframe = '5m'
    use_exit_signal = False
    # #################### END OF RESULT PLACE ####################

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # Get market bias
        symbol = metadata['pair'].replace("/USDT:USDT", "")
        market_bias = coinGeckoAPI.get_file_sentiment(symbol, coinGeckoAPI.apikey, coinGeckoAPI.apisecret)
        logging.info(f"Market bias for {symbol} is {market_bias}")
        if market_bias == "neutral":
            logging.info(f"Market bias is {market_bias} for {symbol}, skipping order.")
        if market_bias == "long":       
            logging.info(f"Market bias is {market_bias} for {symbol}, skipping order.")
            dataframe.loc[:, ['enter_long', 'enter_tag']] = (1, 'entry_reason')
        else:
            dataframe.loc[:, ['enter_long', 'enter_tag']] = (0, 'entry_reason')
            
        if market_bias == "short":             
            logging.info(f"Market bias is {market_bias} for {symbol}, skipping order.")
            dataframe.loc[:, ['enter_short', 'enter_tag']] = (1, 'entry_reason')
        else:
            dataframe.loc[:, ['enter_short', 'enter_tag']] = (0, 'entry_reason')
            

        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        return dataframe

    def custom_exit(self, pair: str, trade: Trade, current_time: datetime, current_rate: float,
                    current_profit: float, **kwargs):
        is_short = trade.is_short
        market_bias = coinGeckoAPI.get_file_sentiment(symbol, coinGeckoAPI.apikey, coinGeckoAPI.apisecret)
        logging.info(f"Market bias for {symbol} is {market_bias}")
        if market_bias == "long" and is_short:       
            logging.info(f"Trade is short but bias is long, selling short")
            return true
            
        if market_bias == "short" and not is_short:             
            logging.info(f"Trade is long but bias is short, selling long")
            return true
                
    def leverage(self, pair: str, current_time: datetime, current_rate: float,
                 proposed_leverage: float, max_leverage: float, entry_tag: str | None, side: str,
                 **kwargs) -> float:
        """
        Customize leverage for each new trade. This method is only called in futures mode.

        :param pair: Pair that's currently analyzed
        :param current_time: datetime object, containing the current datetime
        :param current_rate: Rate, calculated based on pricing settings in exit_pricing.
        :param proposed_leverage: A leverage proposed by the bot.
        :param max_leverage: Max leverage allowed on this pair
        :param entry_tag: Optional entry_tag (buy_tag) if provided with the buy signal.
        :param side: "long" or "short" - indicating the direction of the proposed trade
        :return: A leverage amount, which is between 1.0 and max_leverage.
        """
        return 5 # Should be configurable
    
# if __name__ == "__main__":
#     parser = argparse.ArgumentParser(description="Binance Futures Position Manager")
#     parser.add_argument("--apikey", required=True, help="Your Binance API Key")
#     parser.add_argument("--apisecret", required=True, help="Your Binance API Secret")
#     parser.add_argument("--loss", type=float, default=5.0, help="Loss percentage to trigger position reversal (default: 5%)")
#     parser.add_argument("--profit", type=float, default=6.0, help="Profit percentage to trigger position closure (default: 6%)")
#     parser.add_argument("--sleep", type=float, default=5.0, help="sleep in seconds before api call")
#     parser.add_argument("--leverage", type=float, default=5.0, help="leverage")
#     parser.add_argument("--stake", type=float, default=50.0, help="Stake amount per trade (default: 500 USDT)")

#     args = parser.parse_args()

#     coinGeckoAPI.coinGeckoAPIKey = "CG-AgEZRgMf3iLk1S8CwyCKp7N3"
#     coinGeckoAPI.apikey = args.apikey
#     coinGeckoAPI.apisecret = args.apisecret
#     sleep = args.sleep
#     leverage = args.leverage
#     stake_amount = args.stake

#     client = Client(args.apikey, args.apisecret)

#     logging.info(f"Monitoring positions for {args.loss}% loss threshold and {args.profit}% profit threshold...")
#     # monitor_and_manage(client, args.loss, args.profit, leverage, stake_amount)
