chore: 添加Stock-Prediction-Models项目文件

添加了Stock-Prediction-Models项目的多个文件,包括数据集、模型代码、README文档和CSS样式文件。这些文件用于股票预测模型的训练和展示,涵盖了LSTM、GRU等深度学习模型的应用。
This commit is contained in:
2025-04-27 16:28:06 +08:00
parent f57150dae8
commit 2757a4d0d2
200 changed files with 79402 additions and 0 deletions

View File

@@ -0,0 +1,393 @@
from flask import Flask, request, jsonify
import numpy as np
import pickle
import json
from sklearn.preprocessing import MinMaxScaler
import pandas as pd
from datetime import datetime
app = Flask(__name__)
window_size = 20
skip = 1
layer_size = 500
output_size = 3
def softmax(z):
assert len(z.shape) == 2
s = np.max(z, axis=1)
s = s[:, np.newaxis]
e_x = np.exp(z - s)
div = np.sum(e_x, axis=1)
div = div[:, np.newaxis]
return e_x / div
def get_state(parameters, t, window_size = 20):
outside = []
d = t - window_size + 1
for parameter in parameters:
block = (
parameter[d : t + 1]
if d >= 0
else -d * [parameter[0]] + parameter[0 : t + 1]
)
res = []
for i in range(window_size - 1):
res.append(block[i + 1] - block[i])
for i in range(1, window_size, 1):
res.append(block[i] - block[0])
outside.append(res)
return np.array(outside).reshape((1, -1))
class Deep_Evolution_Strategy:
inputs = None
def __init__(
self, weights, reward_function, population_size, sigma, learning_rate
):
self.weights = weights
self.reward_function = reward_function
self.population_size = population_size
self.sigma = sigma
self.learning_rate = learning_rate
def _get_weight_from_population(self, weights, population):
weights_population = []
for index, i in enumerate(population):
jittered = self.sigma * i
weights_population.append(weights[index] + jittered)
return weights_population
def get_weights(self):
return self.weights
def train(self, epoch = 100, print_every = 1):
lasttime = time.time()
for i in range(epoch):
population = []
rewards = np.zeros(self.population_size)
for k in range(self.population_size):
x = []
for w in self.weights:
x.append(np.random.randn(*w.shape))
population.append(x)
for k in range(self.population_size):
weights_population = self._get_weight_from_population(
self.weights, population[k]
)
rewards[k] = self.reward_function(weights_population)
rewards = (rewards - np.mean(rewards)) / (np.std(rewards) + 1e-7)
for index, w in enumerate(self.weights):
A = np.array([p[index] for p in population])
self.weights[index] = (
w
+ self.learning_rate
/ (self.population_size * self.sigma)
* np.dot(A.T, rewards).T
)
if (i + 1) % print_every == 0:
print(
'iter %d. reward: %f'
% (i + 1, self.reward_function(self.weights))
)
print('time taken to train:', time.time() - lasttime, 'seconds')
class Model:
def __init__(self, input_size, layer_size, output_size):
self.weights = [
np.random.rand(input_size, layer_size)
* np.sqrt(1 / (input_size + layer_size)),
np.random.rand(layer_size, output_size)
* np.sqrt(1 / (layer_size + output_size)),
np.zeros((1, layer_size)),
np.zeros((1, output_size)),
]
def predict(self, inputs):
feed = np.dot(inputs, self.weights[0]) + self.weights[-2]
decision = np.dot(feed, self.weights[1]) + self.weights[-1]
return decision
def get_weights(self):
return self.weights
def set_weights(self, weights):
self.weights = weights
class Agent:
POPULATION_SIZE = 15
SIGMA = 0.1
LEARNING_RATE = 0.03
def __init__(self, model, timeseries, skip, initial_money, real_trend, minmax):
self.model = model
self.timeseries = timeseries
self.skip = skip
self.real_trend = real_trend
self.initial_money = initial_money
self.es = Deep_Evolution_Strategy(
self.model.get_weights(),
self.get_reward,
self.POPULATION_SIZE,
self.SIGMA,
self.LEARNING_RATE,
)
self.minmax = minmax
self._initiate()
def _initiate(self):
# i assume first index is the close value
self.trend = self.timeseries[0]
self._mean = np.mean(self.trend)
self._std = np.std(self.trend)
self._inventory = []
self._capital = self.initial_money
self._queue = []
self._scaled_capital = self.minmax.transform([[self._capital, 2]])[0, 0]
def reset_capital(self, capital):
if capital:
self._capital = capital
self._scaled_capital = self.minmax.transform([[self._capital, 2]])[0, 0]
self._queue = []
self._inventory = []
def trade(self, data):
"""
you need to make sure the data is [close, volume]
"""
scaled_data = self.minmax.transform([data])[0]
real_close = data[0]
close = scaled_data[0]
if len(self._queue) >= window_size:
self._queue.pop(0)
self._queue.append(scaled_data)
if len(self._queue) < window_size:
return {
'status': 'data not enough to trade',
'action': 'fail',
'balance': self._capital,
'timestamp': str(datetime.now()),
}
state = self.get_state(
window_size - 1,
self._inventory,
self._scaled_capital,
timeseries = np.array(self._queue).T.tolist(),
)
action, prob = self.act_softmax(state)
print(prob)
if action == 1 and self._scaled_capital >= close:
self._inventory.append(close)
self._scaled_capital -= close
self._capital -= real_close
return {
'status': 'buy 1 unit, cost %f' % (real_close),
'action': 'buy',
'balance': self._capital,
'timestamp': str(datetime.now()),
}
elif action == 2 and len(self._inventory):
bought_price = self._inventory.pop(0)
self._scaled_capital += close
self._capital += real_close
scaled_bought_price = self.minmax.inverse_transform(
[[bought_price, 2]]
)[0, 0]
try:
invest = (
(real_close - scaled_bought_price) / scaled_bought_price
) * 100
except:
invest = 0
return {
'status': 'sell 1 unit, price %f' % (real_close),
'investment': invest,
'gain': real_close - scaled_bought_price,
'balance': self._capital,
'action': 'sell',
'timestamp': str(datetime.now()),
}
else:
return {
'status': 'do nothing',
'action': 'nothing',
'balance': self._capital,
'timestamp': str(datetime.now()),
}
def change_data(self, timeseries, skip, initial_money, real_trend, minmax):
self.timeseries = timeseries
self.skip = skip
self.initial_money = initial_money
self.real_trend = real_trend
self.minmax = minmax
self._initiate()
def act(self, sequence):
decision = self.model.predict(np.array(sequence))
return np.argmax(decision[0])
def act_softmax(self, sequence):
decision = self.model.predict(np.array(sequence))
return np.argmax(decision[0]), softmax(decision)[0]
def get_state(self, t, inventory, capital, timeseries):
state = get_state(timeseries, t)
len_inventory = len(inventory)
if len_inventory:
mean_inventory = np.mean(inventory)
else:
mean_inventory = 0
z_inventory = (mean_inventory - self._mean) / self._std
z_capital = (capital - self._mean) / self._std
concat_parameters = np.concatenate(
[state, [[len_inventory, z_inventory, z_capital]]], axis = 1
)
return concat_parameters
def get_reward(self, weights):
initial_money = self._scaled_capital
starting_money = initial_money
invests = []
self.model.weights = weights
inventory = []
state = self.get_state(0, inventory, starting_money, self.timeseries)
for t in range(0, len(self.trend) - 1, self.skip):
action = self.act(state)
if action == 1 and starting_money >= self.trend[t]:
inventory.append(self.trend[t])
starting_money -= self.trend[t]
elif action == 2 and len(inventory):
bought_price = inventory.pop(0)
starting_money += self.trend[t]
invest = ((self.trend[t] - bought_price) / bought_price) * 100
invests.append(invest)
state = self.get_state(
t + 1, inventory, starting_money, self.timeseries
)
invests = np.mean(invests)
if np.isnan(invests):
invests = 0
score = (starting_money - initial_money) / initial_money * 100
return invests * 0.7 + score * 0.3
def fit(self, iterations, checkpoint):
self.es.train(iterations, print_every = checkpoint)
def buy(self):
initial_money = self._scaled_capital
starting_money = initial_money
real_initial_money = self.initial_money
real_starting_money = self.initial_money
inventory = []
real_inventory = []
state = self.get_state(0, inventory, starting_money, self.timeseries)
states_sell = []
states_buy = []
for t in range(0, len(self.trend) - 1, self.skip):
action, prob = self.act_softmax(state)
print(t, prob)
if action == 1 and starting_money >= self.trend[t] and t < (len(self.trend) - 1 - window_size):
inventory.append(self.trend[t])
real_inventory.append(self.real_trend[t])
real_starting_money -= self.real_trend[t]
starting_money -= self.trend[t]
states_buy.append(t)
print(
'day %d: buy 1 unit at price %f, total balance %f'
% (t, self.real_trend[t], real_starting_money)
)
elif action == 2 and len(inventory):
bought_price = inventory.pop(0)
real_bought_price = real_inventory.pop(0)
starting_money += self.trend[t]
real_starting_money += self.real_trend[t]
states_sell.append(t)
try:
invest = (
(self.real_trend[t] - real_bought_price)
/ real_bought_price
) * 100
except:
invest = 0
print(
'day %d, sell 1 unit at price %f, investment %f %%, total balance %f,'
% (t, self.real_trend[t], invest, real_starting_money)
)
state = self.get_state(
t + 1, inventory, starting_money, self.timeseries
)
invest = (
(real_starting_money - real_initial_money) / real_initial_money
) * 100
total_gains = real_starting_money - real_initial_money
return states_buy, states_sell, total_gains, invest
with open('model.pkl', 'rb') as fopen:
model = pickle.load(fopen)
df = pd.read_csv('TWTR.csv')
real_trend = df['Close'].tolist()
parameters = [df['Close'].tolist(), df['Volume'].tolist()]
minmax = MinMaxScaler(feature_range = (100, 200)).fit(np.array(parameters).T)
scaled_parameters = minmax.transform(np.array(parameters).T).T.tolist()
initial_money = np.max(parameters[0]) * 2
agent = Agent(model = model,
timeseries = scaled_parameters,
skip = skip,
initial_money = initial_money,
real_trend = real_trend,
minmax = minmax)
@app.route('/', methods = ['GET'])
def hello():
return jsonify({'status': 'OK'})
@app.route('/inventory', methods = ['GET'])
def inventory():
return jsonify(agent._inventory)
@app.route('/queue', methods = ['GET'])
def queue():
return jsonify(agent._queue)
@app.route('/balance', methods = ['GET'])
def balance():
return jsonify(agent._capital)
@app.route('/trade', methods = ['GET'])
def trade():
data = json.loads(request.args.get('data'))
return jsonify(agent.trade(data))
@app.route('/reset', methods = ['GET'])
def reset():
money = json.loads(request.args.get('money'))
agent.reset_capital(money)
return jsonify(True)
if __name__ == '__main__':
app.run(host = '0.0.0.0', port = 8005)