File size: 6,766 Bytes
3f54ea6
0c265a3
0aad598
 
 
 
 
 
0c265a3
 
0aad598
 
 
e6344f0
0aad598
e296f90
0aad598
 
 
 
89abea7
0aad598
 
3fd9651
 
08d16b4
0aad598
 
 
 
 
 
 
0c265a3
0aad598
0c265a3
 
0aad598
 
84a35b6
0aad598
 
 
 
 
 
 
 
 
 
 
 
84a35b6
0aad598
84a35b6
0aad598
0c265a3
 
 
0aad598
d53ebfb
 
0aad598
d53ebfb
 
 
0aad598
d53ebfb
 
 
 
 
0c265a3
 
d53ebfb
0c265a3
d53ebfb
 
 
 
0aad598
 
dc4c84d
0aad598
 
0c265a3
e9db3fa
 
 
0c265a3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3f47a40
 
0c265a3
3f47a40
0c265a3
 
 
 
3f47a40
0c265a3
 
3f47a40
 
 
 
80be64d
 
 
3f47a40
 
0c265a3
 
a1da76c
0aad598
 
 
8739669
 
 
 
 
9eae81e
 
 
8739669
7fe01db
0c265a3
 
 
 
 
 
0aad598
899523b
8739669
9eae81e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
import threading
import gym
import numpy as np
import requests
import pandas as pd
from datetime import datetime, timedelta
from stable_baselines3 import PPO
from stable_baselines3.common.vec_env import DummyVecEnv
from gym import spaces
import time
import firebase_admin
from firebase_admin import credentials, db
import os
import gradio as gr

cred = credentials.Certificate("credentials.json")
firebase_admin.initialize_app(cred, {"databaseURL": "https://socail-swap-default-rtdb.asia-southeast1.firebasedatabase.app/"})
ref = db.reference()
buy_signals = []
sell_signals = []
hold_signals = []

class TradingEnv(gym.Env):
    def __init__(self, data, window_size=50):
        super(TradingEnv, self).__init__()
        super(TradingEnv, self).__init__()
        self.data = data
        self.window_size = window_size
        self.current_step = window_size
        self.action_space = spaces.Discrete(3)
        self.observation_space = spaces.Box(
            low=0, high=1, shape=(window_size, 2), dtype=np.float32)
        
    def reset(self):
        self.current_step = self.window_size
        return self._get_observation()
    
    def _get_observation(self):
        window_data = self.data[self.current_step-self.window_size:self.current_step]
        obs = window_data[['close', 'EMA']].values
        obs = (obs - obs.min()) / (obs.max() - obs.min())
        return obs
    
    def step(self, action):
        reward = 0
        done = False
        self.current_step += 1

        if self.current_step >= len(self.data):
            done = True
        else:
            if action == 1:  
                reward = self.data['close'].iloc[self.current_step] - self.data['close'].iloc[self.current_step - 1]
            elif action == 2: 
                reward = self.data['close'].iloc[self.current_step - 1] - self.data['close'].iloc[self.current_step]

        return self._get_observation(), reward, done, {}
    
def fetch_data(symbol='ETH', tsym='USD', start_date='2021-01-01', api_key='66bc686cb714fadda1fad0320704c98869d4b31ce7d9d27560c6c574b4d04c54'):
    start_date = datetime.strptime(start_date, '%Y-%m-%d')
    end_date = datetime.utcnow()
    to_ts = int(end_date.timestamp())
    
    url = f'https://min-api.cryptocompare.com/data/v2/histohour?fsym={symbol}&tsym={tsym}&toTs={to_ts}&api_key={api_key}'
    response = requests.get(url)
    data = response.json()
    
    if data['Response'] == 'Success':
        data_points = data['Data']['Data']
        df = pd.DataFrame(data_points)
        df['time'] = pd.to_datetime(df['time'], unit='s')
        df.set_index('time', inplace=True)
        
        # Filter data based on start_date
        df = df[df.index >= start_date]
        
        return df[['close']]
    else:
        print(f"Error fetching data: {data['Message']}")
        return None

def calculate_ema(data, span=20):
    data['EMA'] = data['close'].ewm(span=span, adjust=False).mean()
    return data

def run_model():
    while True:
        try:
            new_data = fetch_data(start_date=(datetime.utcnow() - timedelta(days=3)).strftime('%Y-%m-%d'))
            new_data = calculate_ema(new_data)
            
            if len(new_data) < 50:
                print("Not enough data to update the environment.")
                time.sleep(3600)
                continue
            
            env = DummyVecEnv([lambda: TradingEnv(new_data)])
            model.set_env(env)
            
            obs = env.reset()
            dates = new_data.index[50:]
            prices = new_data['close'][50:]
            emas = new_data['EMA'][50:]
            actions = []

            for date, price, ema in zip(dates, prices, emas):
                action, _ = model.predict(obs)
                actions.append(action[0])
                obs, _, done, _ = env.step(action)
                if done:
                    break

            new_buy_signals = [(date, price, ema) for date, price, ema, action in zip(dates, prices, emas, actions) if action == 1 and date not in [signal[0] for signal in buy_signals]]
            new_sell_signals = [(date, price, ema) for date, price, ema, action in zip(dates, prices, emas, actions) if action == 2 and date not in [signal[0] for signal in sell_signals]]
            new_hold_signals = [(date, price, ema) for date, price, ema, action in zip(dates, prices, emas, actions) if action == 0 and date not in [signal[0] for signal in hold_signals]]
            
            for signal in new_buy_signals:
                if signal[0] not in [s[0] for s in buy_signals] and signal[0] not in [s[0] for s in sell_signals] and signal[0] not in [s[0] for s in hold_signals]:
                    buy_signals.append(signal)
                

            for signal in new_sell_signals:
                if signal[0] not in [s[0] for s in sell_signals] and signal[0] not in [s[0] for s in buy_signals] and signal[0] not in [s[0] for s in hold_signals]:
                    sell_signals.append(signal)

            for signal in new_hold_signals:
                if signal[0] not in [s[0] for s in hold_signals] and signal[0] not in [s[0] for s in buy_signals] and signal[0] not in [s[0] for s in sell_signals]:
                    hold_signals.append(signal)
            
            buy_signals_data = [{'timestamp': signal[0].strftime('%Y-%m-%d %H:%M:%S'), 'type': 'b', 'price': round(signal[1], 2), 'ema': round(signal[2], 2)} for signal in buy_signals]
            sell_signals_data = [{'timestamp': signal[0].strftime('%Y-%m-%d %H:%M:%S'), 'type': 's', 'price': round(signal[1], 2), 'ema': round(signal[2], 2)} for signal in sell_signals]
            hold_signals_data = [{'timestamp': signal[0].strftime('%Y-%m-%d %H:%M:%S'), 'type': 'h', 'price': round(signal[1], 2), 'ema': round(signal[2], 2)} for signal in hold_signals]
            all_signals_data = buy_signals_data + sell_signals_data + hold_signals_data
            all_signals_data.sort(key=lambda x: x['timestamp'], reverse=True)

            ref.child('signals').child('data').set(all_signals_data)
            time.sleep(3590) 
        except Exception as e:
            print(f"An error occurred: {e}")
            break

def start_model_in_background():
    thread = threading.Thread(target=run_model)
    thread.daemon = True
    thread.start()

def dummy_interface():
    return "Model is running in the background."
    
if __name__ == "__main__":
    data = fetch_data()
    data = calculate_ema(data)
    if len(data) < 50:
        raise ValueError("Not enough data to fill the window size.")

    env = DummyVecEnv([lambda: TradingEnv(data)])

    model = PPO.load("ppo_trading_agent", env=env)
    start_model_in_background()
    gr.Interface(fn=dummy_interface, inputs=[], outputs="text").launch()