from hist_service import HistWorker

hs = HistWorker()
hs.combine_polo_frames_vol_sorted(3)

print(next(iter(hs.currentHists.values())).head())

hs.currentHists = {}
hs.combine_binance_frames_vol_sorted(3)

print(next(iter(hs.currentHists.values())).head())
class PurpleTrader:

    #needs to be initialized so as to allow for 62 outputs that return a coordinate

    # ES-HyperNEAT specific parameters.
    params = {
        "initial_depth": 3,
        "max_depth": 4,
        "variance_threshold": 0.00013,
        "band_threshold": 0.00013,
        "iteration_level": 3,
        "division_threshold": 0.00013,
        "max_weight": 5.0,
        "activation": "tanh"
    }

    # Config for CPPN.
    config = neat.config.Config(neat.genome.DefaultGenome,
                                neat.reproduction.DefaultReproduction,
                                neat.species.DefaultSpeciesSet,
                                neat.stagnation.DefaultStagnation,
                                'config_trader0')

    start_idx = 0
    highest_returns = 0
    portfolio_list = []

    in_shapes = []
    out_shapes = []

    def __init__(self, hist_depth):
        self.hs = HistWorker()
        self.hs.combine_polo_frames_vol_sorted()
        self.hd = hist_depth
        print(self.hs.currentHists.keys())
        self.end_idx = len(self.hs.currentHists["ZEC"])
        self.but_target = .1
        self.inputs = self.hs.hist_shaped.shape[0] * (
            self.hs.hist_shaped[0].shape[1])
        self.outputs = self.hs.hist_shaped.shape[0]
        sign = 1
        for ix in range(1, self.outputs + 1):
            sign = sign * -1
            self.out_shapes.append(
                (-1.0, 0.0 - (sign * .005 * ix), -1.0, -1.0))
            for ix2 in range(1, (self.inputs // self.outputs) + 1):
                self.in_shapes.append(
                    (0.0 + (sign * .01 * ix2), 0.0 - (sign * .01 * ix2),
                     0.0 + (sign * (self.hd / self.hd + ix + ix2)), 0.0))
        self.subStrate = Substrate(self.in_shapes, self.out_shapes)
        self.epoch_len = 144
        #self.node_names = ['x1', 'y1', 'z1', 'x2', 'y2', 'z2', 'weight']
        self.leaf_names = []
        #num_leafs = 2**(len(self.node_names)-1)//2
        for l in range(len(self.in_shapes[0])):
            self.leaf_names.append('leaf_one_' + str(l))
            self.leaf_names.append('leaf_two_' + str(l))
        #self.leaf_names.append('bias')
    def set_portfolio_keys(self, folio):
        for k in self.hs.currentHists.keys():
            folio.ledger[k] = 0

    def get_one_epoch_input(self, end_idx):
        master_active = []
        for x in range(0, self.hd):
            active = []
            #print(self.outputs)
            for y in range(0, self.outputs):
                try:
                    sym_data = self.hs.hist_shaped[y][end_idx - x]
                    #print(len(sym_data))
                    active += sym_data.tolist()
                except:
                    print('error')
            master_active.append(active)
        #print(active)
        return master_active

    def evaluate(self, network, es, rand_start, g, verbose=False):
        portfolio_start = 1.0
        portfolio = CryptoFolio(portfolio_start, self.hs.coin_dict, "USDT")
        end_prices = {}
        buys = 0
        sells = 0
        if (len(g.connections) > 0.0):
            for z in range(rand_start, rand_start + self.epoch_len):
                active = self.get_one_epoch_input(z)
                network.reset()
                for n in range(1, self.hd + 1):
                    out = network.activate(active[self.hd - n])
                #print(sorted_shit, len(sorted_shit))
                #print(len(sorted_shit), len(key_list))
                for x in range(len(out)):
                    sym = self.hs.coin_dict[x]
                    #print(out[x])
                    #try:
                    if (out[x] < -.5):
                        #print("selling")
                        portfolio.sell_coin(
                            sym, self.hs.currentHists[sym]['close'][z])
                        #print("bought ", sym)
                    if (out[x] > .5):
                        #print("buying")
                        portfolio.target_amount = .1 + (out[x] * .1)
                        portfolio.buy_coin(
                            sym, self.hs.currentHists[sym]['close'][z])
                        #print("sold ", sym)
                    #skip the hold case because we just dont buy or sell hehe
                    if (z > (self.epoch_len + rand_start) - 2):
                        end_prices[sym] = self.hs.currentHists[sym]['close'][
                            self.epoch_len + rand_start]
            result_val = portfolio.get_total_btc_value(end_prices)
            print(result_val[0], "buys: ", result_val[1], "sells: ",
                  result_val[2])
            if (result_val[1] == 0):
                ft = result_val[0] / 2
            else:
                ft = result_val[0]
        else:
            ft = 0.0
        return ft

    def solve(self, network):
        return self.evaluate(network) >= self.highest_returns

    def trial_run(self):
        r_start = 0
        file = open("es_trade_god_cppn_3d.pkl", 'rb')
        [cppn] = pickle.load(file)
        network = ESNetwork(self.subStrate, cppn, self.params)
        net = network.create_phenotype_network_nd()
        fitness = self.evaluate(net, network, r_start)
        return fitness

    def eval_fitness(self, genomes, config):
        self.epoch_len = randint(255, 455)
        r_start = randint(0 + self.hd, self.hs.hist_full_size - self.epoch_len)
        for idx, g in genomes:
            cppn = neat.nn.FeedForwardNetwork.create(g, config)
            network = ESNetwork(self.subStrate, cppn, self.params)
            net = network.create_phenotype_network_nd()
            g.fitness = self.evaluate(net, network, r_start, g)
        return