Fixed issue with fetching historical data and added missing imports.
This commit is contained in:
parent
49c908357f
commit
0bb9780ff6
159
markdown/App.md
159
markdown/App.md
|
|
@ -1,159 +0,0 @@
|
||||||
## App Flow Charts
|
|
||||||
|
|
||||||
### App
|
|
||||||
```plantuml
|
|
||||||
@startuml
|
|
||||||
start
|
|
||||||
:Create BrighterTrades object;
|
|
||||||
:configuration app;
|
|
||||||
:run app;
|
|
||||||
stop
|
|
||||||
@enduml
|
|
||||||
```
|
|
||||||
|
|
||||||
### /index
|
|
||||||
```plantuml
|
|
||||||
@startuml
|
|
||||||
start
|
|
||||||
:Log in user;
|
|
||||||
:Load dynamic data;
|
|
||||||
:Render Landing Page;
|
|
||||||
stop
|
|
||||||
@enduml
|
|
||||||
```
|
|
||||||
|
|
||||||
### /ws
|
|
||||||
```plantuml
|
|
||||||
@startuml
|
|
||||||
start
|
|
||||||
repeat
|
|
||||||
:Listen for message;
|
|
||||||
if (Contains json?) then (yse)
|
|
||||||
:Process_received_json();
|
|
||||||
else (no)
|
|
||||||
:Display_message();
|
|
||||||
endif
|
|
||||||
repeatwhile()
|
|
||||||
@enduml
|
|
||||||
```
|
|
||||||
|
|
||||||
### /settings
|
|
||||||
```plantuml
|
|
||||||
@startuml
|
|
||||||
start
|
|
||||||
if (Logged in?) then (no)
|
|
||||||
:redirect -> "/index";
|
|
||||||
stop
|
|
||||||
else (yes)
|
|
||||||
:get_setting();
|
|
||||||
:process_command();
|
|
||||||
:redirect -> "/index";
|
|
||||||
stop
|
|
||||||
@enduml
|
|
||||||
```
|
|
||||||
|
|
||||||
### /history
|
|
||||||
```plantuml
|
|
||||||
@startuml
|
|
||||||
start
|
|
||||||
if (Logged in?) then (no)
|
|
||||||
:Return empty data;
|
|
||||||
stop
|
|
||||||
else (yes)
|
|
||||||
:Get current chart view details.;
|
|
||||||
:Request price history for the chart view.;
|
|
||||||
:Return data;
|
|
||||||
stop
|
|
||||||
@enduml
|
|
||||||
```
|
|
||||||
|
|
||||||
### /signup
|
|
||||||
```plantuml
|
|
||||||
@startuml
|
|
||||||
start
|
|
||||||
:Return rendered signup page.;
|
|
||||||
stop
|
|
||||||
@enduml
|
|
||||||
```
|
|
||||||
|
|
||||||
### /signout
|
|
||||||
```plantuml
|
|
||||||
@startuml
|
|
||||||
start
|
|
||||||
:Logout user.;
|
|
||||||
:Delete client session var.;
|
|
||||||
:redirect -> /index;
|
|
||||||
stop
|
|
||||||
@enduml
|
|
||||||
```
|
|
||||||
|
|
||||||
### /login
|
|
||||||
```plantuml
|
|
||||||
@startuml
|
|
||||||
start
|
|
||||||
:Get credentials;
|
|
||||||
:Log in user.;
|
|
||||||
if (success) then (yes)
|
|
||||||
:Set the client session var;
|
|
||||||
else (no)
|
|
||||||
endif
|
|
||||||
:Redirect -> /index;
|
|
||||||
stop
|
|
||||||
@enduml
|
|
||||||
```
|
|
||||||
|
|
||||||
### /signup_submit
|
|
||||||
```plantuml
|
|
||||||
@startuml
|
|
||||||
|
|
||||||
start
|
|
||||||
|
|
||||||
:Receive form data;
|
|
||||||
:Extract email, username, and password;
|
|
||||||
:Validate email format;
|
|
||||||
if (Valid email format?) then (yes)
|
|
||||||
:Validate username and password;
|
|
||||||
if (Valid username and password?) then (yes)
|
|
||||||
:Create new user;
|
|
||||||
if (Success) then (yes)
|
|
||||||
:Set session user;
|
|
||||||
:Redirect to homepage;
|
|
||||||
else (no)
|
|
||||||
:Flash error message;
|
|
||||||
endif
|
|
||||||
else (no)
|
|
||||||
:Flash error message;
|
|
||||||
endif
|
|
||||||
else (no)
|
|
||||||
:Flash error message;
|
|
||||||
endif
|
|
||||||
|
|
||||||
stop
|
|
||||||
|
|
||||||
@enduml
|
|
||||||
```
|
|
||||||
### /indictor_init
|
|
||||||
```plantuml
|
|
||||||
@startuml
|
|
||||||
start
|
|
||||||
|
|
||||||
if (Check if username is provided) then (yes)
|
|
||||||
:Retrieve username from request data;
|
|
||||||
else (no)
|
|
||||||
:Return error response;
|
|
||||||
stop
|
|
||||||
endif
|
|
||||||
|
|
||||||
if (Check if user is logged in) then (yes)
|
|
||||||
:Retrieve chart view for the user;
|
|
||||||
else (no)
|
|
||||||
:Return error response;
|
|
||||||
stop
|
|
||||||
endif
|
|
||||||
|
|
||||||
:Retrieve indicator data for the user;
|
|
||||||
:Return data response;
|
|
||||||
stop
|
|
||||||
|
|
||||||
@endum
|
|
||||||
```
|
|
||||||
|
|
@ -0,0 +1,375 @@
|
||||||
|
## App Flow Charts
|
||||||
|
|
||||||
|
### App
|
||||||
|
```plantuml
|
||||||
|
@startuml
|
||||||
|
skinparam legendBackgroundColor lightgreen
|
||||||
|
skinparam defaultFontColor blue
|
||||||
|
skinparam legendAlignment left
|
||||||
|
skinparam defaultFontName "Arial Black"
|
||||||
|
skinparam legendFontSize 12
|
||||||
|
|
||||||
|
skinparam activity {
|
||||||
|
BackgroundColor lightblue
|
||||||
|
BorderColor black
|
||||||
|
FontColor darkblue
|
||||||
|
FontSize 16
|
||||||
|
}
|
||||||
|
|
||||||
|
legend top
|
||||||
|
————————————————————————————————
|
||||||
|
=<b>app.py</b>
|
||||||
|
————————————————————————————————
|
||||||
|
Initializes the BrighterTrades object, configures the Flask
|
||||||
|
server, defines the endpoints then launches the app.
|
||||||
|
end legend
|
||||||
|
start
|
||||||
|
:Create BrighterTrades object;
|
||||||
|
:Configure app;
|
||||||
|
:Define endpoints;
|
||||||
|
:Run app;
|
||||||
|
stop
|
||||||
|
|
||||||
|
|
||||||
|
@enduml
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### /index
|
||||||
|
```plantuml
|
||||||
|
@startuml
|
||||||
|
skinparam legendBackgroundColor lightgreen
|
||||||
|
skinparam defaultFontColor blue
|
||||||
|
skinparam legendAlignment left
|
||||||
|
skinparam defaultFontName "Arial Black"
|
||||||
|
skinparam legendFontSize 12
|
||||||
|
|
||||||
|
skinparam activity {
|
||||||
|
BackgroundColor lightblue
|
||||||
|
BorderColor black
|
||||||
|
FontColor darkblue
|
||||||
|
FontSize 16
|
||||||
|
}
|
||||||
|
|
||||||
|
legend top
|
||||||
|
————————————————————————————————
|
||||||
|
=<b>/index</b>
|
||||||
|
————————————————————————————————
|
||||||
|
Handles the main landing page, logs in the user,
|
||||||
|
loads dynamic data, and renders the landing page.
|
||||||
|
end legend
|
||||||
|
start
|
||||||
|
:Log in user;
|
||||||
|
:Load dynamic data;
|
||||||
|
:Render Landing Page;
|
||||||
|
stop
|
||||||
|
@enduml
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### /ws
|
||||||
|
```plantuml
|
||||||
|
@startuml
|
||||||
|
skinparam legendBackgroundColor lightgreen
|
||||||
|
skinparam defaultFontColor blue
|
||||||
|
skinparam legendAlignment left
|
||||||
|
skinparam defaultFontName "Arial Black"
|
||||||
|
skinparam legendFontSize 12
|
||||||
|
|
||||||
|
skinparam activity {
|
||||||
|
BackgroundColor lightblue
|
||||||
|
BorderColor black
|
||||||
|
FontColor darkblue
|
||||||
|
FontSize 16
|
||||||
|
}
|
||||||
|
|
||||||
|
legend top
|
||||||
|
————————————————————————————————
|
||||||
|
=<b>/ws</b>
|
||||||
|
————————————————————————————————
|
||||||
|
Handles WebSocket connections, listens for messages,
|
||||||
|
processes JSON data, and displays messages.
|
||||||
|
end legend
|
||||||
|
start
|
||||||
|
repeat
|
||||||
|
:Listen for message;
|
||||||
|
if (Contains JSON?) then (yes)
|
||||||
|
:Process received JSON;
|
||||||
|
else (no)
|
||||||
|
:Display message;
|
||||||
|
endif
|
||||||
|
repeat while ()
|
||||||
|
@enduml
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### /settings
|
||||||
|
```plantuml
|
||||||
|
@startuml
|
||||||
|
skinparam legendBackgroundColor lightgreen
|
||||||
|
skinparam defaultFontColor blue
|
||||||
|
skinparam legendAlignment left
|
||||||
|
skinparam defaultFontName "Arial Black"
|
||||||
|
skinparam legendFontSize 12
|
||||||
|
|
||||||
|
skinparam activity {
|
||||||
|
BackgroundColor lightblue
|
||||||
|
BorderColor black
|
||||||
|
FontColor darkblue
|
||||||
|
FontSize 16
|
||||||
|
}
|
||||||
|
|
||||||
|
legend top
|
||||||
|
————————————————————————————————
|
||||||
|
=<b>/settings</b>
|
||||||
|
————————————————————————————————
|
||||||
|
Handles settings changes. If user is logged in,
|
||||||
|
processes commands and redirects to index.
|
||||||
|
end legend
|
||||||
|
start
|
||||||
|
if (Logged in?) then (no)
|
||||||
|
:redirect -> "/index";
|
||||||
|
stop
|
||||||
|
else (yes)
|
||||||
|
:get_setting();
|
||||||
|
:process_command();
|
||||||
|
:redirect -> "/index";
|
||||||
|
endif
|
||||||
|
stop
|
||||||
|
@enduml
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### /history
|
||||||
|
```plantuml
|
||||||
|
@startuml
|
||||||
|
skinparam legendBackgroundColor lightgreen
|
||||||
|
skinparam defaultFontColor blue
|
||||||
|
skinparam legendAlignment left
|
||||||
|
skinparam defaultFontName "Arial Black"
|
||||||
|
skinparam legendFontSize 12
|
||||||
|
|
||||||
|
skinparam activity {
|
||||||
|
BackgroundColor lightblue
|
||||||
|
BorderColor black
|
||||||
|
FontColor darkblue
|
||||||
|
FontSize 16
|
||||||
|
}
|
||||||
|
|
||||||
|
legend top
|
||||||
|
————————————————————————
|
||||||
|
=<b>/history​</b>
|
||||||
|
————————————————————————
|
||||||
|
Fetches candle history for
|
||||||
|
a specific trading pair
|
||||||
|
and timeframe. Returns empty
|
||||||
|
data if user is not logged in.
|
||||||
|
end legend
|
||||||
|
start
|
||||||
|
if (Logged in?) then (no)
|
||||||
|
:Return empty data;
|
||||||
|
stop
|
||||||
|
else (yes)
|
||||||
|
:Get current chart view details;
|
||||||
|
:Request price history for the chart view;
|
||||||
|
:Return data;
|
||||||
|
endif
|
||||||
|
stop
|
||||||
|
@enduml
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### /signup
|
||||||
|
```plantuml
|
||||||
|
@startuml
|
||||||
|
skinparam legendBackgroundColor lightgreen
|
||||||
|
skinparam defaultFontColor blue
|
||||||
|
skinparam legendAlignment left
|
||||||
|
skinparam defaultFontName "Arial Black"
|
||||||
|
skinparam legendFontSize 12
|
||||||
|
|
||||||
|
skinparam activity {
|
||||||
|
BackgroundColor lightblue
|
||||||
|
BorderColor black
|
||||||
|
FontColor darkblue
|
||||||
|
FontSize 16
|
||||||
|
}
|
||||||
|
|
||||||
|
legend top
|
||||||
|
————————————————————————————————
|
||||||
|
=<b>/signup</b>
|
||||||
|
————————————————————————————————
|
||||||
|
Returns the rendered signup page.​
|
||||||
|
end legend
|
||||||
|
start
|
||||||
|
:Return rendered signup page​;
|
||||||
|
stop
|
||||||
|
@enduml
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### /signout
|
||||||
|
```plantuml
|
||||||
|
@startuml
|
||||||
|
skinparam legendBackgroundColor lightgreen
|
||||||
|
skinparam defaultFontColor blue
|
||||||
|
skinparam legendAlignment left
|
||||||
|
skinparam defaultFontName "Arial Black"
|
||||||
|
skinparam legendFontSize 12
|
||||||
|
|
||||||
|
skinparam activity {
|
||||||
|
BackgroundColor lightblue
|
||||||
|
BorderColor black
|
||||||
|
FontColor darkblue
|
||||||
|
FontSize 16
|
||||||
|
}
|
||||||
|
|
||||||
|
legend top
|
||||||
|
————————————————————————————————
|
||||||
|
=<b>/signout</b>
|
||||||
|
————————————————————————————————
|
||||||
|
Logs out the user, deletes the client
|
||||||
|
session variable, and redirects to index.
|
||||||
|
end legend
|
||||||
|
start
|
||||||
|
:Logout user;
|
||||||
|
:Delete client session var;
|
||||||
|
:redirect -> "/index";
|
||||||
|
stop
|
||||||
|
@enduml
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### /login
|
||||||
|
```plantuml
|
||||||
|
@startuml
|
||||||
|
skinparam legendBackgroundColor lightgreen
|
||||||
|
skinparam defaultFontColor blue
|
||||||
|
skinparam legendAlignment left
|
||||||
|
skinparam defaultFontName "Arial Black"
|
||||||
|
skinparam legendFontSize 12
|
||||||
|
|
||||||
|
skinparam activity {
|
||||||
|
BackgroundColor lightblue
|
||||||
|
BorderColor black
|
||||||
|
FontColor darkblue
|
||||||
|
FontSize 16
|
||||||
|
}
|
||||||
|
|
||||||
|
legend top
|
||||||
|
————————————————————————————————
|
||||||
|
=<b>/login</b>
|
||||||
|
————————————————————————————————
|
||||||
|
Handles user login by receiving credentials,
|
||||||
|
logging in the user, and redirecting to index.
|
||||||
|
end legend
|
||||||
|
start
|
||||||
|
:Get credentials;
|
||||||
|
:Log in user;
|
||||||
|
if (success) then (yes)
|
||||||
|
:Set the client session var;
|
||||||
|
else (no)
|
||||||
|
endif
|
||||||
|
:Redirect -> /index;
|
||||||
|
stop
|
||||||
|
@enduml
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### /signup_submit
|
||||||
|
```plantuml
|
||||||
|
@startuml
|
||||||
|
skinparam legendBackgroundColor lightgreen
|
||||||
|
skinparam defaultFontColor blue
|
||||||
|
skinparam legendAlignment left
|
||||||
|
skinparam defaultFontName "Arial Black"
|
||||||
|
skinparam legendFontSize 12
|
||||||
|
|
||||||
|
skinparam activity {
|
||||||
|
BackgroundColor lightblue
|
||||||
|
BorderColor black
|
||||||
|
FontColor darkblue
|
||||||
|
FontSize 16
|
||||||
|
}
|
||||||
|
|
||||||
|
legend top
|
||||||
|
————————————————————————————————
|
||||||
|
=<b>/signup_submit</b>
|
||||||
|
————————————————————————————————
|
||||||
|
Handles user signup by receiving form data,​
|
||||||
|
validating email, creating new user,
|
||||||
|
and redirecting to homepage.
|
||||||
|
end legend
|
||||||
|
start
|
||||||
|
:Receive form data;
|
||||||
|
:Extract email, username, and password​;
|
||||||
|
:Validate email format;
|
||||||
|
if (Valid email format?) then (yes)
|
||||||
|
:Validate username and password;
|
||||||
|
if (Valid username and password?) then (yes)
|
||||||
|
:Create new user;
|
||||||
|
if (Success) then (yes)
|
||||||
|
:Set session user;
|
||||||
|
:Redirect to homepage;
|
||||||
|
else (no)
|
||||||
|
:Flash error message;
|
||||||
|
endif
|
||||||
|
else (no)
|
||||||
|
:Flash error message;
|
||||||
|
endif
|
||||||
|
else (no)
|
||||||
|
:Flash error message;
|
||||||
|
endif
|
||||||
|
stop
|
||||||
|
@enduml
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### /indictor_init
|
||||||
|
```plantuml
|
||||||
|
@startuml
|
||||||
|
skinparam legendBackgroundColor lightgreen
|
||||||
|
skinparam defaultFontColor blue
|
||||||
|
skinparam legendAlignment left
|
||||||
|
skinparam defaultFontName "Arial Black"
|
||||||
|
skinparam legendFontSize 12
|
||||||
|
|
||||||
|
skinparam activity {
|
||||||
|
BackgroundColor lightblue
|
||||||
|
BorderColor black
|
||||||
|
FontColor darkblue
|
||||||
|
FontSize 16
|
||||||
|
}
|
||||||
|
|
||||||
|
legend top
|
||||||
|
————————————————————————————————
|
||||||
|
=<b>/indicator_init</b>
|
||||||
|
————————————————————————————————
|
||||||
|
Initializes the indicators for a given symbol
|
||||||
|
and timeframe, retrieves user and chart view​
|
||||||
|
details, and returns data response.​
|
||||||
|
end legend
|
||||||
|
start
|
||||||
|
if (Check if username is provided) then (yes)
|
||||||
|
:Retrieve username from request data;
|
||||||
|
else (no)
|
||||||
|
:Return error response;
|
||||||
|
stop
|
||||||
|
endif
|
||||||
|
|
||||||
|
if (Check if user is logged in) then (yes)
|
||||||
|
:Retrieve chart view for the user;
|
||||||
|
else (no)
|
||||||
|
:Return error response;
|
||||||
|
stop
|
||||||
|
endif
|
||||||
|
|
||||||
|
:Retrieve indicator data for the user;
|
||||||
|
:Return data response;
|
||||||
|
stop
|
||||||
|
@enduml
|
||||||
|
|
||||||
|
```
|
||||||
|
|
@ -1,6 +1,16 @@
|
||||||
```plantuml
|
```plantuml
|
||||||
|
@startuml
|
||||||
|
scale 1
|
||||||
|
|
||||||
class "BrighterTrades" {
|
skinparam class {
|
||||||
|
BackgroundColor<<BrighterTrades>> lightblue
|
||||||
|
BackgroundColor<<Config>> lightgreen
|
||||||
|
BackgroundColor<<DataCache>> lightyellow
|
||||||
|
BackgroundColor<<Database>> lightcoral
|
||||||
|
BackgroundColor<<ExchangeInterface>> lightgrey
|
||||||
|
}
|
||||||
|
|
||||||
|
class "BrighterTrades" <<BrighterTrades>> {
|
||||||
+ config
|
+ config
|
||||||
+ data_cache
|
+ data_cache
|
||||||
+ strategies
|
+ strategies
|
||||||
|
|
@ -35,30 +45,146 @@ class "BrighterTrades" {
|
||||||
}
|
}
|
||||||
|
|
||||||
class "app" {
|
class "app" {
|
||||||
+ "index()"
|
+ index()
|
||||||
+ "ws(socket_conn)"
|
+ ws(socket_conn)
|
||||||
+ "settings()"
|
+ settings()
|
||||||
+ "history()"
|
+ history()
|
||||||
+ "signup()"
|
+ signup()
|
||||||
+ "signout()"
|
+ signout()
|
||||||
+ "login()"
|
+ login()
|
||||||
+ "signup_submit()"
|
+ signup_submit()
|
||||||
+ "indicator_init()"
|
+ indicator_init()
|
||||||
}
|
}
|
||||||
|
|
||||||
class "Flask" {
|
class "Flask" {
|
||||||
+ "render_template()"
|
+ render_template()
|
||||||
}
|
}
|
||||||
|
|
||||||
"app" --> "index()" : "index()"
|
class "Users" <<DataCache>> {
|
||||||
"app" --> "ws(socket_conn)" : "ws(socket_conn)"
|
+ data_cache
|
||||||
"app" --> "settings()" : "settings()"
|
}
|
||||||
"app" --> "history()" : "history()"
|
|
||||||
"app" --> "signup()" : "signup()"
|
class "Configuration" <<Config>> {
|
||||||
"app" --> "signout()" : "signout()"
|
+ exchanges
|
||||||
"app"--> "login()" : "login()"
|
+ indicators
|
||||||
"app" --> "signup_submit()" : "signup_submit()"
|
+ users
|
||||||
"app" --> "indicator_init()" : "indicator_init()"
|
+ __init__(exchanges, indicators, users)
|
||||||
|
+ get_exchanges()
|
||||||
|
+ get_indicators()
|
||||||
|
+ get_users()
|
||||||
|
+ add_exchange(exchange)
|
||||||
|
+ remove_exchange(exchange)
|
||||||
|
+ add_indicator(indicator)
|
||||||
|
+ remove_indicator(indicator)
|
||||||
|
+ add_user(user)
|
||||||
|
+ remove_user(user)
|
||||||
|
}
|
||||||
|
|
||||||
|
class "Candles" <<DataCache>> {
|
||||||
|
+ __init__(exchanges, config_obj, database)
|
||||||
|
+ get_last_n_candles(num_candles, asset, timeframe, exchange, user_name)
|
||||||
|
+ set_new_candle(cdata)
|
||||||
|
+ set_cache(symbol=None, interval=None, exchange_name=None, user_name=None)
|
||||||
|
+ get_latestvalues(value_name, symbol, timeframe, exchange, user_name, num_record=1)
|
||||||
|
+ convert_candles(candles)
|
||||||
|
+ get_candle_history(num_records, symbol=None, interval=None, exchange_name=None, user_name=None)
|
||||||
|
}
|
||||||
|
|
||||||
|
class "DataCache" <<DataCache>> {
|
||||||
|
+ db
|
||||||
|
+ get_records_since(key, start_datetime, record_length, ex_details)
|
||||||
|
+ cache_exists(key)
|
||||||
|
+ update_candle_cache(more_records, key)
|
||||||
|
+ get_cached_candles(key)
|
||||||
|
+ set_cached_candles(candles, key)
|
||||||
|
+ clear_cache()
|
||||||
|
+ get_cache_info()
|
||||||
|
+ remove_expired_records()
|
||||||
|
+ remove_cache(key)
|
||||||
|
+ remove_all_caches()
|
||||||
|
}
|
||||||
|
|
||||||
|
class "Database" <<Database>> {
|
||||||
|
+ exchanges
|
||||||
|
+ __init__(exchanges)
|
||||||
|
+ execute_sql(sql)
|
||||||
|
+ get_item_where(item_name, table_name, filter_vals)
|
||||||
|
+ get_rows_where(table, filter_vals)
|
||||||
|
+ insert_dataframe(df, table)
|
||||||
|
+ insert_row(table, columns, values)
|
||||||
|
+ _table_exists(table_name)
|
||||||
|
+ _populate_table(table_name, start_time, ex_details, end_time=None)
|
||||||
|
+ _fetch_exchange_id(exchange_name)
|
||||||
|
+ _fetch_market_id(symbol, exchange_name)
|
||||||
|
+ _insert_candles_into_db(candlesticks, table_name, symbol, exchange_name)
|
||||||
|
+ get_records_since(table_name, st, et, rl, ex_details)
|
||||||
|
+ _get_records(table_name, st, et=None)
|
||||||
|
+ _fetch_candles_from_exchange(symbol, interval, exchange_name, user_name, start_datetime=None, end_datetime=None)
|
||||||
|
+ get_from_static_table(item, table, indexes, create_id=False)
|
||||||
|
}
|
||||||
|
|
||||||
|
class "ExchangeInterface" <<ExchangeInterface>> {
|
||||||
|
+ exchange_data
|
||||||
|
+ available_exchanges
|
||||||
|
--
|
||||||
|
+ __init__()
|
||||||
|
+ connect_exchange(exchange_name, user_name, api_keys=None)
|
||||||
|
+ add_exchange(user_name, _class, arg)
|
||||||
|
+ get_exchange(ename, uname)
|
||||||
|
+ get_connected_exchanges(user_name)
|
||||||
|
+ get_available_exchanges()
|
||||||
|
+ get_exchange_balances(name)
|
||||||
|
+ get_all_balances(name)
|
||||||
|
+ get_order(symbol, order_id, target, user_name)
|
||||||
|
+ get_trade_status(trade, user_name)
|
||||||
|
+ get_trade_executed_qty(trade, user_name)
|
||||||
|
+ get_trade_executed_price(trade, user_name)
|
||||||
|
+ get_price(symbol, price_source=None)
|
||||||
|
}
|
||||||
|
|
||||||
|
class "Indicators" <<DataCache>> {
|
||||||
|
+ get_indicators(user_name)
|
||||||
|
+ get_indicator_data(user_name, source, start_ts, num_results)
|
||||||
|
}
|
||||||
|
|
||||||
|
class "Strategies" <<DataCache>> {
|
||||||
|
+ get_strategies(user_name)
|
||||||
|
+ run_strategy(strategy_name, user_name)
|
||||||
|
}
|
||||||
|
|
||||||
|
class "Backtester" <<DataCache>> {
|
||||||
|
+ run_backtest(strategy_name, user_name)
|
||||||
|
}
|
||||||
|
|
||||||
|
class "Signals" <<Config>> {
|
||||||
|
+ generate_signals(strategy_name, user_name)
|
||||||
|
}
|
||||||
|
|
||||||
|
class "Trades" <<DataCache>> {
|
||||||
|
+ execute_trade(trade_details, user_name)
|
||||||
|
}
|
||||||
|
|
||||||
|
class "HDict" <<Database>> {
|
||||||
|
}
|
||||||
|
|
||||||
|
class "SQLite" <<Database>> {
|
||||||
|
}
|
||||||
|
|
||||||
|
class "shared_utilities" <<Candles>> {
|
||||||
|
}
|
||||||
|
|
||||||
|
class "ArrayList" <<ExchangeInterface>> {
|
||||||
|
}
|
||||||
|
|
||||||
|
app --> "index()" : "index()"
|
||||||
|
app --> "ws(socket_conn)" : "ws(socket_conn)"
|
||||||
|
app --> "settings()" : "settings()"
|
||||||
|
app --> "history()" : "history()"
|
||||||
|
app --> "signup()" : "signup()"
|
||||||
|
app --> "signout()" : "signout()"
|
||||||
|
app --> "login()" : "login()"
|
||||||
|
app --> "signup_submit()" : "signup_submit()"
|
||||||
|
app --> "indicator_init()" : "indicator_init()"
|
||||||
|
|
||||||
"signup_submit()" --> "BrighterTrades" : "create_new_user()"
|
"signup_submit()" --> "BrighterTrades" : "create_new_user()"
|
||||||
"history()" --> "BrighterTrades" : get_user_info()
|
"history()" --> "BrighterTrades" : get_user_info()
|
||||||
|
|
@ -90,90 +216,6 @@ class "Flask" {
|
||||||
"BrighterTrades" -- "SQLite"
|
"BrighterTrades" -- "SQLite"
|
||||||
"BrighterTrades" -- "HDict"
|
"BrighterTrades" -- "HDict"
|
||||||
|
|
||||||
class "Users" {
|
|
||||||
+ data_cache
|
|
||||||
}
|
|
||||||
|
|
||||||
class "Configuration" {
|
|
||||||
+ exchanges
|
|
||||||
+ indicators
|
|
||||||
+ users
|
|
||||||
+ __init__(exchanges, indicators, users)
|
|
||||||
+ get_exchanges()
|
|
||||||
+ get_indicators()
|
|
||||||
+ get_users()
|
|
||||||
+ add_exchange(exchange)
|
|
||||||
+ remove_exchange(exchange)
|
|
||||||
+ add_indicator(indicator)
|
|
||||||
+ remove_indicator(indicator)
|
|
||||||
+ add_user(user)
|
|
||||||
+ remove_user(user)
|
|
||||||
}
|
|
||||||
|
|
||||||
class "Candles" {
|
|
||||||
+ __init__(exchanges, config_obj, database)
|
|
||||||
+ get_last_n_candles(num_candles, asset, timeframe, exchange, user_name)
|
|
||||||
+ set_new_candle(cdata)
|
|
||||||
+ set_cache(symbol=None, interval=None, exchange_name=None, user_name=None)
|
|
||||||
+ get_latestvalues(value_name, symbol, timeframe, exchange, user_name, num_record=1)
|
|
||||||
+ convert_candles(candles)
|
|
||||||
+ get_candle_history(num_records, symbol=None, interval=None, exchange_name=None, user_name=None)
|
|
||||||
}
|
|
||||||
|
|
||||||
class "DataCache" {
|
|
||||||
+ db
|
|
||||||
+ get_records_since(key, start_datetime, record_length, ex_details)
|
|
||||||
+ cache_exists(key)
|
|
||||||
+ update_candle_cache(more_records, key)
|
|
||||||
+ get_cached_candles(key)
|
|
||||||
+ set_cached_candles(candles, key)
|
|
||||||
+ clear_cache()
|
|
||||||
+ get_cache_info()
|
|
||||||
+ remove_expired_records()
|
|
||||||
+ remove_cache(key)
|
|
||||||
+ remove_all_caches()
|
|
||||||
}
|
|
||||||
|
|
||||||
class "Database" {
|
|
||||||
+ exchanges
|
|
||||||
+ __init__(exchanges)
|
|
||||||
+ execute_sql(sql)
|
|
||||||
+ get_item_where(item_name, table_name, filter_vals)
|
|
||||||
+ get_rows_where(table, filter_vals)
|
|
||||||
+ insert_dataframe(df, table)
|
|
||||||
+ insert_row(table, columns, values)
|
|
||||||
+ _table_exists(table_name)
|
|
||||||
+ _populate_table(table_name, start_time, ex_details, end_time=None)
|
|
||||||
+ _fetch_exchange_id(exchange_name)
|
|
||||||
+ _fetch_market_id(symbol, exchange_name)
|
|
||||||
+ _insert_candles_into_db(candlesticks, table_name, symbol, exchange_name)
|
|
||||||
+ get_records_since(table_name, st, et, rl, ex_details)
|
|
||||||
+ _get_records(table_name, st, et=None)
|
|
||||||
+ _fetch_candles_from_exchange(symbol, interval, exchange_name, user_name, start_datetime=None, end_datetime=None)
|
|
||||||
+ get_from_static_table(item, table, indexes, create_id=False)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class "ExchangeInterface" {
|
|
||||||
+ exchange_data
|
|
||||||
+ available_exchanges
|
|
||||||
--
|
|
||||||
+ __init__()
|
|
||||||
+ connect_exchange(exchange_name, user_name, api_keys=None)
|
|
||||||
+ add_exchange(user_name, _class, arg)
|
|
||||||
+ get_exchange(ename, uname)
|
|
||||||
+ get_connected_exchanges(user_name)
|
|
||||||
+ get_available_exchanges()
|
|
||||||
+ get_exchange_balances(name)
|
|
||||||
+ get_all_balances(name)
|
|
||||||
+ get_order(symbol, order_id, target, user_name)
|
|
||||||
+ get_trade_status(trade, user_name)
|
|
||||||
+ get_trade_executed_qty(trade, user_name)
|
|
||||||
+ get_trade_executed_price(trade, user_name)
|
|
||||||
+ get_price(symbol, price_source=None)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
"Configuration" -- "Signals"
|
"Configuration" -- "Signals"
|
||||||
"Configuration" -- "Indicators"
|
"Configuration" -- "Indicators"
|
||||||
"Configuration" -- "Users"
|
"Configuration" -- "Users"
|
||||||
|
|
@ -189,9 +231,8 @@ class "ExchangeInterface" {
|
||||||
"ExchangeInterface" -- "ArrayList"
|
"ExchangeInterface" -- "ArrayList"
|
||||||
"ExchangeInterface" -- "DataCache"
|
"ExchangeInterface" -- "DataCache"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@enduml
|
@enduml
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
@ -4,6 +4,14 @@
|
||||||
|
|
||||||
left to right direction
|
left to right direction
|
||||||
skinparam packageStyle rectangle
|
skinparam packageStyle rectangle
|
||||||
|
skinparam usecase {
|
||||||
|
BackgroundColor lightblue
|
||||||
|
BorderColor black
|
||||||
|
FontColor darkblue
|
||||||
|
FontSize 16
|
||||||
|
RoundCorner 20
|
||||||
|
}
|
||||||
|
title Use Case Low Detail Overview
|
||||||
|
|
||||||
actor "User Interface" as User
|
actor "User Interface" as User
|
||||||
rectangle "Flask App" as App {
|
rectangle "Flask App" as App {
|
||||||
|
|
@ -33,6 +41,14 @@ rectangle "Flask App" as App {
|
||||||
|
|
||||||
left to right direction
|
left to right direction
|
||||||
skinparam packageStyle rectangle
|
skinparam packageStyle rectangle
|
||||||
|
skinparam usecase {
|
||||||
|
BackgroundColor lightblue
|
||||||
|
BorderColor black
|
||||||
|
FontColor darkblue
|
||||||
|
FontSize 16
|
||||||
|
RoundCorner 20
|
||||||
|
}
|
||||||
|
title Use Case Medium Detail Overview
|
||||||
|
|
||||||
actor "User Interface" as User
|
actor "User Interface" as User
|
||||||
rectangle "Flask App" as App {
|
rectangle "Flask App" as App {
|
||||||
|
|
@ -73,6 +89,14 @@ rectangle "Flask App" as App {
|
||||||
|
|
||||||
left to right direction
|
left to right direction
|
||||||
skinparam packageStyle rectangle
|
skinparam packageStyle rectangle
|
||||||
|
skinparam usecase {
|
||||||
|
BackgroundColor lightblue
|
||||||
|
BorderColor black
|
||||||
|
FontColor darkblue
|
||||||
|
FontSize 16
|
||||||
|
RoundCorner 20
|
||||||
|
}
|
||||||
|
title Use Case View Homepage
|
||||||
|
|
||||||
actor "User Interface" as User
|
actor "User Interface" as User
|
||||||
rectangle "Flask App" as App {
|
rectangle "Flask App" as App {
|
||||||
|
|
@ -106,16 +130,23 @@ rectangle "Flask App" as App {
|
||||||
|
|
||||||
@enduml
|
@enduml
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
### Sequence Request Homepage
|
### Sequence Request Homepage
|
||||||
```plantuml
|
```plantuml
|
||||||
@startuml
|
@startuml
|
||||||
|
skinparam participant {
|
||||||
|
BackgroundColor lightblue
|
||||||
|
BorderColor black
|
||||||
|
FontColor darkblue
|
||||||
|
}
|
||||||
|
title Sequence Request Homepage
|
||||||
|
|
||||||
actor "User Interface" as User
|
actor "User Interface" as User
|
||||||
participant App as "Flask App"
|
participant "Flask App" as App
|
||||||
participant BrighterTrades as "BrighterTrades"
|
participant "BrighterTrades" as BrighterTrades
|
||||||
participant Config as "Config"
|
participant "Config" as Config
|
||||||
participant UserStorage as "User Storage"
|
participant "User Storage" as UserStorage
|
||||||
|
|
||||||
User -> App: Request Homepage
|
User -> App: Request Homepage
|
||||||
App -> BrighterTrades: Create BrighterTrades object
|
App -> BrighterTrades: Create BrighterTrades object
|
||||||
|
|
@ -129,13 +160,27 @@ App --> User: Serve Homepage
|
||||||
|
|
||||||
@enduml
|
@enduml
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
### Use Case Change Settings:
|
### Use Case Change Settings:
|
||||||
```plantuml
|
```plantuml
|
||||||
@startuml
|
@startuml
|
||||||
|
title Use Case Change Settings
|
||||||
|
|
||||||
left to right direction
|
left to right direction
|
||||||
skinparam packageStyle rectangle
|
skinparam packageStyle rectangle
|
||||||
|
skinparam usecase {
|
||||||
|
BackgroundColor lightblue
|
||||||
|
BorderColor black
|
||||||
|
FontColor darkblue
|
||||||
|
FontSize 16
|
||||||
|
}
|
||||||
|
skinparam actor {
|
||||||
|
BackgroundColor lightgreen
|
||||||
|
BorderColor black
|
||||||
|
FontColor darkblue
|
||||||
|
FontSize 16
|
||||||
|
}
|
||||||
|
|
||||||
actor "User Interface" as User
|
actor "User Interface" as User
|
||||||
rectangle "Flask App" as App {
|
rectangle "Flask App" as App {
|
||||||
|
|
@ -153,10 +198,22 @@ rectangle "Flask App" as App {
|
||||||
|
|
||||||
@enduml
|
@enduml
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
### Sequence Change Settings
|
### Sequence Change Settings
|
||||||
```plantuml
|
```plantuml
|
||||||
@startuml
|
@startuml
|
||||||
|
title Sequence Change Settings
|
||||||
|
|
||||||
|
skinparam sequence {
|
||||||
|
ActorBackgroundColor lightgreen
|
||||||
|
ParticipantBackgroundColor lightblue
|
||||||
|
ActorBorderColor black
|
||||||
|
ParticipantBorderColor black
|
||||||
|
ActorFontColor darkblue
|
||||||
|
ParticipantFontColor darkblue
|
||||||
|
FontSize 14
|
||||||
|
}
|
||||||
|
|
||||||
actor "User Interface" as User
|
actor "User Interface" as User
|
||||||
participant App as "Flask App"
|
participant App as "Flask App"
|
||||||
|
|
@ -171,13 +228,18 @@ App --> User: Redirect to Homepage
|
||||||
|
|
||||||
@enduml
|
@enduml
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
### Use Case Fetch Candle History:
|
### Use Case Fetch Candle History:
|
||||||
```plantuml
|
```plantuml
|
||||||
@startuml
|
@startuml
|
||||||
|
|
||||||
left to right direction
|
left to right direction
|
||||||
skinparam packageStyle rectangle
|
skinparam packageStyle rectangle
|
||||||
|
skinparam usecase {
|
||||||
|
BackgroundColor lightblue
|
||||||
|
BorderColor black
|
||||||
|
FontColor darkblue
|
||||||
|
}
|
||||||
|
|
||||||
actor "User Interface" as User
|
actor "User Interface" as User
|
||||||
rectangle "Flask App" as App {
|
rectangle "Flask App" as App {
|
||||||
|
|
@ -195,10 +257,16 @@ rectangle "Flask App" as App {
|
||||||
|
|
||||||
@enduml
|
@enduml
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
### Sequence Request candle history
|
### Sequence Request candle history
|
||||||
```plantuml
|
```plantuml
|
||||||
@startuml
|
@startuml
|
||||||
|
skinparam participant {
|
||||||
|
BackgroundColor lightblue
|
||||||
|
BorderColor black
|
||||||
|
FontColor darkblue
|
||||||
|
}
|
||||||
|
|
||||||
actor "User Interface" as User
|
actor "User Interface" as User
|
||||||
participant App as "Flask App"
|
participant App as "Flask App"
|
||||||
|
|
@ -215,31 +283,41 @@ App --> User: Serve Candle History
|
||||||
|
|
||||||
@enduml
|
@enduml
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
### Sequence Initialize Indicators:
|
### Sequence Initialize Indicators:
|
||||||
```plantuml
|
```plantuml
|
||||||
@startuml
|
@startuml
|
||||||
|
skinparam participant {
|
||||||
|
BackgroundColor lightblue
|
||||||
|
BorderColor black
|
||||||
|
FontColor darkblue
|
||||||
|
}
|
||||||
|
|
||||||
actor "User Interface"
|
actor "User Interface" as User
|
||||||
|
|
||||||
|
User -> app: Requests initialized indicators
|
||||||
"User Interface" -> app: Requests initialized indicators
|
|
||||||
activate app #005500
|
activate app #005500
|
||||||
app -> Indicators: initialize indicators
|
app -> Indicators: initialize indicators
|
||||||
activate Indicators #005500
|
activate Indicators #005500
|
||||||
Indicators -> app: return initialized indicators
|
Indicators -> app: return initialized indicators
|
||||||
deactivate Indicators
|
deactivate Indicators
|
||||||
|
|
||||||
app -> "User Interface": Returns initialized indicators
|
app -> User: Returns initialized indicators
|
||||||
deactivate app
|
deactivate app
|
||||||
|
|
||||||
@enduml
|
@enduml
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
### Sequence Sign in:
|
### Sequence Sign in:
|
||||||
```plantuml
|
```plantuml
|
||||||
@startuml
|
@startuml
|
||||||
|
skinparam participant {
|
||||||
|
BackgroundColor lightblue
|
||||||
|
BorderColor black
|
||||||
|
FontColor darkblue
|
||||||
|
}
|
||||||
actor "User Interface"
|
actor "User Interface"
|
||||||
|
|
||||||
"User Interface" -> app: requests "Sign In"
|
"User Interface" -> app: requests "Sign In"
|
||||||
|
|
@ -259,7 +337,11 @@ deactivate app
|
||||||
### Sequence Sign up:
|
### Sequence Sign up:
|
||||||
```plantuml
|
```plantuml
|
||||||
@startuml
|
@startuml
|
||||||
|
skinparam participant {
|
||||||
|
BackgroundColor lightblue
|
||||||
|
BorderColor black
|
||||||
|
FontColor darkblue
|
||||||
|
}
|
||||||
actor "User Interface" as User
|
actor "User Interface" as User
|
||||||
|
|
||||||
User -> app: send "Sign Up" request
|
User -> app: send "Sign Up" request
|
||||||
|
|
@ -279,7 +361,11 @@ deactivate app
|
||||||
### Sequence Sign out:
|
### Sequence Sign out:
|
||||||
```plantuml
|
```plantuml
|
||||||
@startuml
|
@startuml
|
||||||
|
skinparam participant {
|
||||||
|
BackgroundColor lightblue
|
||||||
|
BorderColor black
|
||||||
|
FontColor darkblue
|
||||||
|
}
|
||||||
actor "User Interface" as User
|
actor "User Interface" as User
|
||||||
|
|
||||||
User -> app: send "Sign Out" request
|
User -> app: send "Sign Out" request
|
||||||
29
src/app.py
29
src/app.py
|
|
@ -24,10 +24,19 @@ CORS_HEADERS = 'Content-Type'
|
||||||
app.config.from_object(__name__)
|
app.config.from_object(__name__)
|
||||||
app.secret_key = '1_BAD_secrete_KEY_is_not_2'
|
app.secret_key = '1_BAD_secrete_KEY_is_not_2'
|
||||||
|
|
||||||
# Enable cross resources.
|
# Enable cross-origin resource sharing for specific endpoints
|
||||||
cors = CORS(app, supports_credentials=True,
|
cors = CORS(app, supports_credentials=True,
|
||||||
resources=[r'/api/history', r'/api/indicator_init'],
|
resources={
|
||||||
origins=[r'http://127.0.0.1:5000'])
|
r"/api/history": {"origins": ["http://127.0.0.1:5000", "http://localhost:5000"]},
|
||||||
|
r"/api/indicator_init": {"origins": ["http://127.0.0.1:5000", "http://localhost:5000"]}
|
||||||
|
},
|
||||||
|
headers=['Content-Type'])
|
||||||
|
|
||||||
|
|
||||||
|
@app.after_request
|
||||||
|
def add_cors_headers(response):
|
||||||
|
response.headers['Access-Control-Allow-Credentials'] = 'true'
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
|
|
@ -159,18 +168,23 @@ def settings():
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/history', methods=['POST', 'GET'])
|
@app.route('/api/history', methods=['POST', 'GET'])
|
||||||
# @cross_origin(supports_credentials=True)
|
|
||||||
def history():
|
def history():
|
||||||
"""
|
"""
|
||||||
Fetches the candle history of a specific trading pair and timeframe.
|
Fetches the candle history of a specific trading pair and timeframe.
|
||||||
Currently, set to last 1000 candles.
|
Currently, set to last 1000 candles.
|
||||||
:return: json - price history
|
:return: json - price history
|
||||||
"""
|
"""
|
||||||
|
try:
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
|
if not data:
|
||||||
|
raise ValueError("No JSON data received")
|
||||||
|
|
||||||
username = data.get('user_name')
|
username = data.get('user_name')
|
||||||
|
|
||||||
# Return if the user is not logged in.
|
# Return if the user is not logged in.
|
||||||
if not username:
|
if not username:
|
||||||
return {} # redirect('/')
|
# redirect('/')
|
||||||
|
return jsonify({'error': 'User not logged in.'}), 401
|
||||||
|
|
||||||
print('[RECEIVED PRICE HISTORY REQUEST] - user', username)
|
print('[RECEIVED PRICE HISTORY REQUEST] - user', username)
|
||||||
|
|
||||||
|
|
@ -181,7 +195,10 @@ def history():
|
||||||
info='Candle History', num_records=1000, chart_view=chart_view, user_name=username)
|
info='Candle History', num_records=1000, chart_view=chart_view, user_name=username)
|
||||||
|
|
||||||
print('[SENDING PRICE HISTORY TO CLIENT]', payload.tail(2))
|
print('[SENDING PRICE HISTORY TO CLIENT]', payload.tail(2))
|
||||||
return jsonify(payload.to_dict('records'))
|
return jsonify(payload.to_dict('records')), 200
|
||||||
|
except Exception as e:
|
||||||
|
print(f'Error in history endpoint: {e}')
|
||||||
|
return jsonify({'error': str(e)}), 500
|
||||||
|
|
||||||
|
|
||||||
# @app.route('/saved_data')
|
# @app.route('/saved_data')
|
||||||
|
|
|
||||||
|
|
@ -2,4 +2,4 @@ BINANCE_API_KEY = 'rkp1Xflb5nnwt6jys0PG27KXcqwn0q9lKCLryKcSp4mKW2UOlkPRuAHPg45rQ
|
||||||
BINANCE_API_SECRET = 'DiFhhYhF64nkPe5f3V7TRJX2bSVA7ZQZlozSdX7O7uYmBMdK985eA6Kp2B2zKvbK'
|
BINANCE_API_SECRET = 'DiFhhYhF64nkPe5f3V7TRJX2bSVA7ZQZlozSdX7O7uYmBMdK985eA6Kp2B2zKvbK'
|
||||||
ALPACA_API_KEY = 'PKN0WFYT9VZYUVRBG1HM'
|
ALPACA_API_KEY = 'PKN0WFYT9VZYUVRBG1HM'
|
||||||
ALPACA_API_SECRET = '0C1I6UcBSR2B0SZrBC3DoKGtcglAny8znorvganx'
|
ALPACA_API_SECRET = '0C1I6UcBSR2B0SZrBC3DoKGtcglAny8znorvganx'
|
||||||
DB_FILE = "C:/Users/Rob/PycharmProjects/BrighterTrading/BrighterTrading.db"
|
DB_FILE = "C:/Users/Rob/PycharmProjects/BrighterTrading/data/BrighterTrading.db"
|
||||||
|
|
|
||||||
|
|
@ -427,36 +427,35 @@ class Database:
|
||||||
quote_volume, num_trades, taker_buy_base_volume, taker_buy_quote_volume]
|
quote_volume, num_trades, taker_buy_base_volume, taker_buy_quote_volume]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def fill_data_holes(records):
|
def fill_data_holes(records, interval):
|
||||||
time_span = timeframe_to_minutes(interval)
|
time_span = timeframe_to_minutes(interval)
|
||||||
last_timestamp = None
|
last_timestamp = None
|
||||||
# Iterate through the timestamps in all the records.
|
filled_records = []
|
||||||
for time_stamp in records.open_time:
|
|
||||||
|
for _, row in records.iterrows():
|
||||||
|
time_stamp = row['open_time']
|
||||||
|
|
||||||
if last_timestamp is None:
|
if last_timestamp is None:
|
||||||
# Record this time_stamp.
|
|
||||||
last_timestamp = time_stamp
|
last_timestamp = time_stamp
|
||||||
# Skip the first iteration.
|
filled_records.append(row)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Get the time difference between current and last time_stamps in minutes.
|
|
||||||
delta_ms = time_stamp - last_timestamp
|
delta_ms = time_stamp - last_timestamp
|
||||||
delta_minutes = (delta_ms / 1000) / 60
|
delta_minutes = (delta_ms / 1000) / 60
|
||||||
# If the difference exceeds the span of a single record.
|
|
||||||
if delta_minutes > time_span:
|
if delta_minutes > time_span:
|
||||||
# Calculate how many records are missing.
|
num_missing_rec = int(delta_minutes / time_span)
|
||||||
num_missing_rec = (delta_minutes / time_span)
|
|
||||||
# Create the missing records
|
|
||||||
step = int(delta_ms / num_missing_rec)
|
step = int(delta_ms / num_missing_rec)
|
||||||
# loop from the last timestamp + step until the current timestamp.
|
|
||||||
for ts in range(last_timestamp + step, time_stamp, step):
|
for ts in range(int(last_timestamp) + step, int(time_stamp), step):
|
||||||
# Copy the current row and append it with all the missing timestamps.
|
new_row = row.copy()
|
||||||
row = records.loc[records['open_time'] == time_stamp]
|
new_row['open_time'] = ts
|
||||||
row.open_time = ts
|
filled_records.append(new_row)
|
||||||
records = records.append(row, ignore_index=True)
|
|
||||||
# Remember the time_stamp.
|
filled_records.append(row)
|
||||||
last_timestamp = time_stamp
|
last_timestamp = time_stamp
|
||||||
return records
|
|
||||||
|
return pd.DataFrame(filled_records)
|
||||||
|
|
||||||
# Default start date for fetching from the exchange_name.
|
# Default start date for fetching from the exchange_name.
|
||||||
if start_datetime is None:
|
if start_datetime is None:
|
||||||
|
|
@ -494,5 +493,5 @@ class Database:
|
||||||
if num_rec_records < estimated_num_records:
|
if num_rec_records < estimated_num_records:
|
||||||
# Some records may be missing due to server maintenance periods ect.
|
# Some records may be missing due to server maintenance periods ect.
|
||||||
# Fill the holes with copies of the last record received before the gap.
|
# Fill the holes with copies of the last record received before the gap.
|
||||||
candles = fill_data_holes(candles)
|
candles = fill_data_holes(candles, interval)
|
||||||
return candles
|
return candles
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 210 B After Width: | Height: | Size: 210 B |
|
Before Width: | Height: | Size: 129 KiB After Width: | Height: | Size: 129 KiB |
|
|
@ -60,7 +60,7 @@ class Comms {
|
||||||
*/
|
*/
|
||||||
async getPriceHistory(userName) {
|
async getPriceHistory(userName) {
|
||||||
try {
|
try {
|
||||||
const response = await fetch('http://localhost:5000/api/history', {
|
const response = await fetch('http://127.0.0.1:5000/api/history', {
|
||||||
credentials: 'include',
|
credentials: 'include',
|
||||||
mode: 'cors',
|
mode: 'cors',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
|
@ -68,6 +68,10 @@ class Comms {
|
||||||
body: JSON.stringify({ "user_name": userName })
|
body: JSON.stringify({ "user_name": userName })
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP error! Status: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
console.log('Communication[56]: Received candles from the server:');
|
console.log('Communication[56]: Received candles from the server:');
|
||||||
console.log(data);
|
console.log(data);
|
||||||
|
|
@ -77,6 +81,7 @@ class Comms {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches the Indicator data for a specific user.
|
* Fetches the Indicator data for a specific user.
|
||||||
* @param {string} userName - The name of the user.
|
* @param {string} userName - The name of the user.
|
||||||
|
|
@ -31,8 +31,18 @@ class Data {
|
||||||
//Request historical price data from the server.
|
//Request historical price data from the server.
|
||||||
this.price_history = this.comms.getPriceHistory(this.user_name);
|
this.price_history = this.comms.getPriceHistory(this.user_name);
|
||||||
|
|
||||||
//last price from price history.
|
// Last price from price history.
|
||||||
this.price_history.then((value) => { this.last_price = value[value.length-1].close; });
|
this.price_history.then((value) => {
|
||||||
|
if (value && value.length > 0) {
|
||||||
|
this.last_price = value[value.length - 1].close;
|
||||||
|
} else {
|
||||||
|
console.error('Received empty price history data');
|
||||||
|
this.last_price = null;
|
||||||
|
}
|
||||||
|
}).catch((error) => {
|
||||||
|
console.error('Error processing price history:', error);
|
||||||
|
this.last_price = null;
|
||||||
|
});
|
||||||
|
|
||||||
// Request from the server initialization data for the indicators.
|
// Request from the server initialization data for the indicators.
|
||||||
this.indicator_data = this.comms.getIndicatorData(this.user_name);
|
this.indicator_data = this.comms.getIndicatorData(this.user_name);
|
||||||
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
Loading…
Reference in New Issue