GOKULSINGHSHAH123 commited on
Commit
75de802
·
verified ·
1 Parent(s): cb1f099

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.py +484 -0
  2. requirements.txt +7 -0
app.py ADDED
@@ -0,0 +1,484 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import streamlit as st
3
+ import gspread
4
+ from google.oauth2.service_account import Credentials
5
+ import ast
6
+ import requests
7
+ from datetime import datetime
8
+ import json
9
+ # Define the scope
10
+ start = False
11
+ starting_position = []
12
+ tradeHistory_positions = []
13
+ scopes = ["https://www.googleapis.com/auth/spreadsheets"]
14
+
15
+ # Service account credentials as a dictionary
16
+ service_account_info = {
17
+ "type": "service_account",
18
+ "project_id": "primetrade-433011",
19
+ "private_key_id": "8bdab2f373343c045c8712c27e34f858132675df",
20
+ "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCtmNCg9Jkku2+W\nRXWqnOzoLQmXrn4BJC3yk7aaSGNh254/zMrWgyejTGpWxqklv0Hnxx1qn8nb3QoP\nKmRDbJnkt4doKupXFgfxPlebelLXgRT1JDbmVCTfCp8TcG8I1/9FpFNoqvpyeMZx\nd747UfP+bqym1pdhMr6rxCUEYVcKhc/4t+04k3i0IGGWW293CXGWGD54CIeFqWQX\n+SHo20pYfh8FKamytY8LHfwk1XbX1dMjnsxsQ/xZ8IjHZ//+m3bAG7n9QPe3a724\nG3L7iTZ15VET48j55aiSi4tJvHuy/I2kzOXrm/OuHRqJ+bH5+Ze8FVbmbBQlBjn8\nI8boxVSHAgMBAAECggEAMTAHEUwtJmjLpecZf5XGVMUKHkXtYxJmyICNMWsIad5q\nGQbEhIKWFSGeUecpX04xdOSI08Dh19/qLUDkNuyLMHDGN8BNNQ7DgloZRa8j0Pc8\nwncX7SxzZBVk3IOzmmxlYsy8a4BixVOuWtFEgBdpDLM8TWupafuQZigGGxcfrBWl\njgUoga05ybjpsdxW9c9+DoXXaOPHu/QQCEbv1X3dAJHJ0My2rBaO0s+0qoDJime1\nqNms6d36TnnoD6c0qhwD/E0eZfuaijcGxarq5BBnk9qsyxud2dmZd3M8jtVV/Env\n4o1rBV9Hao/z7DKbFdqOPNSMJRtY3e+hRjgm1/feaQKBgQDhKtsMRV+Ovkvu/JdA\nHG6We0nJ/kt8czEmbbW61rvUmJbI8hAK+0TERv/mwXaQqmo6JNhCREcx17vIE7Qy\nEzThGv7hYKotrrEXZq9Dje76KmAtk2zeJPXRriRu1rixRNPRwx9F2I+B3+iXaoqx\nsenzNMSy545P0YvssJYQLnKMTwKBgQDFXi3ZxtKCUwqdOvBEsVHeE00mUbqNm+fV\nDUgxFesQ8KkwuFib29NglnbxG3hgCVpA/4BoCsM2EyuZKap3gtoMW/EZqqhb9Hu+\nfwDoiJy3DmHivq6kHeEo6V6uTDxybqgPN+Yc08X+bqflDMYXLkBuJOnE+8O38TtE\n7BROW+EOSQKBgFiXHPH6BXvLAWM4/GVcCmKohUK1C4weYlMlTSACxooBsynCm29G\npyq2aI6oxXZrpjnUL0X7SSuiHp68qeQdzGtYzLlt5+brWX/EheaFXGYO8CJeY7IP\nRqxF4M2/K5GLa++W3qIDb4sAxql0YLdDMbHfrBhbpJFg97WbUJ9zNtxfAoGAdV23\n7lUpQY6YNT+jOXYotOLNcggP473ecvdfArGCA6TZN7uoFab3X+yZ9m7bemCVZymI\n9lXQGAv2VTJNyJvrhoX2LckqLOSJ4ZIsvBrg9op68xdpSvbpuiZsw0FagMIE9mfL\nU0Er8E1lUfPyqD482kLhMN52WJ//GtE4khBZGOECgYEAwD6mhwYdgQq1rujDZF8g\nzr4Ze3hiwoKGsEvybSYjqmsJMqwLWLCe9Wsj2bPWiMJmkpYdiCC+j3Wo6A1bdWy2\nFn/2T9dO35veJwM/HjP7/jMicyVr6S86vhMfzWuqvnQtuB/HAwctH+N4lJ5z0k8w\nn6WFbBEenJv8p5vZQi0NhHg=\n-----END PRIVATE KEY-----\n",
21
+ "client_email": "myapi-994@primetrade-433011.iam.gserviceaccount.com",
22
+ "client_id": "104595139129046465243",
23
+ "auth_uri": "https://accounts.google.com/o/oauth2/auth",
24
+ "token_uri": "https://oauth2.googleapis.com/token",
25
+ "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
26
+ "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/myapi-994%40primetrade-433011.iam.gserviceaccount.com",
27
+ "universe_domain": "googleapis.com"
28
+ # Add your service account credentials here
29
+ }
30
+ cookie_str = "p20t=web.740861259.532251DB15AFA4E2C9D5A7A4AA7EB97E" #cookie_str get by logging into binance
31
+ csrft = "4f341a1a0b78bfb7ddb0bfc9b093ec06"
32
+ trade_type= "PERPETUAL" # perpetual or delivery
33
+ # Authenticate using the service account info
34
+ creds = Credentials.from_service_account_info(service_account_info, scopes=scopes)
35
+ client = gspread.authorize(creds)
36
+
37
+ # The ID of the Google Sheet (found in the URL of the sheet)
38
+ sheet_id = "1I_PuAeWTaRC4OhS5BA5gv0XQCA17VlIjpA1MvOlzVA8"
39
+
40
+ # Open the Google Sheet by sheet ID
41
+ workbook = client.open_by_key(sheet_id)
42
+
43
+ # Select the specific sheet in the workbook
44
+ sheet = workbook.worksheet("okxHistory")
45
+ sheet2 = workbook.worksheet("okxLeaderBoard")
46
+ sheet3 = workbook.worksheet("Performance")
47
+
48
+ # Extract the data from the Google Sheet into a pandas DataFrame
49
+ data = sheet.get_all_values()
50
+ data2 = sheet2.get_all_values()
51
+
52
+ headers = data.pop(0)
53
+ headers2 = data2.pop(0)
54
+ df = pd.DataFrame(data, columns=headers)
55
+ df2 = pd.DataFrame(data2,columns=headers2)
56
+
57
+
58
+
59
+
60
+
61
+ def combine_chunks(df):
62
+ combined_rows = []
63
+
64
+ # Group by U_IDs
65
+ grouped = df.groupby('U_IDs')
66
+
67
+ for uid, group in grouped:
68
+ # Combine chunks for each UID
69
+
70
+ trade_history_combined = ''.join(group['trade_history'].tolist())
71
+
72
+ # Create a DataFrame for the combined row
73
+ combined_row = pd.DataFrame({
74
+ 'U_IDs': [uid],
75
+ 'trade_history': [trade_history_combined]
76
+ })
77
+
78
+ combined_rows.append(combined_row)
79
+
80
+ # Concatenate all combined rows into a single DataFrame
81
+ combined_df = pd.concat(combined_rows, ignore_index=True)
82
+
83
+ return combined_df
84
+
85
+ df = df.fillna(value=pd.NA)
86
+ df = df.where(pd.notnull(df), None)
87
+ df2 = df2.fillna(value=pd.NA)
88
+ df2 = df2.where(pd.notnull(df2), None)
89
+
90
+
91
+ df = combine_chunks(df)
92
+ # df2 = combine_chunks(df2)
93
+
94
+ def convert_str_to_list_or_keep(value):
95
+ if isinstance(value, str):
96
+ try:
97
+ return ast.literal_eval(value)
98
+ except (SyntaxError, ValueError):
99
+ return value
100
+ else:
101
+ return value
102
+
103
+ df = df.apply(lambda col: col.map(convert_str_to_list_or_keep))
104
+ df2 = df2.apply(lambda col: col.map(convert_str_to_list_or_keep))
105
+
106
+ df['positionClosed'] = False
107
+
108
+ uid_input = st.text_input("Enter U_IDs to filter")
109
+
110
+ option = st.radio("Choose an option:", ["Show Position History", "Show Live Positions"])
111
+
112
+ if df is not None and uid_input:
113
+
114
+ if option == "Show Position History":
115
+ st.title("Position History Viewer")
116
+ # Display starting positions with clickable rows
117
+ st.header("Starting Positions")
118
+
119
+
120
+ filtered_df = df[df['U_IDs'] == uid_input].copy()
121
+
122
+ if not filtered_df.empty:
123
+ trade_list = filtered_df['trade_history'].iloc[0]
124
+ else:
125
+ st.write("No data found for the provided U_ID.")
126
+
127
+
128
+ unique_lists = []
129
+
130
+ def get_amounts_from_positions_and_closed_trades(data):
131
+
132
+
133
+ # Check if 'Modified' key exists and extract amounts
134
+ if 'Modified' in data:
135
+ modified_positions = data['Modified']
136
+ # modified_positions = modified_positions[0]
137
+ if isinstance(modified_positions, dict) and 'amount' in modified_positions:
138
+ amount = modified_positions.get('amount')
139
+ if isinstance(amount, (int, float)): # Check if amount is a number
140
+ amounts =amount
141
+ # Check if 'ClosedTrades' key exists and extract amounts
142
+ if 'ClosedTrades' in data:
143
+ closed_trades = data['ClosedTrades']
144
+ closed_trades =closed_trades[0]
145
+ if isinstance(closed_trades, dict) and 'amount' in closed_trades:
146
+ amount = closed_trades.get('amount')
147
+ if isinstance(amount, (int, float)): # Check if amount is a number
148
+ amounts = amount
149
+
150
+ return amounts
151
+
152
+ def get_symbols_from_positions_and_closed_trades(data):
153
+
154
+
155
+ # Check if 'Modified' key exists and extract symbols
156
+ if 'Modified' in data:
157
+ modified_positions = data['Modified']
158
+ # modified_positions =modified_positions
159
+ if isinstance(modified_positions, dict) and 'symbol' in modified_positions:
160
+ symbol = modified_positions['symbol']
161
+
162
+ # Check if 'ClosedTrades' key exists and extract symbols
163
+ if 'ClosedTrades' in data:
164
+ closed_trades = data['ClosedTrades']
165
+ closed_trades =closed_trades[0]
166
+ if isinstance(closed_trades, dict) and 'symbol' in closed_trades:
167
+ symbol = closed_trades['symbol']
168
+
169
+ return symbol
170
+
171
+ for i in range(len(trade_list)):
172
+
173
+
174
+ if trade_list[i]=="none":
175
+ continue
176
+
177
+ if not trade_list: # Check if the trade_list is empty
178
+ st.header("No data found, this may not be in the leaderboard")
179
+
180
+ if start ==False:
181
+ st.subheader(f"Data is from {datetime.now()}")
182
+ start =True
183
+ foundCLosed = False
184
+ changeInAmount = 0
185
+
186
+ if 'symbol' in trade_list[i]:
187
+ symbol = trade_list[i]['symbol']
188
+ side ="buy" if trade_list[i]['amount']>0 else "sell"
189
+ amount = trade_list[i]['amount']
190
+ symbol = trade_list[i]['symbol']
191
+ trade_list[i]['side'] =side
192
+ trade_list[i]['changeInAmount'] = changeInAmount
193
+ trade_list[i]['i'] = i
194
+ unique_lists.append({"position":trade_list[i]})
195
+ trade_list[i] = "none"
196
+
197
+
198
+ else:
199
+ if 'positions' in trade_list[i]:
200
+ reached = False
201
+ # Collect necessary data first before modifying the dictionary
202
+ for k, v in list(trade_list[i].items()): # Convert to a list to avoid modifying during iteration
203
+ for entry in v:
204
+ if 'NewPosition' in entry:
205
+ new_position = entry.get('NewPosition', {})
206
+ # Extract symbol and amount
207
+ symbol = new_position.get('symbol')
208
+ amount = new_position.get('amount')
209
+ if start==False:
210
+ start_time = new_position.get('updateTime')
211
+ year = start_time[0]
212
+ month = start_time[1]
213
+ day = start_time[2]
214
+ hour =start_time[3]
215
+ minute =start_time[4]
216
+ seconds = start_time[5]
217
+ dt = datetime(year, month, day, hour, minute, seconds)
218
+ human_readable_format = dt.strftime('%B %d, %Y, %I:%M:%S %p')
219
+ st.subheader(f"Data from {human_readable_format}")
220
+ start=True
221
+ # if start==False:
222
+ #
223
+ # start =True
224
+ side = "buy" if amount > 0 else "sell"
225
+ new_position['side'] = side
226
+ new_position['changeInAmount'] = changeInAmount
227
+ new_position['i'] = i
228
+ # Update the entry with the modified 'NewPosition'
229
+ entry['NewPosition'] = new_position
230
+
231
+ # Append the updated trade_list[i] to unique_lists
232
+ unique_lists.append(trade_list[i])
233
+
234
+ reached = True
235
+
236
+ # Now safely modify the dictionary after iteration is complete
237
+ if reached:
238
+ trade_list[i] = "none"
239
+
240
+ # Now safely modify the dictionary after iteration is complete
241
+
242
+
243
+ for j in range(i+1, len(trade_list)):
244
+ if trade_list[j] == "none":
245
+ continue
246
+
247
+ if 'positions' in trade_list[j] and isinstance(trade_list[j]['positions'], list):
248
+ for position in trade_list[j]['positions']:
249
+ # Check if 'Modified' is in the position and is a dict
250
+ if 'Modified' in position and isinstance(position['Modified'], dict):
251
+
252
+ if start==False:
253
+ for k,v in position.items():
254
+ start_time = v['updateTime']
255
+
256
+ year = start_time[0]
257
+ month = start_time[1]
258
+ day = start_time[2]
259
+ hour =start_time[3]
260
+ minute =start_time[4]
261
+ seconds = start_time[5]
262
+ dt = datetime(year, month, day, hour, minute, seconds)
263
+ human_readable_format = dt.strftime('%d-%m-%Y %H:%M:%S')
264
+ st.subheader(f"Data from {human_readable_format}")
265
+ start=True
266
+ modified_amount = get_amounts_from_positions_and_closed_trades(position)
267
+ modified_symbol = get_symbols_from_positions_and_closed_trades(position)
268
+
269
+ if modified_amount > 0:
270
+ modified_side = "buy"
271
+ else:
272
+ modified_side = "sell"
273
+
274
+ if symbol == modified_symbol and side == modified_side:
275
+ if start ==False:
276
+ st.header(f"Data is from {datetime.now}")
277
+ start =True
278
+ position['Modified']['side'] = modified_side
279
+ position['Modified']['changeInAmount'] = amount - modified_amount if modified_amount < 0 else modified_amount - amount
280
+ position['Modified']['i'] = i
281
+ amount = modified_amount
282
+ unique_lists.append(trade_list[j])
283
+ trade_list[j] = "none"
284
+
285
+ # Check if 'ClosedTrades' is in the position and is a tuple
286
+ if 'ClosedTrades' in position and isinstance(position['ClosedTrades'], tuple):
287
+ if start ==False:
288
+ st.header(f"Data is from {datetime.now}")
289
+ start =True
290
+ foundCLosed = False
291
+ closed_trades_tuple = position['ClosedTrades']
292
+ closed_trades_dict = {
293
+ 'trade_info': closed_trades_tuple[0],
294
+ 'side': closed_trades_tuple[1]
295
+ }
296
+
297
+ closed_amount = get_amounts_from_positions_and_closed_trades(position)
298
+ closed_symbol = get_symbols_from_positions_and_closed_trades(position)
299
+
300
+ if closed_amount > 0:
301
+ closed_side = "buy"
302
+ else:
303
+ closed_side = "sell"
304
+
305
+ if symbol == closed_symbol and side == closed_side:
306
+ if start==False:
307
+ for k,v in position.items():
308
+ start_time = v['updateTime']
309
+ start =True
310
+
311
+ closed_trades_dict['side'] = closed_side
312
+ trade_info = closed_trades_dict['trade_info']
313
+ trade_info['changeInAmount'] = amount - closed_amount if closed_amount < 0 else closed_amount - amount
314
+ amount = closed_amount
315
+ closed_trades_dict['trade_info']['i'] = i # Store index 'i' inside 'ClosedTrades'
316
+ closed_trades_dict['trade_info']['closed'] = True
317
+
318
+ # Append the updated trade_list[j] to unique_lists
319
+ unique_lists.append(trade_list[j])
320
+ trade_list[j] = "none"
321
+ foundCLosed = True
322
+ break
323
+
324
+ # Break the inner loop if a closed trade was found
325
+ if foundCLosed:
326
+ break
327
+
328
+
329
+
330
+
331
+ for k in range(len(unique_lists)):
332
+ data = unique_lists[k]
333
+
334
+
335
+ if k ==0:
336
+
337
+
338
+ if 'positions' in data:
339
+ if isinstance(data['positions'], list):
340
+ for a in data['positions']:
341
+ if 'NewPosition' in a:
342
+
343
+ position_data = a['NewPosition']
344
+ starting_position.append(position_data)
345
+ tradeHistory_positions.append(position_data)
346
+
347
+
348
+ else:
349
+ if 'position' in data:
350
+ position_data =data['position']
351
+ starting_position.append(position_data)
352
+ tradeHistory_positions.append(position_data)
353
+
354
+
355
+
356
+ if 'positions' in data:
357
+ if isinstance(data['positions'],list):
358
+ for a in data['positions']:
359
+ if 'ClosedTrades' in a:
360
+ position_data = a['ClosedTrades'][0]
361
+ tradeHistory_positions.append(position_data)
362
+
363
+
364
+
365
+ if 'positions' in data:
366
+ if isinstance(data['positions'],list):
367
+ for a in data['positions']:
368
+ if 'Modified' in a:
369
+ position_data = a['Modified']
370
+ tradeHistory_positions.append(position_data)
371
+
372
+
373
+
374
+
375
+ unique_lists =[]
376
+
377
+ elif option == "Show Live Positions":
378
+ filtered_df2 = df2[df2['U_IDs'] == uid_input]
379
+
380
+ if not filtered_df2.empty:
381
+
382
+ positions_list = filtered_df2['Positions'].iloc[0] # Extract the first match
383
+
384
+ # Convert the list of dictionaries to a DataFrame
385
+ if isinstance(positions_list, list) and positions_list:
386
+ positions_df = pd.DataFrame(positions_list)
387
+ st.subheader("Live Positions")
388
+ st.dataframe(positions_df)
389
+ else:
390
+ st.write("No live positions data available for the given U_ID.")
391
+
392
+
393
+
394
+ data3 = sheet3.get_all_values()
395
+ headers3 = data3.pop(0)
396
+ df3 = pd.DataFrame(data3, columns=headers3)
397
+ filtered_df3 = df3[df3['U_IDs'] == uid_input]
398
+ st.subheader("Performace")
399
+ st.dataframe(filtered_df3)
400
+
401
+
402
+
403
+ def show_position_history(selected_position):
404
+ st.header(f"History for {selected_position}")
405
+
406
+ # Filter trade history for the selected position
407
+ position_history = [pos for pos in tradeHistory_positions if pos['i'] == selected_position]
408
+
409
+
410
+
411
+ if position_history:
412
+ df_history = pd.DataFrame(position_history)
413
+
414
+ # Update the global timestamp with the last update from history
415
+
416
+
417
+ # Create a transformed DataFrame for display
418
+ df_transformed = pd.DataFrame({
419
+ 'Pair/Asset': df_history['symbol'],
420
+ 'is long': df_history['side'],
421
+ 'Current size after change': df_history['amount'],
422
+ 'Change in size in Asset': df_history['changeInAmount'],
423
+ 'Change in size in USDT': df_history['changeInAmount'] * -(df_history['markPrice']),
424
+ 'Entry price': df_history['entryPrice'],
425
+ 'Exit price': df_history['markPrice'],
426
+ 'pnl in usdt': df_history['pnl'],
427
+ 'pnl in %': df_history['roe'],
428
+ 'Leverage': df_history['leverage'],
429
+ 'updatedTime': df_history['updateTime']
430
+ })
431
+
432
+ if 'closed' in df_history.columns:
433
+ df_transformed['Position closed'] = df_history['closed']
434
+
435
+ st.dataframe(df_transformed)
436
+
437
+ # Add the update timestamp to the transformed DataFrame
438
+
439
+ else:
440
+ st.write("No history found for this position.")
441
+
442
+ def lastUpdated(selected_position):
443
+ position_history = [pos for pos in tradeHistory_positions if pos['i'] == selected_position]
444
+ return position_history[-1]['updateTime']
445
+
446
+ def isClosed(selected_position):
447
+ # Filter trade history for the selected position
448
+ position_history = [pos for pos in tradeHistory_positions if pos['i'] == selected_position]
449
+
450
+ # Check if there are any records for the selected position
451
+ if not position_history:
452
+ return False
453
+
454
+ # Get the most recent entry for the selected position
455
+ last_entry = position_history[-1]
456
+
457
+ # Check if the 'closed' key exists and if it indicates the position is closed
458
+ return last_entry.get('closed', False)
459
+
460
+
461
+
462
+
463
+ def main():
464
+ df_starting = pd.DataFrame(starting_position)
465
+
466
+ for index, row in df_starting.iterrows():
467
+ side = True if row['amount'] > 0 else False
468
+ is_closed = isClosed(row['i'])
469
+
470
+ # Generate a unique key for the button
471
+ button_key = f"position_{row['i']}"
472
+
473
+ # Display a button for each trade position
474
+ if st.button(
475
+ f"{row['symbol']} : Long: {side}, Entry Price: {row['entryPrice']}, "
476
+ f"Market Price: {row['markPrice']}, Amount: {row['amount']}, "
477
+ f"Leverage: {row['leverage']}, TradeTakenAt: {row['updateTime']}, "
478
+ f"lastUpdated: {lastUpdated(row['i'])}, isClosed: {is_closed}",
479
+ key=button_key
480
+ ):
481
+ show_position_history(row['i'])
482
+
483
+ if __name__ == "__main__":
484
+ main()
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ pandas
2
+ numpy
3
+ streamlit
4
+ gspread
5
+ google-auth-oauthlib
6
+ requests
7
+ astor