astacn commited on
Commit
c037f49
·
verified ·
1 Parent(s): 1dd65a2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +75 -127
app.py CHANGED
@@ -2,165 +2,113 @@ from flask import Flask, request, jsonify
2
  import pandas as pd
3
  import numpy as np
4
  import baostock as bs
5
- from sklearn.preprocessing import MinMaxScaler, StandardScaler
6
  from sklearn.model_selection import train_test_split
7
- from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, mean_absolute_error
8
  from neuralprophet import NeuralProphet, set_log_level
9
- from torch.optim import Adam
10
- from torch.nn import LSTM
11
  import torch
12
  import torch.nn as nn
 
13
  import os
14
 
15
-
16
  app = Flask(__name__)
17
 
18
- # Set log level to ERROR to suppress unnecessary warnings
19
  set_log_level("ERROR")
20
 
21
- # Baostock API settings
22
- bs.login()
 
 
23
 
24
  # Collect historical data
25
- data = bs.query_history_k_data_plus(
26
- "sz.000001", # Shanghai Composite Index
27
- "date,open,high,low,close,volume",
28
- start_date="2005-05-30",
29
- end_date="2024-01-31",
30
- frequency="d"
31
- )
32
-
33
- # Convert ResultData object to pandas DataFrame
34
- data_list = []
35
- while (data.error_code == '0') & data.next():
36
- # 获取一条记录,将记录合并在一起
37
- data_list.append(data.get_row_data())
38
- data_df = pd.DataFrame(data_list, columns=data.fields)
39
-
40
- # Convert 'open' and 'close' columns to numeric type
41
- data_df['open'] = pd.to_numeric(data_df['open'])
42
- data_df['close'] = pd.to_numeric(data_df['close'])
43
-
44
- # Filter out stocks that meet the conditions
45
- data_df = data_df[(data_df["open"] >= 0.98 * data_df["close"].shift(1).fillna(0)) & (data_df["open"] <= 1.02 * data_df["close"].shift(1).fillna(0))]
46
- data_df = data_df[(data_df["high"] == data_df["close"]) & (data_df["low"] == data_df["close"])] # limit-up condition
47
- data_df = data_df[(data_df["open"]!= 0) & (data_df["close"]!= 0)] # exclude zero prices
48
-
49
- # Check if data_df is empty before proceeding
50
- if data_df.empty:
51
- print("Warning: data_df is empty after filtering. Check your filtering conditions.")
52
- else:
53
- # Now use data_df (the DataFrame) in train_test_split
54
- train_data, val_data = train_test_split(data_df, test_size=0.2, random_state=42)
55
-
56
- # Define the custom model
 
 
 
 
57
  class CustomModel(nn.Module):
58
  def __init__(self):
59
  super(CustomModel, self).__init__()
60
  self.neural_prophet = NeuralProphet(
61
  n_forecasts=1,
62
- n_lags=30,
63
- n_changepoints=10,
64
- changepoints_range=0.8,
65
  learning_rate=1e-3,
66
  optimizer=Adam,
67
  )
68
- self.lstm = LSTM(input_size=1, hidden_size=128, num_layers=1, batch_first=True)
69
-
70
- def forward(self, x):
71
- x = self.neural_prophet(x)
72
- x = self.lstm(x)
73
- return x
74
 
75
  def predict(self, df):
76
- """
77
- Custom predict method for CustomModel. Utilizes NeuralProphet's prediction.
78
-
79
- Args:
80
- df: The input DataFrame for prediction.
81
-
82
- Returns:
83
- Predictions from the NeuralProphet model.
84
- """
85
- # Assuming your NeuralProphet model expects a DataFrame in a specific format
86
- # You might need to adjust this based on your data and model setup
87
- future = self.neural_prophet.make_future_dataframe(df, periods=1) # Adjust periods as needed
88
  forecast = self.neural_prophet.predict(future)
89
- return forecast['yhat1'].values # Or access the relevant prediction column
90
 
91
- # Instantiate the model
92
  model = CustomModel()
93
 
94
- # Define loss function and optimizer
95
- criterion = nn.BCELoss()
96
- optimizer = Adam(model.parameters(), lr=1e-3)
97
-
98
- # Training loop
99
- def fit(model, train_data, epochs, batch_size, validation_data):
100
- """
101
- Custom training loop for the CustomModel.
102
-
103
- Args:
104
- model: The CustomModel instance.
105
- train_data: Training data.
106
- epochs: Number of training epochs.
107
- batch_size: Batch size for training.
108
- validation_data: Validation data.
109
- """
110
- for epoch in range(epochs):
111
- model.train() # Set model to training mode
112
- for batch_idx, (data, target) in enumerate(train_data): # Assuming train_data is a DataLoader
113
- optimizer.zero_grad() # Zero the gradients
114
- output = model(data) # Forward pass
115
- loss = criterion(output, target) # Calculate loss
116
- loss.backward() # Backpropagate gradients
117
- optimizer.step() # Update model parameters
118
-
119
- # Print training progress
120
- if batch_idx % 100 == 0:
121
- pass Load the prediction model
122
- model = CustomModel()
123
-
124
- # Define a function to prepare the data for prediction
125
  def prepare_data(date):
126
- # Get the historical data for the given date
127
- data = bs.query_history_k_data_plus(
128
- "sz.000001", # Shanghai Composite Index
129
- "date,open,high,low,close,volume",
130
- start_date="2005-05-30",
131
- end_date=date,
132
- frequency="d"
133
- )
134
- data_list = []
135
- while (data.error_code == '0') & data.next():
136
- data_list.append(data.get_row_data())
137
- data_df = pd.DataFrame(data_list, columns=data.fields)
138
-
139
- # Convert 'open' and 'close' columns to numeric type
140
- data_df['open'] = pd.to_numeric(data_df['open'])
141
- data_df['close'] = pd.to_numeric(data_df['close'])
142
-
143
- # Filter out stocks that meet the conditions
144
- data_df = data_df[(data_df["open"] >= 0.98 * data_df["close"].shift(1).fillna(0)) & (data_df["open"] <= 1.02 * data_df["close"].shift(1).fillna(0))]
145
- data_df = data_df[(data_df["high"] == data_df["close"]) & (data_df["low"] == data_df["close"])] # limit-up condition
146
- data_df = data_df[(data_df["open"]!= 0) & (data_df["close"]!= 0)] # exclude zero prices
147
 
148
  # Scale the data using MinMaxScaler
149
  scaler = MinMaxScaler()
150
- data_df[['open', 'high', 'low', 'close', 'volume']] = scaler.fit_transform(data_df[['open', 'high', 'low', 'close', 'volume']])
151
-
152
- return data_df
153
 
154
  # Define a route to predict the top 5 stock codes
155
  @app.route('/predict', methods=['POST'])
156
  def predict():
157
- date = request.json['date']
158
- data_df = prepare_data(date)
159
- if data_df.empty:
160
- return jsonify({'error': 'No data available for the given date'}), 400
161
- y_pred = model.predict(data_df)
162
- top_5_stocks = predict_stock_codes(y_pred, data_df)
163
- return jsonify({'top_5_stocks': top_5_stocks})
164
-
 
 
 
 
 
165
  if __name__ == '__main__':
166
- app.run(debug=True)
 
 
 
 
2
  import pandas as pd
3
  import numpy as np
4
  import baostock as bs
5
+ from sklearn.preprocessing import MinMaxScaler
6
  from sklearn.model_selection import train_test_split
7
+ from sklearn.metrics import mean_absolute_error
8
  from neuralprophet import NeuralProphet, set_log_level
 
 
9
  import torch
10
  import torch.nn as nn
11
+ from torch.optim import Adam
12
  import os
13
 
14
+ # Initialize Flask app
15
  app = Flask(__name__)
16
 
17
+ # Set log level to suppress unnecessary warnings
18
  set_log_level("ERROR")
19
 
20
+ # Baostock API login
21
+ lg = bs.login()
22
+ if lg.error_code != '0':
23
+ raise ConnectionError(f"Baostock login failed. Error code: {lg.error_code}, Error message: {lg.error_msg}")
24
 
25
  # Collect historical data
26
+ def get_historical_data(start_date, end_date):
27
+ data = bs.query_history_k_data_plus(
28
+ "sz.000001", # Shanghai Composite Index
29
+ "date,open,high,low,close,volume",
30
+ start_date=start_date,
31
+ end_date=end_date,
32
+ frequency="d"
33
+ )
34
+ if data.error_code != '0':
35
+ raise ValueError(f"Error in fetching data: {data.error_msg}")
36
+
37
+ data_list = []
38
+ while data.next():
39
+ data_list.append(data.get_row_data())
40
+ data_df = pd.DataFrame(data_list, columns=data.fields)
41
+
42
+ # Convert relevant columns to numeric type
43
+ data_df[['open', 'close', 'high', 'low', 'volume']] = data_df[['open', 'close', 'high', 'low', 'volume']].apply(pd.to_numeric, errors='coerce')
44
+ return data_df.dropna()
45
+
46
+ # Filter stocks based on conditions
47
+ def filter_stocks(data_df):
48
+ data_df = data_df[(data_df["open"] >= 0.98 * data_df["close"].shift(1).fillna(0)) & (data_df["open"] <= 1.02 * data_df["close"].shift(1).fillna(0))]
49
+ data_df = data_df[(data_df["high"] == data_df["close"]) & (data_df["low"] == data_df["close"]) & (data_df["open"] != 0) & (data_df["close"] != 0)]
50
+ return data_df
51
+
52
+ # Prepare the training and validation data
53
+ data_df = get_historical_data("2005-05-30", "2024-01-31")
54
+ filtered_df = filter_stocks(data_df)
55
+
56
+ if filtered_df.empty:
57
+ raise ValueError("Filtered dataset is empty. Please adjust the filtering conditions.")
58
+
59
+ train_data, val_data = train_test_split(filtered_df, test_size=0.2, random_state=42)
60
+
61
+ # Define custom model
62
  class CustomModel(nn.Module):
63
  def __init__(self):
64
  super(CustomModel, self).__init__()
65
  self.neural_prophet = NeuralProphet(
66
  n_forecasts=1,
67
+ n_lags=30,
68
+ n_changepoints=10,
69
+ changepoints_range=0.8,
70
  learning_rate=1e-3,
71
  optimizer=Adam,
72
  )
 
 
 
 
 
 
73
 
74
  def predict(self, df):
75
+ future = self.neural_prophet.make_future_dataframe(df, periods=1)
 
 
 
 
 
 
 
 
 
 
 
76
  forecast = self.neural_prophet.predict(future)
77
+ return forecast['yhat1'].values
78
 
79
+ # Instantiate model
80
  model = CustomModel()
81
 
82
+ # Prepare data for prediction
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
  def prepare_data(date):
84
+ data_df = get_historical_data("2005-05-30", date)
85
+ filtered_df = filter_stocks(data_df)
86
+ if filtered_df.empty:
87
+ return pd.DataFrame() # Return empty DataFrame if no data matches the filter
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
 
89
  # Scale the data using MinMaxScaler
90
  scaler = MinMaxScaler()
91
+ filtered_df[['open', 'high', 'low', 'close', 'volume']] = scaler.fit_transform(filtered_df[['open', 'high', 'low', 'close', 'volume']])
92
+ return filtered_df
 
93
 
94
  # Define a route to predict the top 5 stock codes
95
  @app.route('/predict', methods=['POST'])
96
  def predict():
97
+ try:
98
+ date = request.json['date']
99
+ data_df = prepare_data(date)
100
+ if data_df.empty:
101
+ return jsonify({'error': 'No data available for the given date'}), 400
102
+
103
+ y_pred = model.predict(data_df)
104
+ top_5_stocks = y_pred[:5] # Assuming y_pred contains the predicted values for stocks
105
+ return jsonify({'top_5_stocks': top_5_stocks.tolist()})
106
+ except Exception as e:
107
+ return jsonify({'error': str(e)}), 500
108
+
109
+ # Run the Flask app
110
  if __name__ == '__main__':
111
+ app.run(debug=True)
112
+
113
+ # Logout from Baostock API
114
+ bs.logout()