Fixed issue with fetching historical data and added missing imports.

This commit is contained in:
Rob 2024-07-26 03:52:24 -03:00
parent 49c908357f
commit 0bb9780ff6
47 changed files with 695 additions and 321 deletions

0
BrighterTrading.db Normal file
View File

View File

@ -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
```

375
markdown/App/App.md Normal file
View File

@ -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&#8203;</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.&#8203;
end legend
start
:Return rendered signup page&#8203;;
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,&#8203;
validating email, creating new user,
and redirecting to homepage.
end legend
start
:Receive form data;
:Extract email, username, and password&#8203;;
: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&#8203;
details, and returns data response.&#8203;
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
```

View File

@ -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
``` ```

View File

@ -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

View File

@ -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')

View File

@ -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"

View File

@ -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

View File

Before

Width:  |  Height:  |  Size: 210 B

After

Width:  |  Height:  |  Size: 210 B

View File

Before

Width:  |  Height:  |  Size: 129 KiB

After

Width:  |  Height:  |  Size: 129 KiB

View File

@ -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.

View File

@ -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);

View File

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB