from django.views import generic

from ekidata.models import Join, Line

class DetailLineView(generic.DetailView):
    template_name = 'ekidata/detail_line.html'
    model = Line

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)

        station_list = []

        for station in self.object.station_set.all():
            station_list.append({
                'station': station,
                'join_next_list': [
                    join.station_2 for join in Join.objects.filter(
                        line=self.object, station_1=station
                    )],
                'join_prev_list': [
                    join.station_1 for join in Join.objects.filter(
                        line=self.object, station_2=station
                    )],
            })

        context['station_list'] = station_list

        return context


import pandas as pd
import numpy as np

df = pd.read_csv("input/Grocery_Db.csv")
prices = np.round(np.absolute(np.random.randn(df.shape[0])*50),2)
# df.drop('id')
df["price"] = prices
for i in range(df.shape[0]):
    df.at[i,'name'] = df.at[i,'name'].replace(',',' ')
print (df)
df.to_csv('input/ModifiedGroceryList.csv')

print(df.shape)


# -*- coding: utf-8 -*-
"""
Created on Sat Jun 24 13:35:36 2017

@author: marina
"""

import random
import string

WORDLIST_FILENAME = "words.txt"

def load_words():
    """
    Returns a list of valid words. Words are strings of lowercase letters.

    Depending on the size of the word list, this function may
    take a while to finish.
    """
    print("Loading word list from file...")
    # inFile: file
    inFile = open(WORDLIST_FILENAME, 'r')
    # line: string
    line = inFile.readline()
    # wordlist: list of strings
    wordlist = line.split()
    print("  ", len(wordlist), "words loaded.")
    return wordlist

def choose_word(wordlist):
    """
    wordlist (list): list of words (strings)

    Returns a word from wordlist at random
    """
    return random.choice(wordlist)

# end of helper code

# -----------------------------------

# Load the list of words into the variable wordlist
# so that it can be accessed from anywhere in the program
wordlist = load_words()

def is_word_guessed(secret_word, letters_guessed):
    correct = 0
    for i in range(len(secret_word)):
        if secret_word[i] in letters_guessed:
            correct += 1
            if correct == len(secret_word):
                return True
        else:
            return False

def get_guessed_word(secret_word, letters_guessed):
    string = ""
    for i in secret_word:
        if i in letters_guessed:
            string += i
        else:
            string += '*'
    return string
guesses = 6
number_letters = 0
secret_word = choose_word(wordlist)

def get_available_letters(letters_guessed):
    available_letters = ""
    for letter in string.ascii_lowercase:
        if letter not in letters_guessed:
            available_letters = available_letters + letter
    return available_letters

def get_unique_letters(secret_word):
    letters = []
    for letter in secret_word:
        if letter not in letters:
            letters.append(letter)
    return len(letters)

def match_with_gaps(my_word, other_word):
    my_word = my_word.replace(' ','')
    other_word = other_word.replace(' ','')
    if len(my_word) != len(other_word):
        return False
    my_word_list = list(my_word)
    other_word_list = list(other_word)
    i = 0
    for letter in my_word_list:
        if letter != '*':
            if my_word_list.count(letter) != other_word_list.count(letter):
                return False
            if letter != other_word_list[i]:
                return False
        i += 1
    return True

def show_possible_matches(my_word):
    matches = False
    match_list = []
    for word in wordlist:
        if match_with_gaps(my_word, word):
            match_list.append(word)
            matches = True
    if matches:
        print("Possible word matches are:")
        print(' '.join(match_list))
    else:
        print("No matches found")

def get_unique_letters(secret_word):
    letters = []
    for letter in secret_word:
        if letter not in letters:
            letters.append(letter)
    return len(letters)

def hangman_with_hints(secret_word):
    print("Welcome to the game Hangman!")
    warnings_remaining = 3
    print("I am thinking of a word that is", len(secret_word), "letters long.")
    print("You have", warnings_remaining, "warnings left.")
    letters_guessed = []
    guesses_remaining = 6
    while guesses_remaining > 0 and not is_word_guessed(secret_word, letters_guessed):
        print ("-------------")
        print("You have", guesses_remaining, "guesses left")
        print("Available letters:", get_available_letters(letters_guessed))
        guess = input("Please guess a letter: ")
        if guess == '*':
            show_possible_matches(get_guessed_word(secret_word, letters_guessed))
        else:
            if not str.isalpha(guess):
                print( "Oops! That is not a valid letter.")
                if warnings_remaining > 0:
                    warnings_remaining -= 1
                    print("You have " + str(warnings_remaining) + " warnings left.")
                else:
                    guesses_remaining -= 1
                    print("You have no warnings left so you lose one guess:")
            else:
                guess = str.lower(guess)
                if guess in letters_guessed:
                    print("Oops! You've already guessed that letter.")
                    if warnings_remaining > 0:
                        warnings_remaining -= 1
                        print ("You have " + str(warnings_remaining) + " warnings left.")
                    else:
                        guesses_remaining -= 1
                        print("You have no warnings left so you lose one guess.")
                else:
                    letters_guessed.append(guess)
                    if guess in secret_word:
                        print( "Good guess:", get_guessed_word(secret_word, letters_guessed))
                    else:
                        if guess in 'aeuio':
                            guesses_remaining -= 2
                        else:
                            guesses_remaining -= 1
                        print("Oops! That letter is not in my word:" , get_guessed_word(secret_word, letters_guessed))

    print ("-------------")
    if is_word_guessed(secret_word, letters_guessed):
        print("Congratulations, you won!")
        total_score = guesses_remaining * get_unique_letters(secret_word)
        print("Your total score for this game is:", total_score)
    else:
        print("Sorry, you ran out of guesses. The word was else.")

if __name__ == "__main__":

    secret_word = choose_word(wordlist)
    hangman_with_hints(secret_word)
input("Press the enter key to exit.")


from config import opts
import time
import pickle
from utils.model import SDPP
from utils.utils_func import shuffle_data, get_batch, analysis_data, ProgressBar
from utils.metrics import mSEL, mape_loss_func2, MSEL, accuracy
import tensorflow as tf
from tqdm import tqdm
import numpy as np
import math
import os
import sys

sys.path.append('./')

os.environ['CUDA_VISIBLE_DEVICES'] = '1'
tf.set_random_seed(0)

n_nodes, n_sequences, n_steps = pickle.load(open(opts.information, 'rb'))
opts.n_sequences = n_sequences
opts.n_steps = n_steps
print("dataset information: nodes:{}, n_sequence:{}, n_steps:{} ".format(n_nodes, n_sequences, n_steps))

opts.dropout_prob = 0.001
opts.learning_rate = 0.005
opts.emb_learning_rate = 0.0005

print("===================configuration===================")
print("dropout prob : ", opts.dropout_prob)
print("l2", opts.l2)
print("learning rate : ", opts.learning_rate)
print("emb_learning_rate : ", opts.emb_learning_rate)
print("observation hour [{},{}]".format(opts.start_hour, opts.end_hour))
print("observation threshold : ", opts.observation_time)
print("prediction time : ", opts.prediction_time)
print("cascade length [{},{}]".format(opts.least_num, opts.up_num))
print("model save at : {}".format(opts.save_dir))
print("===================configuration===================")

x_train, y_train, sz_train, time_train, rnn_index_train, vocabulary_size = pickle.load(open(opts.train_pkl, 'rb'))
x_test, y_test, sz_test, time_test, rnn_index_test, _ = pickle.load(open(opts.test_pkl, 'rb'))
x_val, y_val, sz_val, time_val, rnn_index_val, _ = pickle.load(open(opts.val_pkl, 'rb'))

analysis_data(y_train, y_test, y_val)
print(len(x_train), len(x_test), len(x_val))

training_iters = opts.training_iters
batch_size = opts.batch_size
display_step = math.ceil(len(x_train) / batch_size)  # display for each epoch
epoch_batch = math.ceil(len(sz_train) / batch_size)

# determine the way floating point numbers,arrays and other numpy object are displayed
np.set_printoptions(precision=2)

sess = tf.Session(config=tf.ConfigProto(allow_soft_placement=True))
start = time.time()
model = SDPP(opts, sess, n_nodes)

step = 0
best_val_loss = 1000
best_test_loss = 1000

# Keep training until reach max iterations or max_try
train_loss = []
train_mse = []
max_try = 8
patience = max_try

start = time.time()
# 保存模型
saver = tf.train.Saver(max_to_keep=5)
pbar_train = ProgressBar(n_total=math.ceil(training_iters/batch_size), desc="Training")
while step * batch_size < training_iters:
    batch_x, batch_x_indict, batch_y, batch_time_interval_index, batch_rnn_index = get_batch(x_train,
                                                                                y_train,
                                                                                sz_train,
                                                                                time_train,
                                                                                rnn_index_train,
                                                                                step,
                                                                                opts)
    pred = model.train_batch(batch_x, batch_x_indict, batch_y, batch_time_interval_index, batch_rnn_index)

    loss_train = model.get_error(batch_x, batch_x_indict, batch_y, batch_time_interval_index, batch_rnn_index)
    train_loss.append(loss_train)
    pbar_train(step, {'loss': train_loss[-1]})
    if (step + 1) % display_step == 0:
        print('finish one epoch, time{}'.format(time.time() - start))

    if (step + 1) % display_step == 0:

        val_loss = []
        val_pred, val_truth = [], []
        pbar_val = ProgressBar(n_total=int(len(y_val) / batch_size), desc="Validating")
        for val_step in range(int(len(y_val) / batch_size)):
            val_x, val_x_indict, val_y, val_time_interval_index, val_rnn_index = get_batch(x_val, y_val, sz_val, time_val, rnn_index_val, val_step, opts)
            val_loss.append(model.get_error(val_x, val_x_indict, val_y, val_time_interval_index, val_rnn_index))
            pbar_val(val_step, {"loss": val_loss[-1]})
            predictions = model.predict(val_x, val_x_indict, val_y, val_time_interval_index, val_rnn_index)
            if opts.classification:
                predictions = predictions.argmax(axis=-1)
            val_pred.extend(predictions.squeeze().tolist())
            val_truth.extend(val_y.squeeze().tolist())

        test_loss = []
        test_pred, test_truth = [], []
        pbar_test = ProgressBar(n_total=int(len(y_test) / batch_size), desc="Testing")
        for test_step in range(int(len(y_test) / batch_size)):
            test_x, test_x_indict, test_y, test_time_interval_index, test_rnn_index = get_batch(x_test,
                                                                                y_test,
                                                                                sz_test,
                                                                                time_test,
                                                                                rnn_index_test,
                                                                                test_step,
                                                                                opts)
            test_loss.append(model.get_error(test_x, test_x_indict, test_y, test_time_interval_index, test_rnn_index))
            pbar_test(test_step, {"loss": test_loss[-1]})
            predictions = model.predict(test_x, test_x_indict, test_y, test_time_interval_index, test_rnn_index)
            if opts.classification:
                predictions = predictions.argmax(axis=-1)
            test_pred.extend(predictions.squeeze().tolist())
            test_truth.extend(test_y.squeeze().tolist())

        predict_result = []
        if np.mean(val_loss) < best_val_loss:
            best_val_loss = np.mean(val_loss)
            patience = max_try

        if np.mean(test_loss) < best_test_loss:
            saver.save(sess, opts.save_dir, global_step=step)
            best_test_loss = np.mean(test_loss)

        if not opts.classification:
            median_loss = np.median((np.array(test_pred) - np.array(test_truth))**2)
            median_val_loss = np.median((np.array(val_pred) - np.array(val_truth))**2)
            # val metric
            val_mape = mape_loss_func2(val_pred, val_truth)
            val_acc = accuracy(np.array(val_pred), np.array(val_truth), 0.5)
            val_mSEL = mSEL(MSEL(val_pred, val_truth))
            # test metric
            test_mape = mape_loss_func2(test_pred, test_truth)
            test_acc = accuracy(np.array(test_pred), np.array(test_truth), 0.5)
            test_mSEL = mSEL(MSEL(test_pred, test_truth))
        else:
            # acc in actually
            acc_test = np.sum(np.equal(np.array(test_pred), np.array(test_truth))) / len(test_pred)
            acc_valid = np.sum(np.equal(np.array(val_pred), np.array(val_truth))) / len(val_pred)

        if not opts.classification:
            print("\n#" + str(int(step / display_step)) + ", Training Loss= " + "{:.5f}".format(np.mean(train_loss)) + ", Valid Loss= " + "{:.5f}".format(np.mean(val_loss)) + ", Valid median Loss= " +
                  "{:.5f}".format(median_val_loss) + ", Best Valid Loss= " + "{:.5f}".format(best_val_loss) + ", Test Loss= " + "{:.5f}".format(np.mean(test_loss)) + ", Test median  Loss= " +
                  "{:.5f}".format(median_loss) + ", Best Test Loss= " + "{:.5f}".format(best_test_loss))
            print(' Val Loss mSEL:{:5f}, Test Loss mSEL:{:5f},'.format(val_mSEL, test_mSEL))
            print(' Val acc:{:5f}, Test acc:{:5f},'.format(val_acc, test_acc))
            print(' Val Loss mape:{:5f}, Test Loss mape:{:5f},\n'.format(val_mape, test_mape))
        else:
            print("#" + str(int(step / display_step)) + ", Training Loss= " + "{:.6f}".format(np.mean(train_loss)) + ", Validation Loss= " + "{:.6f}".format(np.mean(val_loss)) + ", Valid acc= " +
                  "{:.6f}".format(acc_valid) + ", Test Loss= " + "{:.6f}".format(np.mean(test_loss)) + ", Test acc= " + "{:.6f}".format(acc_test) + ", Best Valid Loss= " +
                  "{:.6f}".format(best_val_loss) + ", Best Test Loss= " + "{:.6f}".format(best_test_loss))

        train_loss = []
        patience -= 1
        if not patience:
            break
    step += 1
    if step % epoch_batch == 0:
        x_train, y_train, sz_train, time_train, rnn_index_train = shuffle_data(x_train, y_train, sz_train, time_train, rnn_index_train)
        x_test, y_test, sz_test, time_test, rnn_index_test = shuffle_data(x_test, y_test, sz_test, time_test, rnn_index_test)
        x_val, y_val, sz_val, time_val, rnn_index_val, = shuffle_data(x_val, y_val, sz_val, time_val, rnn_index_val)

print("Finished!\n----------------------------------------------------------------")
print("Time:", time.time() - start)
print("Valid Loss:", best_val_loss)
print("Test Loss:", best_test_loss)


from aiogram import Router, F
from aiogram.filters import Command, CommandStart
from aiogram.types import Message

from tgbot.lexicon.lexicon_ru import lexicon_ru_dict, lexicon_reply_kb
from tgbot.keyboards.reply.start_kb import create_reply_kb

user_router = Router()

@user_router.message(CommandStart())
async def user_start(message: Message):
    await message.answer(text=lexicon_ru_dict['/start'], reply_markup=create_reply_kb(1, 'contact_us', 'donate'))

# Этот хэндлер срабатывает на команду /help
@user_router.message(Command(commands='help'))
async def process_help_command(message: Message):
    await message.answer(text=lexicon_ru_dict['/help'], reply_markup=create_reply_kb(1, 'contact_us', 'back'))

@user_router.message(F.text == lexicon_reply_kb['donate'])
async def process_donate_answer(message: Message):
    await message.answer(text=lexicon_ru_dict['donate'], reply_markup=create_reply_kb(1, 'back'))

@user_router.message(F.text == lexicon_reply_kb['contact_us'])
async def process_donate_answer(message: Message):
    await message.answer(text=lexicon_ru_dict['contact_us'], reply_markup=create_reply_kb(1, 'back'))

@user_router.message(F.text == lexicon_reply_kb['back'])
async def process_donate_answer(message: Message):
    await message.answer(text=lexicon_ru_dict['/start'], reply_markup=create_reply_kb(1, 'contact_us', 'donate'))

@user_router.message(F.photo)
async def admin_start(message: Message):
    await message.answer(lexicon_ru_dict['photo'])


"""
A Client for the OKFN Badging service...
"""
import urllib2
import json
import hashlib
from urllib import quote

class Client():
    """ The client for Badging:

        Usage:
            c=Client(url, id, api_key)
        """

    def __init__(self, url, id, api_key):
        self.url=url
        self.id=id
        self.api_key=api_key

    def issue(self, badge, recipient, evidence=None):
        """ Issue a badge to recipient """
        parameters={
            "id": str(self.id),
            "badge": badge,
            "recipient": recipient,
            "signature": hashlib.sha256(badge + recipient +
                                        self.api_key).hexdigest(),
            }
        if evidence:
            parameters['evidence']=evidence
        parameters="&".join(("%s=%s" % (k, quote(v)) for (k, v) in
                                parameters.items()))
        url="%s/api/issue?%s" % (self.url, parameters)
        u=urllib2.urlopen(url)
        return json.load(u)


import numpy as np
import os
execfile(os.path.join(os.path.dirname(__file__), "fix_imports.py"))
import config
from utils import *

class DataSet(object):
  """docstring for DataSet"""
  def __init__(self, descriptor_type, config_net = None):
    self.name            = config_net['dataset']
    self.config_net      = config_net
    self.descriptor_type = descriptor_type
    # if config_net != None:
    self.path_feat = os.path.join(config.descriptors_path, self.name, "_".join((descriptor_type, config_net['name'], config.name_features)))
    self.path_feat_mirrored = os.path.join(config.descriptors_path, self.name, "_".join((descriptor_type, config_net['name'], config.name_features_mirror)))
    # else:
    #   self.path_feat = os.path.join(config.descriptors_path, self.name, "_".join((descriptor_type,config.name_features)))

    path_label = os.path.join(config.databases_path, self.name, config.name_labels)
    self.labels = np.load(path_label)

  def loadPathRawData(self):
    path_data = os.path.join(config.databases_path, self.name, config.name_data_filename)
    with open(path_data,'r') as f:
      files_path = [line.strip() for line in f]
    return files_path

  def loadDataClassification(self, type_data):
    if type_data == "train":
      path_labels = os.path.join(config.databases_path, self.name, config.name_label_train)
    elif type_data == "val":
      path_labels = os.path.join(config.databases_path, self.name, config.name_label_val)

    labels   = np.load(path_labels)
    return labels

  def loadDataVerification(self, type_data):
    if type_data == "train":
      path_labels = os.path.join(config.databases_path, self.name, config.name_ver_train)
    elif type_data == "val":
      path_labels = os.path.join(config.databases_path, self.name, config.name_ver_val)

    labels   = np.load(path_labels)
    return  labels

  def loadFeatures(self):
    self.features = np.load(self.path_feat)
    return self.features

  def loadFeaturesMirrored(self):
    self.features = np.load(self.path_feat_mirrored)
    return self.features

  def loadLFW(self):
    '''Load LFW database using same net like in config file. Return all data and ground truth which point pairs'''
    path_feat   =  os.path.join(config.descriptors_path, self.config_net['lfw_folder'], "_".join((self.descriptor_type, self.config_net['name'], config.name_features)))
    path_labels =  os.path.join(config.databases_path, self.config_net['lfw_folder'], self.config_net['lfw_name'] + '_' + config.lfw_pairs_path)
    features    =  np.load(path_feat)
    pairs       =  np.load(path_labels)
    return  features.astype(np.float32), pairs

  def loadLFWMirrored(self):
    path_feat   =  os.path.join(config.descriptors_path, self.config_net['lfw_folder'], "_".join((self.descriptor_type, self.config_net['name'], config.name_features_mirror)))
    features    =  np.load(path_feat)
    return  features

  def loadBLUFR(self):
    '''Load BLUFR data: features and verification data'''
    path_feat   =  os.path.join(config.descriptors_path, self.config_net['blufr_folder'], "_".join((self.descriptor_type, self.config_net['name'], config.name_features)))
    path_pairs  =  os.path.join(config.databases_path, self.config_net['blufr_folder'], config.blufr_lfw_test_ver_file)
    features    =  np.load(path_feat)
    with open(path_pairs,'r') as f:
      pair_files = [ line.strip() for line in  f.readlines()]

    return features, pair_files


from persona import Persona
from departamento import Departamento
from trabajador import Trabajador

def conocer_instancia(objeto, objeto_comparar):
    return 'Si' if isinstance(objeto, objeto_comparar) else 'No'

trabajador1 = Trabajador("Juan", "Perez", "2005", "Ingenieria de software", "IS", "20000")

# print(trabajador1.nombre)
# print(trabajador1.apellido)
# print(trabajador1.nombre_dpto)
# print(trabajador1.salario)

#! Drilling

print(trabajador1.__dict__)
print("Es trabajador instancia de Persona: ",conocer_instancia(trabajador1, Persona))
print("Es trabajador instancia de Departamento: ",conocer_instancia(trabajador1, Departamento))
print("Es trabajador instancia de Trabajador: ",conocer_instancia(trabajador1, Trabajador))


import sys

def part1(forest: list[list[int]]) -> int:
    size = len(forest[0])
    # array of maxes from each direction (E, W, N, S)
    maxes = [[[0, 0, 0, 0] for x in range(size)] for y in range(size)]

    for y in range(1, size-1):
        # calculate maxes from east
        for x in range(1, size-1):
            maxes[y][x][0] = max(maxes[y][x-1][0], forest[y][x-1])

        # calculate maxes from west
        for x in range(size-2, 0, -1):
            maxes[y][x][1] = max(maxes[y][x+1][1], forest[y][x+1])

    for x in range(size):
        # calculate maxes from north
        for y in range(1, size-1):
            maxes[y][x][2] = max(maxes[y-1][x][2], forest[y-1][x])

        # calculate maxes from south
        for y in range(size-2, 0, -1):
            maxes[y][x][3] = max(maxes[y+1][x][3], forest[y+1][x])

    # visible trees are those that are greater than the max from any direction
    visible = (size-1)*4  # edges
    for y in range(1, size-1):
        for x in range(1, size-1):
            if forest[y][x] > min(maxes[y][x]):
                visible += 1

    return visible

def part2(forest: list[list[int]]) -> int:
    size = len(forest[0])
    max_score = 0
    for y in range(size):
        for x in range(size):
            # number of trees visible in each direction
            east, west, north, south = 0, 0, 0, 0
            # east
            for i in range(x-1, -1, -1):
                east += 1
                if forest[y][i] >= forest[y][x]:
                    break
            # west
            for i in range(x+1, size):
                west += 1
                if forest[y][i] >= forest[y][x]:
                    break
            # north
            for i in range(y-1, -1, -1):
                north += 1
                if forest[i][x] >= forest[y][x]:
                    break
            # count south
            for i in range(y+1, size):
                if forest[i][x] >= forest[y][x]:
                    break
                south += 1
            max_score = max(max_score, east * west * north * south)

    return max_score

if __name__ == '__main__':
    forest = [[int(n) for n in [*line.rstrip()]] for line in sys.stdin]
    print("Part 1: %d" % part1(forest))
    print("Part 2: %d" % part2(forest))


#!/usr/bin/env python
# coding=utf-8

import json

class pay_pam_diy:

    def __init__(self):
        # 支付参数获取
        pass

    def GetMaikanData(self, paydata, DB):

        _id = 0
        _price2 = 0
        _name = ""
        json_data = paydata
        wid = json_data["wid"]
        b_uid = json_data["b_uid"]
        organization = json_data["organization"]
        distributor = json_data["distributor"]

        json_pay = {
                "Code": 0,
                "Data": {},
        }

        sql_str = "select ID,price2,`Name` from tb_workmarket where WID = " + str(wid) + " AND UID = " + str(b_uid) + ";"
        data = DB.fetchone(sql_str, None)
        if data:
            _id = int(data[0])
            _price2 = int(data[1])
            _name = data[2]

        if _id == 0 or _price2 <= 0:
            json_pay["Code"] = 0  # 价格异常
        else:
            _power = 0
            if "power" in json_data.keys():
                _power = json_data["power"]
            params = str(wid) + "@" + str(b_uid) + "@" + str(organization) + "@" + str(distributor) + "@" + json_data["from"] + "@" + str(_power) + "@n@" + json_data["ip"]
            Data = {
                    "name": _name,
                    "price": _price2 * 10,  # 分
                    "params": params,
            }
            json_pay["Code"] = 1
            json_pay["Data"] = Data

        return json_pay

    def GetSISCourseData(self, paydata, DB):

        _id = 0
        _price2 = 0
        _name = ""
        json_data = paydata
        CourseID = json_data["wid"]
        BType = int(json_data["b_uid"])
        organization = json_data["organization"]
        distributor = json_data["distributor"]
        _from = json_data["from"]
        json_pay = {
                "Code": 0,
                "Data": {},
        }

        table_name = "new_coursedetails"
        if _from == "SISNG":
            table_name = "new_sis3dcoursedeta"

        if BType == 0:
            sql_str = "select id,coursePrice,`name` from " + table_name + " where courseId = '" + CourseID + "';"
        else:
            sql_str = "select id,courseYearPrice,`name` from " + table_name + " where courseId = '" + CourseID + "';"

        data = DB.fetchone(sql_str, None)
        _PRICE = 0
        if data:
            _id = int(data[0])
            _price2 = int(data[1])
            _name = data[2]
            if _from == "SISNG":
                _PRICE = _price2
            else:
                _PRICE = _price2 * 10

        if _id == 0 or _price2 < 0:
            json_pay["Code"] = 0  # 价格异常
        else:
            _power = 0
            if "power" in json_data.keys():
                _power = json_data["power"]
            params = str(CourseID) + "@" + str(BType) + "@" + str(organization) + "@" + str(distributor) + "@" + json_data["from"] + "@" + str(_power) + "@n@" + json_data["ip"]
            Data = {
                    "name": _name,
                    "price": _PRICE,  # 分
                    "params": params,
            }
            json_pay["Code"] = 1
            json_pay["Data"] = Data

        return json_pay

    def GetChangxiangData(self, paydata, DB):

        _id = 0
        _price2 = 0
        _name = ""
        json_data = paydata
        channel = json_data["changel"]
        month = int(json_data["month"])
        organization = json_data["organization"]
        distributor = json_data["distributor"]
        CIDS = ""

        json_pay = {
                "Code": 0,
                "Data": {},
        }

        sql_str = "select Price,`Desc`,WTYPE,CID from tb_channel where WID in (" + channel + ");"

        data = DB.fetchall(sql_str, None)
        _name = ""
        _wtype = ""
        _price_record = ""
        if data:
            list_data = list(data)
            for minfo in list_data:
                if _price_record == "":
                    _price_record = str(minfo[0])
                else:
                    _price_record = _price_record + "#" + str(minfo[0])
                _price2 += int(minfo[0])
                if _name == "":
                    _name = minfo[1]
                else:
                    _name = _name + "#" + minfo[1]
                if _wtype == "":
                    _wtype = str(minfo[2])
                else:
                    _wtype = _wtype + "#" + str(minfo[2])
                if CIDS == "":
                    CIDS = str(minfo[3])
                else:
                    CIDS = CIDS + "#" + str(minfo[3])

        if _price2 <= 0:
            json_pay["Code"] = 0  # 价格异常
        if _price2 > 0:
            sql_str = "select Days,`Discount` from tb_discount where CID = " + str(month) + ";"

            data = DB.fetchone()
            _price3 = 0
            days = 0
            if data:
                days = int(data[0])
                _price3 = float(data[1])
            if days == 0:
                json_pay["Code"] = -1  # 价格异常
            else:
                _price = int(int((days / 30)) * _price2 * _price3)
                if _price <= 0:
                    json_pay["Code"] = 0  # 价格异常
                else:
                    _power = 0
                    if "power" in json_data.keys():
                        _power = json_data["power"]
                    params = str(channel) + "@" + str(month) + "@" + str(days) + "@" + str(organization) + "@" + str(distributor) + "@" + json_data["from"] + "@" + str(_power) + "@" + json_data["ip"]

                    Data = {
                            "name": "频道畅享",
                            "price": _price,  # 分
                            "params": params,
                    }
                    json_pay["Code"] = 1
                    json_pay["Data"] = Data

        return json_pay

    def GetVipData(self, UID, paydata, DB):

        _id = 0
        _price2 = 0
        _name = ""
        json_data = paydata

        extra = json_data["extra"]
        model = int(json_data["model"])
        organization = json_data["organization"]
        distributor = json_data["distributor"]

        json_pay = {
                "Code": 0,
                "Data": {},
        }

        # vip
        b_date = 0
        # 存储位
        b_id = 0
        b_num = 0
        if model == 0:
            b_date = int(extra)
        elif model == 1:
            _arr = extra.split('$')
            b_id = int(_arr[0])
            b_num = int(_arr[1])

        bagID = 0
        pdate = 0
        # 验证下参数
        sql = ""
        if model == 0:
            sql = "select VIPDATE FROM Tb_Userdata where uid = " + str(UID)
        else:
            if b_id != 0:
                sql = "select ENDDATE,ID FROM TB_BAG where ID = " + str(b_id)
        _name = ""
        price = 0  # 分为单位
        if sql != "":

            data = DB.fetchone(sql, None)
            if data:
                _pam = int(data[0])
                if model == 0:
                    if _pam == 1:
                        json_pay["Code"] = -1
                        return json_pay
                    pdate = _pam
                else:
                    if extra != 0:
                        if _pam == 1:
                            json_pay["Code"] = -1
                            return json_pay
                        bagID = int(data[1])
                        pdate = _pam

        # 计算价格
        sql = "select VIPPrice,WorksAPrice,(select DiscountRate from tb_new_vipdiscount where ThePurchaseTime = " + str(b_date) + ") as rate from tb_new_config;"

        data = DB.fetchone(sql, None)
        _id = 0
        _price2 = 0

        if model == 0:
            _name = "VIP开通/续费"
        else:
            _name = "存储包裹"
        if data != None and len(data) > 0:
            # print("data", data)
            if model == 0:
                price = int(data[0] * data[2] * b_date)
            else:
                price = int(data[1]) * b_num

        if price <= 0:
            json_pay["Code"] = 0
        else:
            _power = 0
            if "power" in json_data.keys():
                _power = json_data["power"]
            params = str(model) + "@" + str(extra) + "@" + str(pdate) + "@" + str(bagID) + "@" + str(organization) + "@" + str(distributor) + "@" + json_data["from"] + "@" + str(_power) + "@" + \
                     json_data["ip"]

            Data = {
                    "name": _name,
                    "price": price,  # 分
                    "params": params,
            }
            json_pay["Code"] = 1
            json_pay["Data"] = Data

        return json_pay

    def GetWitScore(self, UID, paydata, DB):

        json_pay = {
                "Code": 0,
                "Data": {},
        }

        organization = paydata["organization"]
        distributor = paydata["distributor"]

        rmb = int(paydata["rmb"])
        if rmb <= 0:
            json_pay["Code"] = 0  # 价格异常
        else:
            price = rmb * 100
            _power = 0
            if "power" in paydata.keys():
                _power = paydata["power"]
            params = str(price) + "@" + str(organization) + "@" + str(distributor) + "@" + paydata["from"] + "@" + str(_power) + "@" + paydata["ip"]
            Data = {
                    "name": "充值中心",
                    "price": price,  # 分
                    "params": params,
            }
            json_pay["Code"] = 1
            json_pay["Data"] = Data

        return json_pay

    def GetProjectSisData(self, UID, paydata, DB):

        json_pay = {
                "Code": 0,
                "Data": {},
        }

        organization = paydata["organization"]
        distributor = paydata["distributor"]
        ptype = int(paydata["ptype"])
        cid = int(paydata["cid"])
        puid = int(paydata["puid"])
        lid = int(paydata["lid"])
        wid = int(paydata["wid"])
        buyCount = int(paydata["buyCount"])

        if buyCount <= 0:
            json_pay["Code"] = 0  # 价格异常
        else:
            sql = ""
            if ptype == 1:  # 工程
                json_pay["Code"] = -1  # 价格异常
            elif ptype == 2:  # 购买的作品
                sql = "SELECT T1.price1,T1.`Name` FROM tb_workmarket AS T1 INNER JOIN tb_project AS T2 ON T1.UID = T2.P_UID AND T1.PID = T2.ParentPid AND T2.uid = " + str(
                    puid) + " and T2.PID = " + str(wid)
            else:  # 课程
                sql = "select Price,`Name` from tb_mlesson_" + str(puid) + "_" + str(cid) + " where lid = " + str(lid) + "; "

            if len(sql) > 0:
                price = 0
                _name = ""

                data = DB.fetchone(sql, None)
                if data:
                    price = int(data[0])
                    _name = data[1]
                if price <= 0:
                    json_pay["Code"] = 0  # 价格异常
                else:
                    params = str(price) + "@" + str(organization) + "@" + str(distributor) + "@" + paydata["from"] + "@" + str(UID) + "@" + str(paydata["puid"]) + "@" + str(
                            paydata["cid"]) + "@" + str(paydata["lid"]) + "@" + str(paydata["wid"]) + "@" + str(paydata["buyCount"]) + "@" + str(ptype) + "@" + paydata["ip"]
                    Data = {
                            "name": _name,
                            "price": price * buyCount * 10,  # 分
                            "params": params,
                    }
                    json_pay["Code"] = 1
                    json_pay["Data"] = Data

        return json_pay

PayPamDiyClass = pay_pam_diy()


import pandas as pd
import pandas_ta as pt
import numpy as np
import vectorbt as vbt
import datetime
from scipy.stats import linregress
import re

pd.options.display.max_rows = 999

def EhlersSuperSmoother(close, length):
    a1 = np.exp(-np.sqrt(2) * np.pi / length)
    coeff2 = 2 * a1 * np.cos(np.sqrt(2) * np.pi / length)
    coeff3 = -(a1**2)
    coeff1 = 1 - coeff2 - coeff3
    filt = close.copy()
    n = filt.size
    if type(close) == pd.Series:
        for i in range(0, n):
            filt.iloc[i] = (
                coeff1 * (close.iloc[i] + close.iloc[i - 1]) / 2
                + coeff2 * filt.iloc[i - 1]
                + coeff3 * filt.iloc[i - 2]
            )
    else:
        for i in range(0, n):
            filt[i] = (
                coeff1 * (close[i] + close[i - 1]) / 2
                + coeff2 * filt[i - 1]
                + coeff3 * filt[i - 2]
            )
    return filt

def EhlersHighpass(close, length):
    a1 = np.exp(-np.sqrt(2) * np.pi / length)
    coeff2 = 2 * a1 * np.cos(np.sqrt(2) * np.pi / length)
    coeff3 = -(a1**2)
    coeff1 = (1 + coeff2 - coeff3) / 4
    filt = close.copy()
    n = filt.size
    for i in range(0, n):
        filt.iloc[i] = (
            coeff1 * (close.iloc[i] - (2 * close.iloc[i - 1] + close.iloc[i - 2]))
            + coeff2 * filt.iloc[i - 1]
            + coeff3 * filt.iloc[i - 2]
        )
    return filt

def vwap(price, volume, length):
    return (price * volume).rolling(length).sum() / volume.rolling(length).sum()

def dsma_alpha(price, length):
    price_change = price - price.shift(2)
    filt = EhlersSuperSmoother(price_change.bfill(), length)

    def rolling_rms(x):
        r = 1.0
        a = np.sqrt((len(x) * r**2) / (x**2).sum())
        x = x * a
        return x.iloc[-1]

    ScaledFilt = filt.rolling(length).apply(rolling_rms).bfill()

    alpha = ScaledFilt.abs() * 5 / length
    return alpha

def dsma(price, length):
    alpha = dsma_alpha(price, length)
    dsma = price.copy()
    n = dsma.size
    for i in range(1, n):
        dsma.iloc[i] = alpha[i] * price[i] + (1 - alpha[i]) * dsma[i - 1]
    return dsma

def ma_cloud_signal(
    data,
    ma_length1=11,
    ma_length2=24,
    target_pct=0.65,
    price_for_ma="open",
    shift=False,
):
    data = data.copy()
    if "date" in data.columns:
        data.set_index("date", inplace=True)
    data["day"] = pd.DatetimeIndex(data.index).date
    data["isFirstBar"] = data["day"].diff() >= "1 days"
    price = data[price_for_ma]
    volume = data.volume
    high = data.high
    low = data.low
    ma1 = vwap(price, volume, ma_length1)
    ma2 = vwap(price, volume, ma_length2)
    ma_mid = (ma1 + ma2) / 2
    longTarget = (target_pct / 100 + 1) * ma_mid
    shortTarget = ma_mid / (target_pct / 100 + 1)
    longExit = high > longTarget
    shortExit = low < shortTarget
    trend_up = ma1.gt(ma2)
    trend_down = ma1.lt(ma2)
    rsi = pt.rsi(data.open, 10)
    strong_trend = rsi.gt(40) & rsi.lt(80)
    newday_trendup_continuation = (
        data["isFirstBar"].fillna(False)
        & strong_trend
        & (trend_up.fillna(False) & ~longExit)
    )
    long = (trend_up & ~trend_up.shift().fillna(False)) | newday_trendup_continuation
    longX = longExit
    short = longExit
    shortX = shortExit | long
    signal = pd.DataFrame(
        columns=["Long", "LongX", "Short", "ShortX"], index=data.index
    )
    signal["Long"] = long
    signal["LongX"] = longX
    signal["Short"] = short
    signal["ShortX"] = shortX
    signal["longTarget"] = longTarget
    signal["shortTarget"] = shortTarget
    signal["maMID"] = ma_mid
    signal["RSI"] = rsi
    signal["EOD"] = pd.DatetimeIndex(signal.index).time == datetime.time(12, 50)
    if shift:
        return signal.shift()
    else:
        return signal

def ma_cloud_ichimoku_signal(
    data,
    ma_length1=15,
    ma_length2=24,
    target_pct=0.67,
    ichimoku_conversionLine_length=9,
    ichimoku_baseLine_length=26,
    price_for_ma="open",
    shift=False,
):
    data = data.copy()
    if "date" in data.columns:
        data.set_index("date", inplace=True)
    data["day"] = pd.DatetimeIndex(data.index).date
    data["isFirstBar"] = data["day"].diff() >= "1 days"
    price = data[price_for_ma]
    volume = data.volume
    high = data.high
    low = data.low
    ma1 = vwap(price, volume, ma_length1)
    ma2 = vwap(price, volume, ma_length2)
    ma_mid = (ma1 + ma2) / 2
    ma_bandwidth = ma1 - ma2
    longTarget = (target_pct / 100 + 1) * ma_mid
    shortTarget = ma_mid / (target_pct / 100 + 1)
    longExit = high > longTarget
    shortExit = low < shortTarget

    # Ichimoku
    ma_max = pd.concat([ma1, ma2], axis=1).max(axis=1).bfill()
    conversionLine = (
        low.rolling(ichimoku_conversionLine_length).min()
        + high.rolling(ichimoku_conversionLine_length).max()
    ) / 2

    baseLine = (
        low.rolling(ichimoku_baseLine_length).min()
        + high.rolling(ichimoku_baseLine_length).max()
    ) / 2
    leadline1 = (conversionLine + baseLine) / 2
    leadline2 = (
        low.rolling(int(2 * ichimoku_baseLine_length)).min()
        + high.rolling(int(2 * ichimoku_baseLine_length)).max()
    ) / 2
    close_under_ichimoku = data.close.lt(
        pd.concat([leadline1, leadline2], axis=1)
        .min(axis=1)
        .shift(ichimoku_baseLine_length - 1)
    )
    trend_up = ma1.gt(ma2)
    trend_down = ma1.lt(ma2)
    # rsi = pt.rsi(data.open, 10)
    rsi = pt.rsi(data.ta.hlc3(), 10)
    strong_trend = rsi.gt(20) & rsi.lt(80)
    newday_trendup_continuation = (
        data["isFirstBar"].fillna(False)
        & strong_trend
        & (trend_up.fillna(False) & ~longExit)
        & ma_bandwidth.pct_change().gt(0)
    )
    shortCondition = (
        (close_under_ichimoku & ~close_under_ichimoku.shift().fillna(False))
        & trend_down.fillna(False)
    ) | (
        close_under_ichimoku.fillna(False)
        & trend_down.fillna(False)
        & data["isFirstBar"].fillna(False)
        # & ~shortExit
    )
    momentum_condition1 = (rsi.gt(rsi.shift())).fillna(False)
    # momentum_condition2 = (close - op).gt(0)
    momentum_condition = momentum_condition1
    longCondition = (
        (trend_up & ~trend_up.shift().fillna(False)) & momentum_condition
    ) | newday_trendup_continuation
    long = longCondition
    longX = longExit
    # short = longExit | shortCondition
    short = shortCondition
    shortX = shortExit | long
    # long = trend_up & ~trend_up.shift().fillna(False)
    # longX = longExit
    # short = longExit
    # shortX = shortExit | long
    signal = pd.DataFrame(
        columns=["Long", "LongX", "Short", "ShortX"], index=data.index
    )
    signal["Long"] = long
    signal["LongX"] = longX & ~longX.shift().fillna(False)
    signal["Short"] = short
    signal["ShortX"] = shortX & ~shortX.shift().fillna(False)
    signal["longTarget"] = longTarget
    signal["shortTarget"] = shortTarget
    signal["maMID"] = ma_mid
    signal["RSI"] = rsi
    signal["EOD"] = pd.DatetimeIndex(signal.index).time == datetime.time(12, 50)
    if shift:
        return signal.shift()
    else:
        return signal

def linreg_signal(data, lookback, shift=False):
    data = data.copy()
    if "date" in data.columns:
        data.set_index("date", inplace=True)
    lo = data.low.copy()
    hi = data.high.copy()
    linreg_lo = pt.linreg(lo, lookback, tsf=True)
    linreg_hi = pt.linreg(hi, lookback, tsf=True)
    trendlines = pd.DataFrame(
        index=data.index, columns=["Hi", "Lo", "Hi_Breakage", "Lo_Breakage"]
    )
    trendlines["Hi"] = linreg_hi
    trendlines["Lo"] = linreg_lo
    trendlines["Hi_Breakage"] = hi.gt(linreg_hi) & hi.shift().lt(linreg_hi.shift())
    trendlines["Lo_Breakage"] = lo.lt(linreg_lo) & lo.shift().gt(linreg_lo.shift())
    if shift:
        return trendlines.shift()
    else:
        return trendlines

def ma_double_cloud_signal(
    data,
    ma_length1=18,
    ma_length2=47,
    ma_length3=70,
    target_pct=0.665,
    price_for_ma="open",
    shift=False,
    long_only=True,
    short_only=False,
    assume_downtrend_follows_uptrend=False,
    with_longX=False,
    with_shortX=False,
    daytrade=True,
):
    data = data.copy()

    if "date" in data.columns:
        data.set_index("date", inplace=True)
    data["day"] = pd.DatetimeIndex(data.index).date
    data["isFirstBar"] = data["day"].diff() >= "1 days"
    price = data[price_for_ma]
    volume = data.volume
    high = data.high
    low = data.low
    ma1 = vwap(price, volume, ma_length1)
    ma2 = vwap(price, volume, ma_length2)
    ma3 = vwap(price, volume, ma_length3)
    ma4 = pt.sma(price, ma_length3)

    ma_mid = (ma1 + ma2) / 2
    ma_bandwidth = ma1 - ma2
    longTarget = (target_pct / 100 + 1) * ma_mid
    shortTarget = ma_mid / (target_pct / 100 + 1)
    if with_longX:
        longExit = high > longTarget
    else:
        longExit = pd.Series([False] * len(data), index=data.index)

    if with_shortX:
        shortExit = low < shortTarget
    else:
        shortExit = pd.Series([False] * len(data), index=data.index)
    trend_up = ma1.gt(ma2)
    trend_dn = ma1.lt(ma2)
    rsi = pt.rsi(data.ta.hlc3(), 10)
    strong_trend = rsi.gt(20) & rsi.lt(80)

    momentum_condition1 = (rsi.gt(rsi.shift())).fillna(False)
    momentum_condition = momentum_condition1
    newday_trendup_continuation = (
        data["isFirstBar"].fillna(False)
        & strong_trend
        & (
            trend_up.fillna(False)
            & trend_up.shift().fillna(False)
            & ~longExit
            & ma3.gt(ma4)
        )
        & ma_bandwidth.pct_change().gt(0)
        & momentum_condition
    )
    newday_trenddn_continuation = (
        data["isFirstBar"].fillna(False)
        & strong_trend
        & (
            trend_dn.fillna(False)
            & trend_dn.shift().fillna(False)
            & ~shortExit
            & ma3.lt(ma4)
        )
        & ma_bandwidth.pct_change().gt(0)
        & ~momentum_condition
    )

    longCondition = (
        (trend_up & ~trend_up.shift().fillna(False)) & momentum_condition & ma3.gt(ma4)
    ) | newday_trendup_continuation

    shortCondition = (
        (trend_dn & ~trend_dn.shift().fillna(False)) & ~momentum_condition & ma3.lt(ma4)
    ) | newday_trenddn_continuation

    if daytrade:
        in_session = pd.Series(
            np.logical_and(
                pd.DatetimeIndex(data.index).time < datetime.time(12, 25),
                pd.DatetimeIndex(data.index).time >= datetime.time(6, 30),
            ),
            index=data.index,
        )
    else:
        in_session = (
            pd.Series(
                [True] * len(data),
                index=data.index,
            ),
        )

    long = in_session & longCondition & (not short_only)

    if assume_downtrend_follows_uptrend:
        short = in_session & (longExit & (not long_only))
    else:
        short = in_session & shortCondition & (not long_only)

    longX = longExit
    shortX = shortExit

    signal = pd.DataFrame(
        columns=["Long", "LongX", "Short", "ShortX"], index=data.index
    )
    signal["Long"] = long
    signal["LongX"] = longX & ~longX.shift().fillna(False)
    signal["Short"] = short
    signal["ShortX"] = shortX & ~shortX.shift().fillna(False)
    signal["longTarget"] = longTarget
    signal["shortTarget"] = shortTarget
    signal["maMID"] = ma_mid
    signal["RSI"] = rsi
    signal["EOD"] = (pd.DatetimeIndex(signal.index).time >= datetime.time(12, 25)) & (
        pd.DatetimeIndex(signal.index).time <= datetime.time(12, 55)
    )
    if shift:
        return signal.shift()
    else:
        return signal

def price_position_by_pivots(
    data,
    secondary_tf="D",
    pivot_data_shift=1,
    return_nearest_levels=False,
    return_all_levels=False,
):
    data = data.copy().reset_index()
    data.columns = data.columns.str.lower()
    if "date" in data.columns:
        data = data.set_index("date")
    pivot_data = data.shift(pivot_data_shift)

    high = (
        pivot_data.high.groupby(pivot_data.index.to_period(secondary_tf))
        .max()
        .shift(pivot_data_shift)
    )
    high.index = (
        pd.Series(pivot_data.index)
        .groupby(pivot_data.index.to_period(secondary_tf))
        .last()
    )
    high = pivot_data.align(high, axis=0)[1].bfill()

    low = (
        pivot_data.low.groupby(pivot_data.index.to_period(secondary_tf))
        .min()
        .shift(pivot_data_shift)
    )
    low.index = (
        pd.Series(pivot_data.index)
        .groupby(pivot_data.index.to_period(secondary_tf))
        .last()
    )
    low = pivot_data.align(low, axis=0)[1].bfill()
    close = (
        pivot_data.close.groupby(pivot_data.index.to_period(secondary_tf))
        .last()
        .shift(1)
    )
    close.index = (
        pd.Series(pivot_data.index)
        .groupby(pivot_data.index.to_period(secondary_tf))
        .last()
    )
    close = pivot_data.align(close, axis=0)[1].bfill()

    hlc3 = (high + low + close) / 3
    xLow = low
    xHigh = high
    vPP = hlc3
    vR1 = vPP + (vPP - xLow)
    vS1 = vPP - (xHigh - vPP)
    vR2 = vPP + (xHigh - xLow)
    vS2 = vPP - (xHigh - xLow)
    vR3 = vR1 + (xHigh - xLow)
    vS3 = vS1 - (xHigh - xLow)
    vR4 = vR1 + 2 * (xHigh - xLow)
    vS4 = vS1 - 2 * (xHigh - xLow)
    vR5 = vR1 + 3 * (xHigh - xLow)
    vS5 = vS1 - 3 * (xHigh - xLow)

    p5 = data.close.between(vR5, np.inf)
    p4 = data.close.between(vR4, vR5)
    p3 = data.close.between(vR3, vR4)
    p2 = data.close.between(vR2, vR3)
    p1 = data.close.between(vR1, vR2)
    p0 = data.close.between(vPP, vR1)
    p_1 = data.close.between(vS1, vPP)
    p_2 = data.close.between(vS2, vS1)
    p_3 = data.close.between(vS3, vS2)
    p_4 = data.close.between(vS4, vS3)
    p_5 = data.close.between(vS5, vS4)
    p_6 = data.close.between(-np.inf, vS5)

    price_position = pd.concat(
        [p_6, p_5, p_4, p_3, p_2, p_1, p0, p1, p2, p3, p4, p5], axis=1
    ).apply(np.argmax, axis=1)
    levels = pd.concat(
        [
            pd.Series([0] * len(price_position), index=data.index),
            vS5,
            vS4,
            vS3,
            vS2,
            vS1,
            vPP,
            vR1,
            vR2,
            vR3,
            vR4,
            vR5,
            pd.Series([np.inf] * len(price_position), index=data.index),
        ],
        axis=1,
    )
    nearest_levels = pd.concat(
        [
            pd.Series(
                [row[1][p] for row, p in zip(levels.iterrows(), price_position)],
                index=data.index,
            ),
            pd.Series(
                [row[1][p + 1] for row, p in zip(levels.iterrows(), price_position)],
                index=data.index,
            ),
        ],
        axis=1,
    )
    nearest_levels.columns = ["S", "R"]
    nearest_levels["MID"] = (nearest_levels["S"] + nearest_levels["R"]) / 2
    nearest_levels["38.2"] = (
        nearest_levels["S"] + (nearest_levels["R"] - nearest_levels["S"]) * 0.382
    )
    nearest_levels["61.8"] = (
        nearest_levels["S"] + (nearest_levels["R"] - nearest_levels["S"]) * 0.618
    )

    if return_nearest_levels:
        return price_position, nearest_levels
    elif return_all_levels:
        return price_position, levels
    else:
        return price_position

def dailySpreadProbabilityBrackets(data):
    price_position, levels = price_position_by_pivots(
        data, "W", return_all_levels=True, pivot_data_shift=1
    )
    p5 = data.close.between(levels[11], levels[12])
    p4 = data.close.between(levels[10], levels[11])
    p3 = data.close.between(levels[9], levels[10])
    p2 = data.close.between(levels[8], levels[9])
    p1 = data.close.between(levels[7], levels[8])
    p0 = data.close.between(levels[6], levels[7])
    p_1 = data.close.between(levels[5], levels[6])
    p_2 = data.close.between(levels[4], levels[5])
    p_3 = data.close.between(levels[3], levels[4])
    p_4 = data.close.between(levels[2], levels[3])
    p_5 = data.close.between(levels[1], levels[2])
    p_6 = data.close.between(levels[0], levels[1])

    close_pp = pd.concat(
        [p_6, p_5, p_4, p_3, p_2, p_1, p0, p1, p2, p3, p4, p5], axis=1
    ).apply(np.argmax, axis=1)

    p5 = data.open.between(levels[11], levels[12])
    p4 = data.open.between(levels[10], levels[11])
    p3 = data.open.between(levels[9], levels[10])
    p2 = data.open.between(levels[8], levels[9])
    p1 = data.open.between(levels[7], levels[8])
    p0 = data.open.between(levels[6], levels[7])
    p_1 = data.open.between(levels[5], levels[6])
    p_2 = data.open.between(levels[4], levels[5])
    p_3 = data.open.between(levels[3], levels[4])
    p_4 = data.open.between(levels[2], levels[3])
    p_5 = data.open.between(levels[1], levels[2])
    p_6 = data.open.between(levels[0], levels[1])

    open_pp = pd.concat(
        [p_6, p_5, p_4, p_3, p_2, p_1, p0, p1, p2, p3, p4, p5], axis=1
    ).apply(np.argmax, axis=1)

    mapping = {"0":"S6", "1":"S5","2":"S4","3":"S3","4":"S2","5":"S1","6":"P","7":"R1","8":"R2","9":"R3","10":"R4","11":"R5"}
    df = pd.DataFrame({"from": open_pp, "to": close_pp})

    df2 = df.groupby("from")["to"].value_counts(normalize=True)  # .loc[7]
    out = df2.reset_index().astype({"from": str, "to": str}).replace(mapping)
    return out

def calc_vwap(df, tf):
    df = df.copy()
    df.columns = df.columns.str.lower()
    if re.split(r"\d", tf)[-1] in ["H", "min"] or re.split(r"\D", tf)[0] != "":
        first_time = df.index.unique().time[0].strftime("%H:%M:%S")
        group = (df.index - pd.Timedelta(first_time)).floor(tf) + pd.Timedelta(
            first_time
        )
        return (df.ta.hlc3() * df.volume).groupby(group).cumsum() / df.volume.groupby(
            group
        ).cumsum()
    else:
        return df.ta.vwap(anchor=tf)

def crossabove(data, line, tf, consider_wicks=False, rolling_tf=False):
    data = data.copy()
    data.columns = data.columns.str.lower()
    if "date" in data.columns:
        data.set_index("date", inplace=True)

    if consider_wicks:
        crossabove = (data.close.gt(line) & data.open.lt(line)) | (
            data.open.gt(line) & data.close.gt(line) & data.low.lt(line)
        )
    else:
        crossabove = data.close.gt(line) & data.open.lt(line)
    if rolling_tf:
        crossabove = crossabove.rolling(tf).sum()
    else:
        group = data.index.floor(tf)
        crossabove = crossabove.groupby(group).cumsum()
    return crossabove

def crossbelow(data, line, tf, consider_wicks=False, rolling_tf=False):
    data = data.copy()
    data.columns = data.columns.str.lower()
    if "date" in data.columns:
        data.set_index("date", inplace=True)
    if consider_wicks:
        crossbelow = (data.close.lt(line) & data.open.gt(line)) | (
            data.open.lt(line) & data.close.lt(line) & data.high.gt(line)
        )
    else:
        crossbelow = data.close.lt(line) & data.open.gt(line)
    if rolling_tf:
        crossbelow = crossbelow.rolling(tf).sum()
    else:
        group = data.index.floor(tf)
        crossbelow = crossbelow.groupby(group).cumsum()
    return crossbelow

def MTFVWAP(
    data,
    HTF1="D",
    HTF2="W",
    HTF3="M",
    use_three_TF=False,
    use_rsi=False,
    use_avwap_cross=True,
    pivot_shift=78,
    price_move_tp=None,
    long_only=False,
    short_only=False,
    shift=False,
    daytrade=True,
):
    data = data.copy()
    data.columns = data.columns.str.lower()
    if "date" in data.columns:
        data.set_index("date", inplace=True)
    data["day"] = pd.DatetimeIndex(data.index).date
    data["isFirstBar"] = data["day"].diff() >= "1 days"

    rsi = pt.rsi(data.ta.hlc3(), 10)
    rsi_up = rsi.gt(rsi.shift())
    use_rsi_cond = {True: (rsi_up, ~rsi_up), False: (True, True)}

    avwap_htf1 = calc_vwap(data, HTF1)
    avwap_htf2 = calc_vwap(data, HTF2)
    avwap_htf3 = calc_vwap(data, HTF3)

    if use_three_TF:
        avwap_htf3 = calc_vwap(data, HTF3)
        avwap_uptrend = avwap_htf1.gt(avwap_htf2) & avwap_htf2.gt(avwap_htf3)
        avwap_dntrend = avwap_htf1.lt(avwap_htf2) & avwap_htf2.lt(avwap_htf3)
    else:
        avwap_uptrend = avwap_htf1.gt(avwap_htf2)
        avwap_dntrend = avwap_htf1.lt(avwap_htf2)
    avwap_crossover = avwap_htf1.gt(avwap_htf2) & avwap_htf1.shift().lt(
        avwap_htf2.shift()
    )
    avwap_crossunder = avwap_htf1.lt(avwap_htf2) & avwap_htf1.shift().gt(
        avwap_htf2.shift()
    )

    if price_move_tp is not None:
        price_position = price_position_by_pivots(data, pivot_data_shift=pivot_shift)
        pexp = price_position.groupby(price_position.index.to_period("D")).expanding()
        price_move = pexp.apply(lambda x: x[-1]) - pexp.apply(lambda x: x[0])
        price_move = price_move.droplevel(0)

    buy_call_open = data["isFirstBar"].fillna(False) & avwap_uptrend
    buy_put_open = data["isFirstBar"].fillna(False) & avwap_dntrend

    longCondition = (
        buy_call_open | avwap_crossover if use_avwap_cross else buy_call_open
    ) & use_rsi_cond[use_rsi][0]

    shortCondition = (
        buy_put_open | avwap_crossunder if use_avwap_cross else buy_put_open
    ) & use_rsi_cond[use_rsi][1]

    if daytrade:
        in_session = pd.Series(
            np.logical_and(
                pd.DatetimeIndex(data.index).time < datetime.time(12, 25),
                pd.DatetimeIndex(data.index).time >= datetime.time(6, 30),
            ),
            index=data.index,
        )
    else:
        in_session = (
            pd.Series(
                [True] * len(data),
                index=data.index,
            ),
        )

    long = in_session & longCondition & (not short_only)
    short = in_session & shortCondition & (not long_only)

    longX = (
        price_move.eq(price_move_tp) & price_move.shift().ne(price_move_tp)
        if price_move_tp is not None
        else pd.Series([False] * len(data), index=data.index)
    )
    shortX = (
        price_move.eq(-price_move_tp) & price_move.shift().ne(-price_move_tp)
        if price_move_tp is not None
        else pd.Series([False] * len(data), index=data.index)
    )
    signal = pd.DataFrame(
        columns=["Long", "LongX", "Short", "ShortX"], index=data.index
    )
    signal["isFirstBar"] = data["isFirstBar"]
    signal["Long"] = long
    signal["LongX"] = longX
    signal["Short"] = short
    signal["ShortX"] = shortX
    signal["RSI"] = rsi
    signal["EOD"] = (pd.DatetimeIndex(signal.index).time >= datetime.time(12, 25)) & (
        pd.DatetimeIndex(signal.index).time <= datetime.time(12, 55)
    )
    if shift:
        return signal.shift()
    else:
        return signal

def intraday_dynamic_level_breaks(data, return_levels=False):
    data = data.copy()
    data.columns = data.columns.str.lower()
    if "date" in data.columns:
        data.set_index("date", inplace=True)
    dynamic_support = data.low.groupby(data.index.to_period("D")).cummin()
    dynamic_resistance = data.high.groupby(data.index.to_period("D")).cummax()
    support_nbreaks = (
        dynamic_support.ne(dynamic_support.shift())
        .groupby(dynamic_support.index.to_period("D"))
        .cumsum()
        - 1
    )
    resistance_nbreaks = (
        dynamic_resistance.ne(dynamic_resistance.shift())
        .groupby(dynamic_resistance.index.to_period("D"))
        .cumsum()
        - 1
    )
    if return_levels:
        return dynamic_support, dynamic_resistance
    else:
        return support_nbreaks, resistance_nbreaks

def vwapbounce_signal(
    data,
    HTF1="D",
    HTF2="W",
    crossing_count_reset="1H",
    ntouch=2,
    entry_zone="('6:30', '7:30')",
    sod_time="6:30",
    eod_time="12:50",
    daytrade=True,
    use_rsi=False,
    pivot_shift=78,
    price_move_tp=None,
    long_only=True,
    short_only=False,
    shift=True,
    restrict_entry_zone=False,
    filter_by_secondary_timeframe=False,
    consider_wicks=False,
    rolling_tf=False,
):
    data = data.copy()
    data.columns = data.columns.str.lower()
    if "date" in data.columns:
        data.set_index("date", inplace=True)
    data["day"] = pd.DatetimeIndex(data.index).date
    data["isFirstBar"] = data["day"].diff() >= "1 days"

    rsi = pt.rsi(data.ta.hlc3(), 10)
    rsi_up = rsi.gt(rsi.shift())
    use_rsi_cond = {True: (rsi_up, ~rsi_up), False: (True, True)}

    avwap_htf1 = calc_vwap(data, HTF1)
    vwap_crossabove_htf1 = crossabove(
        data,
        avwap_htf1,
        crossing_count_reset,
        consider_wicks=consider_wicks,
        rolling_tf=rolling_tf,
    )

    avwap_htf2 = calc_vwap(data, HTF2)

    if price_move_tp is not None:
        price_position = price_position_by_pivots(data, pivot_data_shift=pivot_shift)
        pexp = price_position.groupby(price_position.index.to_period(HTF1)).expanding()
        price_move = pexp.apply(lambda x: x[-1]) - pexp.apply(lambda x: x[0])
        price_move = price_move.droplevel(0)

    entry_hr_left = int(eval(entry_zone)[0].split(":")[0])
    entry_min_left = int(eval(entry_zone)[0].split(":")[1])
    entry_hr_right = int(eval(entry_zone)[1].split(":")[0])
    entry_min_right = int(eval(entry_zone)[1].split(":")[1])

    longCondition = (
        vwap_crossabove_htf1.eq(ntouch) & vwap_crossabove_htf1.shift().ne(ntouch)
    ) & use_rsi_cond[use_rsi][0]
    if filter_by_secondary_timeframe:
        longCondition = longCondition & avwap_htf1.gt(avwap_htf2)

    if restrict_entry_zone:
        longCondition = longCondition & pd.Series(
            np.logical_and(
                pd.DatetimeIndex(data.index).time
                < datetime.time(entry_hr_right, entry_min_right),
                pd.DatetimeIndex(data.index).time
                >= datetime.time(entry_hr_left, entry_min_left),
            ),
            index=data.index,
        )

    shortCondition = (
        avwap_htf1.lt(avwap_htf2)
        & avwap_htf1.shift().ge(avwap_htf2.shift())
        & use_rsi_cond[use_rsi][1]
    )
    if filter_by_secondary_timeframe:
        shortCondition = shortCondition & avwap_htf1.lt(avwap_htf2)
    if restrict_entry_zone:
        shortCondition = shortCondition & pd.Series(
            np.logical_and(
                pd.DatetimeIndex(data.index).time
                < datetime.time(entry_hr_right, entry_min_right),
                pd.DatetimeIndex(data.index).time
                >= datetime.time(entry_hr_left, entry_min_left),
            ),
            index=data.index,
        )

    if daytrade:
        in_session = pd.Series(
            np.logical_and(
                pd.DatetimeIndex(data.index).time
                < datetime.time(
                    int(eod_time.split(":")[0]), int(eod_time.split(":")[1])
                ),
                pd.DatetimeIndex(data.index).time
                >= datetime.time(
                    int(sod_time.split(":")[0]), int(sod_time.split(":")[1])
                ),
            ),
            index=data.index,
        )
    else:
        in_session = (
            pd.Series(
                [True] * len(data),
                index=data.index,
            ),
        )

    long = in_session & longCondition & (not short_only)
    short = in_session & shortCondition & (not long_only)

    longX = (
        price_move.eq(price_move_tp) & price_move.shift().ne(price_move_tp)
        if price_move_tp is not None
        else pd.Series([False] * len(data), index=data.index)
    )
    shortX = (
        price_move.eq(-price_move_tp) & price_move.shift().ne(-price_move_tp)
        if price_move_tp is not None
        else pd.Series([False] * len(data), index=data.index)
    )
    signal = pd.DataFrame(
        columns=["Long", "LongX", "Short", "ShortX"], index=data.index
    )
    signal["isFirstBar"] = data["isFirstBar"]
    signal["Long"] = long
    signal["LongX"] = longX
    signal["Short"] = short
    signal["ShortX"] = shortX
    signal["RSI"] = rsi
    signal["EOD"] = (
        pd.DatetimeIndex(signal.index).time
        >= datetime.time(int(eod_time.split(":")[0]), int(eod_time.split(":")[1]))
    ) & (pd.DatetimeIndex(signal.index).time <= datetime.time(13, 0))
    if shift:
        return signal.shift()
    else:
        return signal

def EhlersRoofing(close, fast_length, slow_length):
    return EhlersSuperSmoother(EhlersHighpass(close, slow_length), fast_length)

def fit_trendline(data, trend_type="low"):
    data = data.copy()
    data["dateint"] = data.index.astype("int64") - data.index.astype("int64").min()
    trendline_data = data.copy()
    # recursively fit until only 3 points or fewer are above the trendline
    while len(trendline_data) > 3:
        fit = linregress(x=trendline_data["dateint"], y=trendline_data[trend_type])
        if trend_type == "high":
            trendline_data = trendline_data.loc[
                trendline_data[trend_type].gt(
                    fit[0] * trendline_data["dateint"] + fit[1]
                )
            ]
        else:
            trendline_data = trendline_data.loc[
                trendline_data[trend_type].lt(
                    fit[0] * trendline_data["dateint"] + fit[1]
                )
            ]

    fit = linregress(
        x=trendline_data["dateint"],
        y=trendline_data[trend_type],
    )
    return fit[0] * data["dateint"] + fit[1]

def buyingpressure(
    data,
    length=15,
    normalization_period=200,
    buyingpressure_definition="3",
    how_to_treat_inside_bar=np.nan,
    with_volume=1,
):
    data = data.copy()
    data.columns = data.columns.str.lower()
    close = data.close
    open = data.open
    low = data.low
    high = data.high
    volume = data.volume
    inside = (high.le(high.shift()) & low.ge(low.shift())).fillna(False)
    # inside = (high.le(high.shift()) & low.ge(low.shift())) | (high.le(high.shift(2)) & low.ge(low.shift(2))).fillna(False)
    first_bar = data.index.strftime("%H:%M") == "06:30"
    atr = data.ta.atr(5)
    intraday_move = close - open  # / ATR
    intraday_move[
        intraday_move.abs().gt(2 * atr)
    ] = np.nan  # filter out knee jerk reactions due to news
    intraday_move.ffill(inplace=True)
    interday_move = close - close.shift()
    interday_move[first_bar] = 0
    interday_move[
        interday_move.abs().gt(2 * atr)
    ] = np.nan  # filter out knee jerk reactions due to news
    interday_move.ffill(inplace=True)
    hWick = high - np.max([close, open], axis=0)
    hWick[intraday_move.abs().gt(2 * atr)] = np.nan
    hWick.ffill(inplace=True)
    lWick = np.min([close, open], axis=0) - low
    lWick[intraday_move.abs().gt(2 * atr)] = np.nan
    lWick.ffill(inplace=True)
    candle_body = np.abs(intraday_move)
    oc = pd.concat([close, open], axis=1)
    min_oc = oc.min(axis=1)
    max_oc = oc.max(axis=1)
    touch_low = pd.Series(0, index=close.index)
    touch_low[min_oc - low <= 0.05 * candle_body] = 1
    touch_low *= np.sign(intraday_move)
    touch_high = pd.Series(0, index=close.index)
    touch_high[high - max_oc <= 0.05 * candle_body] = 1
    touch_high *= np.sign(intraday_move)

    pressure1 = (
        intraday_move
        + (lWick - hWick)
        + interday_move
        + candle_body * (touch_high + touch_low)
    ) * [1, volume][with_volume]
    pressure1[inside] = how_to_treat_inside_bar
    pressure1.ffill(inplace=True)

    pressure2 = ((close - low) / (high - low) - (high - close) / (high - low)) * [
        1,
        volume,
    ][with_volume]
    pressure2[inside] = how_to_treat_inside_bar
    pressure2.ffill(inplace=True)

    pressure3 = (intraday_move + (lWick - hWick) + interday_move) * [1, volume][
        with_volume
    ]
    pressure3[inside] = how_to_treat_inside_bar
    pressure3.ffill(inplace=True)

    if buyingpressure_definition.lower() == "1":
        pressure = pressure1
    elif buyingpressure_definition.lower() == "2":
        pressure = pressure2
    elif buyingpressure_definition.lower() == "3":
        pressure = pressure3
    elif buyingpressure_definition.lower() == "combined":
        pressure = (pressure1 + pressure2 + pressure3) / 3
    elif buyingpressure_definition.lower() == "combined2":
        pressure = (
            pressure1 / pressure1.rolling(normalization_period).std()
            + pressure2 / pressure2.rolling(normalization_period).std()
            + pressure3 / pressure3.rolling(normalization_period).std()
        ) / 3

    # pressure = pressure.fillna(0)

    pressure = pressure.ffill()

    def rolling_rms(x):
        r = 1.0
        a = np.sqrt((len(x) * r**2) / (x**2).sum())
        x = x * a
        return x[-1]

    pressure = pressure.rolling(normalization_period).apply(rolling_rms)

    # pressure = pressure / pressure.rolling(normalization_period).std()
    if length > 1:
        pressure = EhlersSuperSmoother(pressure.fillna(0), length=length)

    return pressure

def rma(close, length):
    alpha = 1 / length
    filt = close.copy()
    n = filt.size
    for i in range(0, n):
        filt.iloc[i] = alpha * close.iloc[i] + (1 - alpha) * filt.iloc[i - 1]
    return filt

def bandpass_filter(close, low_cutoff=None, high_cutoff=None, **kwargs):
    """Bandpass filter signal

    Args:
        close (pd.Series): pandas Series
        low_cutoff (float, optional): low frequency cutoff. Defaults to 0.01. Should be 0.5 > low_cutoff > 0
        high_cutoff (float, optional): high frequency cutoff. Defaults to 0.1. Should be 0.5 > high_cutoff

    Returns:
        pd.Series: Bandpass-filtered Series
    """
    # Configuration.
    fL = (
        low_cutoff if low_cutoff else 0.01
    )  # Cutoff frequency as a fraction of the sampling rate.
    fH = (
        high_cutoff if high_cutoff else 0.1
    )  # Cutoff frequency as a fraction of the sampling rate.
    NL = kwargs.get(
        "low_cutoff_rolloff_length", 29
    )  # Filter length for roll-off at fL, must be odd.
    NH = kwargs.get(
        "high_cutoff_rolloff_length", 25
    )  # Filter length for roll-off at fH, must be odd.
    beta = kwargs.get("beta", 3.395)  # Kaiser window beta.

    # Compute a low-pass filter with cutoff frequency fH.
    hlpf = np.sinc(2 * fH * (np.arange(NH) - (NH - 1) / 2))
    hlpf *= np.kaiser(NH, beta)
    hlpf /= np.sum(hlpf)

    # Compute a high-pass filter with cutoff frequency fL.
    hhpf = np.sinc(2 * fL * (np.arange(NL) - (NL - 1) / 2))
    hhpf *= np.kaiser(NL, beta)
    hhpf /= np.sum(hhpf)
    hhpf = -hhpf
    hhpf[(NL - 1) // 2] += 1

    # Convolve both filters.
    h = np.convolve(hlpf, hhpf)

    # Applying the filter to a signal s can be as simple as writing
    s = np.convolve(close, h)

    return pd.Series(s[NL + NH - 2 :], index=close.index)

def get_ohlc4(open, high, low, close):
    return 1 / 4 * (open + high + low + close)

def get_atr(high, low, close, period, MAtype="Ehlers", convert_series=False):
    if type(high) == pd.Series:
        idx = high.index
    else:
        idx = pd.RangeIndex(1, len(high) + 1)
    high = np.array(high)
    low = np.array(low)
    close = np.array(close)
    shifted_close = vbt.nb.fshift_1d_nb(close)
    tr0 = np.abs(high - low)
    tr1 = np.abs(high - shifted_close)
    tr2 = np.abs(low - shifted_close)
    tr = np.column_stack((tr0, tr1, tr2)).max(axis=1)
    if MAtype == "ema":
        atr = vbt.nb.ewm_mean_1d_nb(tr, period)
    elif MAtype == "sma":
        atr = pt.sma(pd.Series(tr), period).values
    elif MAtype == "wma":
        atr = pt.wma(pd.Series(tr), period).values
    elif MAtype == "Ehlers":
        atr = EhlersSuperSmoother(vbt.nb.fillna_1d_nb(tr, 0), period)
    elif MAtype == "rma":
        atr = rma(pd.Series(tr).fillna(0), period).values
    atr = vbt.nb.ffill_1d_nb(atr)
    if convert_series:
        atr = pd.Series(atr, index=idx)
        atr.name = "ATR"
    return atr

class TALib:
    def __init__(self, **kwargs) -> None:
        self.data = kwargs.get("data", None)

    def didiIndex(
        self,
        data=None,
        ma_fast_length=10,
        ma_mid_length=20,
        ma_slow_length=30,
        ssf_length=15,
    ):
        if data is None:
            data = self.data.copy()
        else:
            data = data.copy()
        hlc3 = data.ta.hlc3().ffill()
        ma_fast = EhlersSuperSmoother(hlc3, ma_fast_length)
        ma_mid = EhlersSuperSmoother(hlc3, ma_mid_length)
        ma_slow = EhlersSuperSmoother(hlc3, ma_slow_length)

        fast = (ma_fast / ma_mid - 1) * 100
        slow = (ma_slow / ma_mid - 1) * 100
        didi = EhlersSuperSmoother((fast - slow).fillna(0), ssf_length)
        return didi

    def VFI(self, data=None, length=130, maxVolumeCutOff=2.5):
        if data is None:
            data = self.data.copy()
        else:
            data = data.copy()
        hlc3 = data.ta.hlc3().ffill()
        cutOff = (
            0.2 * (np.log(hlc3) - np.log(hlc3.shift(1))).rolling(30).std() * data.close
        )
        hlcChange = hlc3 - hlc3.shift(1)
        avgVolume = data.volume.rolling(length).mean().shift(1)
        minVolume = pd.concat([data.volume, avgVolume * maxVolumeCutOff], axis=1).apply(
            np.min, axis=1
        )
        dirVolume = pd.Series(0, index=hlcChange.index)
        dirVolume[hlcChange.gt(cutOff)] = minVolume[hlcChange.gt(cutOff)]
        dirVolume[hlcChange.lt(-cutOff)] = -minVolume[hlcChange.lt(-cutOff)]

        VFI = EhlersSuperSmoother(
            (dirVolume.rolling(length).sum() / avgVolume).fillna(0), 50
        )
        return VFI

    def buyingpressure(
        self,
        data=None,
        length=15,
        normalization_period=200,
        buyingpressure_definition="3",
        how_to_treat_inside_bar=np.nan,
        with_volume=1,
    ):
        if data is None:
            data = self.data.copy()
        else:
            data = data.copy()
        close = data.close
        open = data.open
        low = data.low
        high = data.high
        volume = data.volume
        inside = (high.le(high.shift()) & low.ge(low.shift())).fillna(False)
        # inside = (high.le(high.shift()) & low.ge(low.shift())) | (high.le(high.shift(2)) & low.ge(low.shift(2))).fillna(False)
        first_bar = data.index.strftime("%H:%M") == "06:30"
        atr = data.ta.atr(5)
        intraday_move = close - open  # / ATR
        intraday_move[
            intraday_move.abs().gt(2 * atr)
        ] = np.nan  # filter out knee jerk reactions due to news
        intraday_move.ffill(inplace=True)
        interday_move = close - close.shift()
        interday_move[first_bar] = 0
        interday_move[
            interday_move.abs().gt(2 * atr)
        ] = np.nan  # filter out knee jerk reactions due to news
        interday_move.ffill(inplace=True)
        hWick = high - np.max([close, open], axis=0)
        hWick[intraday_move.abs().gt(2 * atr)] = np.nan
        hWick.ffill(inplace=True)
        lWick = np.min([close, open], axis=0) - low
        lWick[intraday_move.abs().gt(2 * atr)] = np.nan
        lWick.ffill(inplace=True)
        candle_body = np.abs(intraday_move)
        oc = pd.concat([close, open], axis=1)
        min_oc = oc.min(axis=1)
        max_oc = oc.max(axis=1)
        touch_low = pd.Series(0, index=close.index)
        touch_low[min_oc - low <= 0.05 * candle_body] = 1
        touch_low *= np.sign(intraday_move)
        touch_high = pd.Series(0, index=close.index)
        touch_high[high - max_oc <= 0.05 * candle_body] = 1
        touch_high *= np.sign(intraday_move)

        pressure1 = (
            intraday_move
            + (lWick - hWick)
            + interday_move
            + candle_body * (touch_high + touch_low)
        ) * [1, volume][with_volume]
        pressure1[inside] = how_to_treat_inside_bar
        pressure1.ffill(inplace=True)

        pressure2 = ((close - low) / (high - low) - (high - close) / (high - low)) * [
            1,
            volume,
        ][with_volume]
        pressure2[inside] = how_to_treat_inside_bar
        pressure2.ffill(inplace=True)

        pressure3 = (intraday_move + (lWick - hWick) + interday_move) * [1, volume][
            with_volume
        ]
        pressure3[inside] = how_to_treat_inside_bar
        pressure3.ffill(inplace=True)

        if buyingpressure_definition.lower() == "1":
            pressure = pressure1
        elif buyingpressure_definition.lower() == "2":
            pressure = pressure2
        elif buyingpressure_definition.lower() == "3":
            pressure = pressure3
        elif buyingpressure_definition.lower() == "combined":
            pressure = (pressure1 + pressure2 + pressure3) / 3
        elif buyingpressure_definition.lower() == "combined2":
            pressure = (
                pressure1 / pressure1.rolling(normalization_period).std()
                + pressure2 / pressure2.rolling(normalization_period).std()
                + pressure3 / pressure3.rolling(normalization_period).std()
            ) / 3

        # pressure = pressure.fillna(0)

        pressure = pressure.ffill()

        def rolling_rms(x):
            r = 1.0
            a = np.sqrt((len(x) * r**2) / (x**2).sum())
            x = x * a
            return x[-1]

        pressure = pressure.rolling(normalization_period).apply(rolling_rms)

        # pressure = pressure / pressure.rolling(normalization_period).std()
        if length > 1:
            pressure = EhlersSuperSmoother(pressure.fillna(0), length=length)

        return pressure

    def supply_demand(
        self,
        data=None,
        resample=None,
        return_sorted_levels=False,
        significant_threshold=1.8,
        prefer_recent_zones=False,
        **bp_kwargs,
    ):
        if data is None:
            data = self.data.copy()
        else:
            data = data.copy()
        original_data = data.copy()
        levels = pd.DataFrame(columns=["Demand", "Supply"], index=original_data.index)
        data = data.copy()
        if resample is not None:
            logic = {
                "close": "last",
                "open": "first",
                "volume": "sum",
                "low": "min",
                "high": "max",
            }
            data = data.resample(resample).apply(logic).dropna()

        def rolling_rms(x):
            r = 1.0
            a = np.sqrt((len(x) * r**2) / (x**2).sum())
            x = x * a
            return x[-1]

        volume = original_data.volume.rolling(
            bp_kwargs.get("normalization_period", 200)
        ).apply(rolling_rms)

        bp = self.buyingpressure(data, **bp_kwargs)
        original_bp = self.buyingpressure(original_data, **bp_kwargs)

        demands = data.shift(2).low[
            bp.shift(2).gt(significant_threshold)
            & data.shift(1).high.gt(data.shift(2).high)
        ]

        demands_old1 = demands.shift(1)
        demands_old2 = demands.shift(2)
        demands_old3 = demands.shift(3)

        demands = demands.align(original_data.close)[0].ffill()
        demands_old1 = demands_old1.align(original_data.close)[0].ffill()
        demands_old2 = demands_old2.align(original_data.close)[0].ffill()
        demands_old3 = demands_old3.align(original_data.close)[0].ffill()

        sorted_demands = pd.concat(
            [demands, demands_old1, demands_old2, demands_old3], axis=1
        )
        sorted_demands.columns = ["D1", "D2", "D3", "D4"]

        sorted_demands = sorted_demands.align(original_data)[0].ffill()[
            ["D1", "D2", "D3", "D4"]
        ]

        cl = pd.concat([original_data.close.shift()] * 4, axis=1)
        cl.columns = ["D1", "D2", "D3", "D4"]

        def first_nonNan(x):
            try:
                return x.dropna()[0]
            except:
                return np.nan

        if prefer_recent_zones:
            levels["Demand"] = sorted_demands[sorted_demands.lt(cl)].apply(
                first_nonNan, axis=1
            )
            levels["DemandTurnedSupply"] = sorted_demands[sorted_demands.gt(cl)].apply(
                first_nonNan, axis=1
            )
        else:
            levels["Demand"] = sorted_demands[sorted_demands.lt(cl)].max(axis=1)
            levels["DemandTurnedSupply"] = sorted_demands[sorted_demands.gt(cl)].min(
                axis=1
            )

        supplies = data.shift(2).high[
            bp.shift(2).lt(-significant_threshold)
            & data.shift(1).low.lt(data.shift(2).low)
        ]

        supplies_old1 = supplies.shift(1)
        supplies_old2 = supplies.shift(2)
        supplies_old3 = supplies.shift(3)

        supplies = supplies.align(original_data.close)[0].ffill()
        supplies_old1 = supplies_old1.align(original_data.close)[0].ffill()
        supplies_old2 = supplies_old2.align(original_data.close)[0].ffill()
        supplies_old3 = supplies_old3.align(original_data.close)[0].ffill()
        sorted_supplies = pd.concat(
            [supplies, supplies_old1, supplies_old2, supplies_old3], axis=1
        )
        sorted_supplies.columns = ["S1", "S2", "S3", "S4"]

        sorted_supplies = sorted_supplies.align(original_data)[0].ffill()[
            ["S1", "S2", "S3", "S4"]
        ]
        cl.columns = ["S1", "S2", "S3", "S4"]
        if prefer_recent_zones:
            levels["Supply"] = sorted_supplies[sorted_supplies.gt(cl)].apply(
                first_nonNan, axis=1
            )
            levels["SupplyTurnedDemand"] = sorted_supplies[
                sorted_supplies.lt(cl)
            ].apply(first_nonNan, axis=1)
        else:
            levels["Supply"] = sorted_supplies[sorted_supplies.gt(cl)].min(axis=1)
            levels["SupplyTurnedDemand"] = sorted_supplies[sorted_supplies.lt(cl)].max(
                axis=1
            )

        price_pct = (original_data.close - levels["Demand"]) / (
            levels["Supply"] - levels["Demand"]
        )

        levels["Near Demand"] = price_pct.lt(0.05)
        levels["Near Supply"] = price_pct.gt(0.95)
        levels["Touched Demand"] = (
            original_data.low.le(levels["Demand"])
            & original_data.low.shift().gt(levels["Demand"])
            & original_data.close.gt(levels["Demand"])
            & ~(
                original_data.high.ge(levels["Supply"])
                & original_data.high.shift().lt(levels["Supply"])
                & original_data.close.lt(levels["Supply"])
            )
        )
        levels["Touched Supply"] = (
            original_data.high.ge(levels["Supply"])
            & original_data.high.shift().lt(levels["Supply"])
            & original_data.close.lt(levels["Supply"])
            # & original_data.open.lt(levels["Supply"])
            & ~(
                original_data.low.le(levels["Demand"])
                & original_data.low.shift().gt(levels["Demand"])
                & original_data.close.gt(levels["Demand"])
            )
        )

        levels["Demand Touch Pressure"] = original_bp[levels["Touched Demand"]]
        levels["Demand Touch Volume"] = volume[levels["Touched Demand"]]

        levels["Touched Demand and Bounced"] = (
            levels["Touched Demand"].shift()
            & original_bp.gt(original_bp.shift())
            & original_data.close.gt(levels["Demand"].shift())
        )

        levels["Touched Demand and Failed"] = levels["Demand Touch Pressure"].lt(-0.2)

        levels["Supply Touch Pressure"] = original_bp[levels["Touched Supply"]]
        levels["Supply Touch Volume"] = volume[levels["Touched Supply"]]

        levels["Touched Supply and Bounced"] = (
            levels["Touched Supply"].shift()
            & original_bp.lt(original_bp.shift())
            & original_data.close.lt(levels["Supply"].shift())
        )

        levels["Touched Supply and Failed"] = levels["Supply Touch Pressure"].gt(0.2)

        for _, sup_df in list(levels.groupby("Supply")):
            levels.loc[sup_df.index, "Supply Touch No."] = sup_df[
                "Touched Supply"
            ].cumsum()
            levels.loc[sup_df.index, "Touched Supply and Bounced No."] = sup_df[
                "Touched Supply and Bounced"
            ].cumsum()
            levels.loc[sup_df.index, "Cumulative Supply Touch Pressure"] = sup_df[
                "Supply Touch Pressure"
            ].cumsum() / np.arange(1, len(sup_df) + 1)

        for _, dem_df in list(levels.groupby("Demand")):
            levels.loc[dem_df.index, "Demand Touch No."] = dem_df[
                "Touched Demand"
            ].cumsum()
            levels.loc[dem_df.index, "Touched Demand and Bounced No."] = dem_df[
                "Touched Demand and Bounced"
            ].cumsum()
            levels.loc[dem_df.index, "Cumulative Demand Touch Pressure"] = dem_df[
                "Demand Touch Pressure"
            ].cumsum() / np.arange(1, len(dem_df) + 1)

        levels["close"] = original_data.close
        levels["close_shift"] = original_data.close.shift()
        levels["high"] = original_data.high
        levels["high_shift"] = original_data.high.shift()

        if return_sorted_levels:
            return levels, sorted_demands, sorted_supplies
        else:
            return levels


#!/usr/bin/python3
"""
Return the perimeter of the island.
"""

def island_perimeter(grid):
    """Returns the perimeter of the island described in grid"""
    if not grid:
        return 0

    island_perimeter = 0
    # Get the number of rows, columns in the grid.
    grid_rows = len(grid)
    grid_cols = len(grid[0])

    for row in range(grid_rows):
        for col in range(grid_cols):
            # we Check if the current cell is land.
            if grid[row][col] == 1:
                # we start by adding 4 sides to the perimeter count.
                island_perimeter += 4
                # check if there's a neighboring landcell on the left.
                if col > 0 and grid[row][col - 1] == 1:
                    island_perimeter -= 2
                # check if there's a neighboring landcell on the top.
                if row > 0 and grid[row - 1][col] == 1:
                    island_perimeter -= 2

    return island_perimeter


#First Type of solution
def canJump(self,nums):
    goal = len(nums) - 1
    coverage = 0
    last_index = 0

    for i in range(len(nums)):
        coverage = max(coverage,i+nums[i])

        if i == last_index:
            last_index = coverage
            if coverage>=goal:
                return True

    return False

#Second Solution

def canJumpx(self,nums):
    destination = len(nums)-1
    curr = 0
    steps = nums[curr]

    while curr<destination  and steps>0:
        curr += 1

        steps = max(steps-1,nums[curr])

    return curr == destination


from urllib.request import urlopen
from urllib.error import URLError
from django.db import models
from django.urls import reverse
from django.contrib.postgres.functions import TransactionNow
from simple_history.models import HistoricalRecords

from common.models import HistoricalRecord
from operation_requests.settings import UNIQUE_ID_SIZE
from MDOR_editor.settings import FLASH_MEMORY_BUFFER, MEMORY_PATCH_UNIQUE_ID_SIZE
from MDOR_editor.utils import LoadMemoryTelecommand, FlashCopyTelecommand
from .memory_chip import MemoryChip
from .validation import MDORMemoryPatchValidateMixin

__all__ = ['MemoryPatch']

class MemoryPatchManager(models.Manager):
	'''Manager that optimises queries by always selecting related memory chip'''
	def get_queryset(self):
		queryset = super().get_queryset()
		queryset = queryset.select_related('memory')
		return queryset

class MemoryPatch(MDORMemoryPatchValidateMixin, models.Model):
	'''Model representing a patch to memory'''
	# Force primary key to a 64 bits integer to avoid overflow
	id = models.BigAutoField(primary_key=True)
	operation_request_file = models.ForeignKey('MDOR', on_delete=models.CASCADE, help_text='The MDOR to which the memory patch belongs', related_name='memory_patches', related_query_name='memory_patch')
	execution_time = models.DateTimeField(help_text = 'The time at which to apply the memory patch (this is only indicative as MDOR do not contain any time information)')
	unique_id = models.CharField(max_length = MEMORY_PATCH_UNIQUE_ID_SIZE, help_text='An unique identifier of the memory patch for the whole mission lifetime', null = True, blank = True)
	file_url = models.CharField(max_length = 500, help_text = 'The URL to the binary source file of the patch')
	memory = models.ForeignKey('MemoryChip', on_delete=models.PROTECT, help_text = 'The memory where to upload the patch', related_name='memory_patchs', related_query_name='memory_patch', limit_choices_to={'is_writable': True})
	memory_address = models.PositiveIntegerField(help_text = 'The start address in memory where to upload the patch')

	# Track objects history
	history = HistoricalRecords(inherit=True, bases=[HistoricalRecord])

	# Force the date of history records to be the time of transaction
	# So that related objects have the same history_date when saving
	_history_date = TransactionNow()

	# Override the manager to optimize queries
	objects = MemoryPatchManager()

	class Meta:
		verbose_name = 'Memory patch'
		ordering = ['execution_time']

	def __str__(self):
		return '%s@%s' % (self.memory, self.get_memory_address_display())

	def get_absolute_url(self):
		return reverse('MDOR_editor:memory_patch_details', kwargs={'memory_patch_pk': self.pk})

	def get_html_id(self):
		'''Return an unique ID for use in html'''
		return 'id_mdor_memory_patch_%s' % self.pk

	def get_immutable(self):
		if not hasattr(self, '_immutable'):
			self._immutable = self.operation_request_file.immutable
		return self._immutable

	def set_immutable(self, value):
		self._immutable = value

	immutable = property(get_immutable, set_immutable, doc='The object cannot be modified or deleted')

	def get_memory_address_display(self):
		'''Return the memory address in hexadecimal'''
		return '0x%08X' % self.memory_address

	@property
	def file_handle(self):
		'''Return a file handle for the file URL'''
		if not hasattr(self, '_file_handle'):
			try:
				self._file_handle = urlopen(self.file_url)
			except URLError as why:
				self._file_handle = None
				self.file_error = why

		return self._file_handle

	@property
	def file_content(self):
		'''Return the content of the file as a bytestring'''
		if not hasattr(self, '_file_content'):
			if self.file_handle is not None:
				self._file_content = self.file_handle.read()
			else:
				self._file_content = None

		return self._file_content

	@property
	def file_size(self):
		'''Return the file size'''
		if not hasattr(self, '_file_size'):
			if self.file_content is not None:
				self._file_size = len(self.file_content)
			else:
				self._file_size = None

		return self._file_size

	@property
	def file_content_type(self):
		'''Return the file content type'''
		if not hasattr(self, '_file_content_type'):
			if self.file_handle is not None:
				self._file_content_type = self.file_handle.info().get_content_type().split('/')
			else:
				self._file_content_type = None

		return self._file_content_type

	def get_mock_telecommand_calls(self):
		'''Expand the memory patch into a list of mock telecommand calls '''

		# For regular memory, load the whole patch directly to memory
		# For flash memory, the patch must be split in small chuncks (usually 4096 bytes)
		# each chunk is then loaded to a memory buffer (usually CPU_SRAM)
		# and finally copied to the flash memory
		if not self.memory.is_flash:

			# Create a proxy for the load memory telecommand
			load_memory_telecommand = LoadMemoryTelecommand(self.operation_request_file.MIB_version, self.memory)

			# Create the mock telecommand calls to load the whole file
			mock_telecommand_calls = self.get_load_memory_mock_telecommand_calls(
				telecommand = load_memory_telecommand,
				memory_chip = self.memory,
				memory_address = self.memory_address,
				file_position = 0,
				data_size = self.file_size
			)

		else:
			mock_telecommand_calls = list()

			# Get the memory buffer info
			buffer_memory = MemoryChip.objects.get(name=FLASH_MEMORY_BUFFER['name'])
			buffer_address = int(FLASH_MEMORY_BUFFER['address'], 16)

			# Create a proxy for the load memory telecommand
			load_memory_telecommand = LoadMemoryTelecommand(self.operation_request_file.MIB_version, buffer_memory)

			# Create a proxy for the flash copy telecommand
			flash_copy_telecommand = FlashCopyTelecommand(self.operation_request_file.MIB_version, buffer_memory)

			# Memory address in the flash memory where to copy the buffer
			memory_address = self.memory_address

			# Note: The file size is always a multiple of the memory write size,
			# so no need to worry about going beyond the end of the file
			for file_position in range(0, self.file_size, self.memory.write_size):
				# Load a block of data to the buffer
				mock_telecommand_calls.extend(self.get_load_memory_mock_telecommand_calls(
					telecommand = load_memory_telecommand,
					memory_chip = buffer_memory,
					memory_address = buffer_address,
					file_position = file_position,
					data_size = self.memory.write_size
				))

				# Copy the block of data to flash
				mock_telecommand_calls.append(flash_copy_telecommand.get_mock_telecommand_call(
					operation_request_file = self.operation_request_file,
					memory_chip_from = buffer_memory,
					memory_chip_to = self.memory,
					memory_address = memory_address,
					length = self.memory.write_size,
					comment = 'Copy of bytes[%s:%s[ from %s to %s at address 0x%08X' % (file_position, file_position + self.memory.write_size, buffer_memory, self.memory, memory_address)
				))

				# Update the memory address for the next block
				memory_address += self.memory.write_size // self.memory.SAU

		# On the first telecommand call, add a comment on the patch being uploaded
		mock_telecommand_calls[0].memory_patch_comment = 'Upload of %s to %s at address %s' % (self.file_url, self.memory, self.get_memory_address_display())

		# Set the unique ID on the telecommand calls
		if self.unique_id is not None:
			# The unique ID is a 20 char string that start with the memory patch unique ID followed by the mock telecommand call position
			template = self.unique_id + '%0{digits}d'.format(digits = UNIQUE_ID_SIZE - len(self.unique_id))
			for counter, mock_telecommand_call in enumerate(mock_telecommand_calls):
				mock_telecommand_call.unique_id = template % counter

		return mock_telecommand_calls

	def get_load_memory_mock_telecommand_calls(self, telecommand, memory_chip, memory_address, file_position, data_size):
		'''Create mock telecommand calls for a memory patch'''

		mock_telecommand_calls = list()

		# Create telecommand calls as long as there is data to be uploaded
		while data_size > 0:
			# Don't write more than telecommand max data size nor than data size
			write_size = min(telecommand.max_data_size, data_size)

			# Create the telecommand call
			mock_telecommand_calls.append(telecommand.get_mock_telecommand_call(
				operation_request_file = self.operation_request_file,
				memory_chip = memory_chip,
				memory_address = memory_address,
				data = self.file_content[file_position:file_position + write_size],
				comment = 'Upload of bytes[%s:%s[ at address 0x%08X' % (file_position, file_position + write_size, memory_address)
			))

			# Update the remaining data size
			data_size -= write_size

			# Update the file_position for the next telecommand call
			file_position += write_size

			# Update the memory address for the next telecommand call
			memory_address += write_size // memory_chip.SAU

		return mock_telecommand_calls