Описание < /h1>
Я пытаюсь добавить чат -бот для платформы бэкеста, созданного с колбой, и на правой стороне есть кнопка, которая переключает боковую панель. Если пользователь нажимает кнопку, он показывает боковую панель с чатботом. /> html, css, js < /h1>
const promptInput = document.getElementById("userInput");
const chatContainer = document.getElementById("chatContainer");
const typingIndicator = document.getElementById("typingIndicator");
const sidebar = document.getElementById("sidebar");
const sidebarContent = document.getElementById("sidebarContent");
async function sendMessage() {
const prompt = promptInput.value.trim();
if (!prompt) {
alert("Please enter a message.");
return;
}
addMessage(prompt, 'user');
promptInput.value = "";
showTypingIndicator();
const generatedText = await generateText(prompt);
addMessage(generatedText, 'bot');
hideTypingIndicator();
}
async function generateText(prompt) {
try {
const response = await fetch("http://127.0.0.1:5000/generate_text_stream", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ prompt }),
});
if (!response.ok) {
console.error("Error:", response.statusText);
return "Error occurred while generating response.";
}
const reader = response.body.getReader();
const decoder = new TextDecoder();
let isFinished = false;
let generatedTextContent = "";
while (!isFinished) {
const { done, value } = await reader.read();
if (done) {
isFinished = true;
break;
}
generatedTextContent += decoder.decode(value, {stream: true});
}
return generatedTextContent;
} catch (error) {
console.error("Error:", error);
return "An error occurred.";
}
}
function addMessage(text, type) {
const messageDiv = document.createElement("div");
messageDiv.className = `message ${type}`;
messageDiv.innerHTML = `${text}`;
chatContainer.appendChild(messageDiv);
chatContainer.scrollTop = chatContainer.scrollHeight;
hideTypingIndicator();
}
let typingTimeout;
function showTypingIndicator() {
clearTimeout(typingTimeout);
typingIndicator.style.display = "inline-block";
}
function hideTypingIndicator() {
typingTimeout = setTimeout(() => {
typingIndicator.style.display = "none";
}, 1000);
}
function handleKeyPress(event) {
if (event.key === "Enter") {
sendMessage();
}
}
function toggleSidebar() {
if (sidebar.style.width === "500px") {
sidebar.style.width = "0";
sidebarContent.style.display = "none";
} else {
sidebar.style.width = "500px";
sidebarContent.style.display = "block";
}
}
window.onload = () => addMessage("Hello! How can I assist you today?", 'bot');< /code>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
text-align: center;
background-color: #f4f4f4;
}
.container {
margin-top: 0;
width: 90%;
max-width: 450px;
margin: 10px auto 0;
background-color: #fff;
border-radius: 12px;
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.1);
padding: 20px;
transition: all 0.3s;
}
.chat {
overflow-y: auto;
height: 400px;
margin-bottom: 20px;
border-bottom: 2px solid #e2e2e2;
}
.message {
display: flex;
margin-bottom: 12px;
}
.message.user {
justify-content: flex-end;
}
.message-bubble {
padding: 12px 18px;
max-width: 70%;
border-radius: 20px;
line-height: 1.6;
font-size: 0.95rem;
}
.message.user .message-bubble {
background-color: #3182ce;
color: white;
}
.message.bot .message-bubble {
background-color: #e2e2e2;
color: #333;
}
input[type="text"] {
width: calc(100% - 110px);
padding: 12px 18px;
border: 2px solid #e2e2e2;
border-radius: 8px 0 0 8px;
font-size: 1rem;
outline: none;
z-index: 2; /* Ensure it's above other elements */
}
.send-button {
width: 110px;
background-color: #3182ce;
color: white;
padding: 12px 18px;
border: none;
border-radius: 0 8px 8px 0;
cursor: pointer;
transition: background-color 0.3s;
}
.send-button:hover {
background-color: #2c5282;
}
.footer {
text-align: center;
padding: 15px 0;
font-size: 0.9rem;
color: #666;
position: static;
border-top: 1px solid #e2e2e2;
background-color: #fff;
position: fixed;
bottom: 0;
width: 100%;
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.fadeIn {
animation: fadeIn 1s;
}
@media (max-width: 600px) {
.container {
width: 95%;
margin: 10px auto 0;
}
.chat {
height: 300px;
}
input[type="text"],
.send-button {
padding: 10px 14px;
font-size: 0.9rem;
}
.footer {
font-size: 0.8rem;
margin-top: 30px;
}
}
.typing-indicator {
display: none;
align-items: center;
justify-content: flex-end;
margin-top: 8px;
width: 10px;
height: 10px;
background-color: #333;
border-radius: 50%;
margin-left: 4px;
animation: typing 1s infinite;
}
@keyframes typing {
0%,
100% {
transform: scale(1);
opacity: 1;
}
50% {
transform: scale(1.2);
opacity: 0.7;
}
}
/* Sidebar Styles */
.sidebar {
position: fixed;
right: 0;
top: 0;
height: 100%;
width: 100%;
max-width: 500px;
background-color: #f4f4f4;
overflow-x: hidden;
transition: 0.5s;
padding-top: 60px;
color: white;
}
.sidebar-content {
display: none;
}
.sidebar-content h2 {
text-align: center;
}
.sidebar-content p {
padding: 10px;
}
.toggle-button {
position: fixed;
right: 0;
top: 0;
padding: 15px;
background-color: #3182ce;
color: white;
border: none;
cursor: pointer;
}
.toggle-button:hover {
background-color: #2c5282;
}
h1 {
color: rgb(0, 0, 0);
padding: 20px 0;
margin: 0 0 20px 0;
}
form {
display: inline-block;
background-color: #fff;
padding: 20px;
border-radius: 10px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
label {
display: block;
margin-bottom: 10px;
font-weight: bold;
}
select {
width: 100%;
padding: 10px;
margin-bottom: 20px;
border-radius: 5px;
border: 1px solid #ccc;
}
button {
padding: 10px 20px;
border: none;
border-radius: 5px;
background-color: #4CAF50;
color: white;
font-size: 16px;
cursor: pointer;
}
button:hover {
background-color: #45a049;
}
img {
max-width: 90%;
margin: 20px 0;
border: 1px solid #ddd;
border-radius: 10px;
}< /code>
Backtesting Engine
Backtesting Engine
☰
ChatBot
Send
Cross-Sectional Model:
EW
MSR
GMV
MDP
EMV
RP
Time-Series Model:
VT
CVT
KL
CPPI
None
Run Backtest
{% if plot_url1 and plot_url2 and plot_url3 %}
Backtesting Results
[img]data:image/png;base64,{{ plot_url1 }}[/img]
[img]data:image/png;base64,{{ plot_url2 }}[/img]
alt="Underlying Asset Performance"
/>
[img]data:image/png;base64,{{ plot_url3 }}[/img]
alt="Portfolio Performance"
/>
{% endif %}
< /code>
< /div>
< /div>
< /p>
функцияfrom flask import Flask, render_template, request
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import yfinance as yf
import quantstats as qs
from scipy.optimize import minimize
from scipy.stats import norm
from io import BytesIO
import base64
app = Flask(__name__)
# Function to get ETF price data
def get_etf_price_data():
tickers = ['AAPL', 'MSFT', 'NVDA', 'GOOG', 'XLK']
etf = yf.Tickers(tickers)
data = etf.history(start='2010-01-01', actions=False)
data.drop(['Open', 'High', 'Low', 'Volume'], inplace=True, axis=1)
data = data.droplevel(0, axis=1)
data.ffill(inplace=True)
df = data.resample('W').last()
return df
df = get_etf_price_data()
# Portfolio Backtesting Engine Class
class GEMTU772:
# Initialization Function
def __init__(self, price, param=52):
# Annualization Parameter
self.param = param
# Intraday Return Rate
self.rets = price.pct_change().dropna()
# Expected Rate of Return
self.er = np.array(self.rets * self.param)
# Volatility
self.vol = np.array(self.rets.rolling(self.param).std() * np.sqrt(self.param))
# Covariance Matrix
cov = self.rets.rolling(self.param).cov().dropna() * self.param
# Transaction Cost per Unit
self.cov = cov.values.reshape(int(cov.shape[0]/cov.shape[1]), cov.shape[1], cov.shape[1])
self.cost = 0.0005
# Cross-Sectional Risk Models Class
class CrossSectional:
#EW
def ew(self, er):
noa = er.shape[0]
weights = np.ones_like(er) * (1/noa)
return weights
def msr(self, er, cov):
noa = er.shape[0]
init_guess = np.repeat(1/noa, noa)
bounds = ((0.0, 1.0), ) * noa
weights_sum_to_1 = {'type': 'eq', 'fun': lambda weights: np.sum(weights) - 1}
def neg_sharpe(weights, er, cov):
r = weights.T @ er # @ means multiplication
vol = np.sqrt(weights.T @ cov @ weights)
return - r / vol
weights = minimize(neg_sharpe, init_guess, args=(er, cov), method='SLSQP', constraints=(weights_sum_to_1,), bounds=bounds)
return weights.x
#GMV
def gmv(self, cov):
noa = cov.shape[0]
init_guess = np.repeat(1/noa, noa)
bounds = ((0.0, 1.0), ) * noa
weights_sum_to_1 = {'type': 'eq', 'fun': lambda weights: np.sum(weights) - 1}
def port_vol(weights, cov):
vol = np.sqrt(weights.T @ cov @ weights)
return vol
weights = minimize(port_vol, init_guess, args=(cov,), method='SLSQP', constraints=(weights_sum_to_1,), bounds=bounds)
return weights.x
#MDP
def mdp(self, vol, cov):
noa = vol.shape[0]
init_guess = np.repeat(1/noa, noa)
bounds = ((0.0, 1.0), ) * noa
weights_sum_to_1 = {'type': 'eq', 'fun': lambda weights: np.sum(weights) - 1}
def neg_div_ratio(weights, vol, cov):
weighted_vol = weights.T @ vol
port_vol = np.sqrt(weights.T @ cov @ weights)
return - weighted_vol / port_vol
weights = minimize(neg_div_ratio, init_guess, args=(vol, cov), method='SLSQP', constraints=(weights_sum_to_1,), bounds=bounds)
return weights.x
#RP
def rp(self, cov):
noa = cov.shape[0]
init_guess = np.repeat(1/noa, noa)
bounds = ((0.0, 1.0), ) * noa
target_risk = np.repeat(1/noa, noa)
weights_sum_to_1 = {'type': 'eq', 'fun': lambda weights: np.sum(weights) - 1}
def msd_risk(weights, target_risk, cov):
port_var = weights.T @ cov @ weights
marginal_contribs = cov @ weights
risk_contribs = np.multiply(marginal_contribs, weights.T) / port_var
w_contribs = risk_contribs
return ((w_contribs - target_risk)**2).sum()
weights = minimize(msd_risk, init_guess, args=(target_risk, cov), method='SLSQP', constraints=(weights_sum_to_1,), bounds=bounds)
return weights.x
#EMV
def emv(self, vol):
inv_vol = 1 / vol
weights = inv_vol / inv_vol.sum()
return weights
# Time-Series Risk Models Class
class TimeSeries:
#VT
def vt(self, port_rets, param, vol_target=0.1):
vol = port_rets.rolling(param).std().fillna(0) * np.sqrt(param)
weights = (vol_target / vol).replace([np.inf, -np.inf], 0).shift(1).fillna(0)
weights[weights > 1] = 1
return weights
#CVT
def cvt(self, port_rets, param, delta=0.01, cvar_target=0.05):
def calculate_CVaR(rets, delta=0.01):
VaR = rets.quantile(delta)
return rets[rets 1] = 1
return weights
#KL
def kl(self, port_rets, param):
sharpe_ratio = (port_rets.rolling(param).mean() * np.sqrt(param) / port_rets.rolling(param).std())
weights = pd.Series(2 * norm.cdf(sharpe_ratio) - 1, index=port_rets.index).fillna(0)
weights[weights < 0] = 0
weights = weights.shift(1).fillna(0)
return weights
#CPPI
def cppi(self, port_rets, m=3, floor=0.7, init_val=1):
n_steps = len(port_rets)
port_value = init_val
floor_value = init_val * floor
peak = init_val
port_history = pd.Series(dtype=np.float64).reindex_like(port_rets)
weight_history = pd.Series(dtype=np.float64).reindex_like(port_rets)
floor_history = pd.Series(dtype=np.float64).reindex_like(port_rets)
for step in range(n_steps):
peak = np.maximum(peak, port_value)
floor_value = peak * floor
cushion = (port_value - floor_value) / port_value
weight = m * cushion
risky_alloc = port_value * weight
safe_alloc = port_value * (1 - weight)
port_value = risky_alloc * (1 + port_rets.iloc[step]) + safe_alloc
port_history.iloc[step] = port_value
weight_history.iloc[step] = weight
floor_history.iloc[step] = floor_value
return weight_history.shift(1).fillna(0)
# Transaction Cost Function (Compound rate of return method assuming reinvestment)
def transaction_cost(self, weights_df, rets_df, cost=0.0005):
prev_weights_df = (weights_df.shift(1).fillna(0) * (1 + rets_df.iloc[self.param-1:,:])) \
.div((weights_df.shift(1).fillna(0) * (1 + rets_df.iloc[self.param-1:,:])).sum(axis=1), axis=0)
# Investment Weight of Previous Period (The backslash ('\') in Python is used as a line continuation character.)
cost_df = abs(weights_df - prev_weights_df) * cost
cost_df.fillna(0, inplace=True)
return cost_df
# Backtesting Execution Function
def run(self, cs_model, ts_model, cost):
# Empty Dictionary
backtest_dict = {}
# Intraday Return Rate DataFrame
rets = self.rets
# Select and Run Cross-Sectional Risk Models
for i, index in enumerate(rets.index[self.param-1:]):
if cs_model == 'EW':
backtest_dict[index] = self.CrossSectional().ew(self.er)
elif cs_model == 'MSR':
backtest_dict[index] = self.CrossSectional().msr(self.er, self.cov)
elif cs_model == 'GMV':
backtest_dict[index] = self.CrossSectional().gmv(self.cov)
elif cs_model == 'MDP':
backtest_dict[index] = self.CrossSectional().mdp(self.vol, self.cov)
elif cs_model == 'EMV':
backtest_dict[index] = self.CrossSectional().emv(self.vol)
elif cs_model == 'RP':
backtest_dict[index] = self.CrossSectional().rp(self.cov)
# Cross-Sectional Weights DataFrame
cs_weights = pd.DataFrame(list(backtest_dict.values()), index=backtest_dict.keys(), columns=rets.columns)
cs_weights.fillna(0, inplace=True)
# Cross-Sectional Risk Models Return on Assets
cs_rets = cs_weights.shift(1) * rets.iloc[self.param-1:,:]
# Cross-Sectional Risk Models Portfolio Return
cs_port_rets = cs_rets.sum(axis=1)
# Select and Run Time-Series Risk Models
if ts_model == 'VT':
ts_weights = self.TimeSeries().vt(cs_port_rets, self.param)
elif ts_model == 'CVT':
ts_weights = self.TimeSeries().cvt(cs_port_rets, self.param)
elif ts_model == 'KL':
ts_weights = self.TimeSeries().kl(cs_port_rets, self.param)
elif ts_model == 'CPPI':
ts_weights = self.TimeSeries().cppi(cs_port_rets)
elif ts_model == None:
ts_weights = 1
# Final Portfolio Investment Weights
port_weights = cs_weights.multiply(ts_weights, axis=0)
# Transaction Cost DataFrame
cost = self.transaction_cost(port_weights, rets)
# Final Portfolio Return by Assets
port_asset_rets = port_weights.shift() * rets - cost
# Final Portfolio Return
port_rets = port_asset_rets.sum(axis=1)
port_rets.index = pd.to_datetime(port_rets.index).strftime("%Y-%m-%d")
return port_weights, port_asset_rets, port_rets
def performance_analytics(self, port_weights, port_asset_rets, port_rets):
img = BytesIO()
plt.figure(figsize=(12, 7))
port_weights['Cash'] = 1 - port_weights.sum(axis=1)
plt.stackplot(port_weights.index, port_weights.T, labels=port_weights.columns)
plt.title('Portfolio Weights')
plt.xlabel('Date')
plt.ylabel('Weights')
plt.legend(loc='upper left')
plt.savefig(img, format='png')
plt.close()
img.seek(0)
plot_url1 = base64.b64encode(img.getvalue()).decode('utf8')
img = BytesIO()
plt.figure(figsize=(12, 7))
plt.plot((1 + port_asset_rets).cumprod() - 1)
plt.title('Underlying Asset Performance')
plt.xlabel('Date')
plt.ylabel('Returns')
plt.legend(port_asset_rets.columns, loc='upper left')
plt.savefig(img, format='png')
plt.close()
img.seek(0)
plot_url2 = base64.b64encode(img.getvalue()).decode('utf8')
img = BytesIO()
plt.figure(figsize=(12, 7))
plt.plot((1 + port_rets).cumprod() - 1)
plt.title('Portfolio Performance')
plt.xlabel('Date')
plt.ylabel('Returns')
plt.savefig(img, format='png')
plt.close()
img.seek(0)
plot_url3 = base64.b64encode(img.getvalue()).decode('utf8')
return plot_url1, plot_url2, plot_url3
#Route function
@app.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'POST':
cs_model = request.form.get('cs_model') # cs model selection
ts_model = request.form.get('ts_model') # ts model selection
engine = GEMTU772(df) # Run backtesting
res = engine.run(cs_model=cs_model, ts_model=ts_model, cost=0.0005) # Run method
port_weights = res[0]
port_asset_rets = res[1]
port_rets = res[2]
plot_url1, plot_url2, plot_url3 = engine.performance_analytics(port_weights, port_asset_rets, port_rets)
return render_template('index.html', plot_url1=plot_url1, plot_url2=plot_url2, plot_url3=plot_url3) # Rendering
return render_template('index.html')
if __name__ == '__main__':
app.run(debug=True)
Подробнее здесь: https://stackoverflow.com/questions/787 ... user-input
Невозможно ввести тексты для ввода пользователя Chatbot ⇐ Html
Программисты Html
-
Anonymous
1750604033
Anonymous
Описание < /h1>
Я пытаюсь добавить чат -бот для платформы бэкеста, созданного с колбой, и на правой стороне есть кнопка, которая переключает боковую панель. Если пользователь нажимает кнопку, он показывает боковую панель с чатботом. /> html, css, js < /h1>
const promptInput = document.getElementById("userInput");
const chatContainer = document.getElementById("chatContainer");
const typingIndicator = document.getElementById("typingIndicator");
const sidebar = document.getElementById("sidebar");
const sidebarContent = document.getElementById("sidebarContent");
async function sendMessage() {
const prompt = promptInput.value.trim();
if (!prompt) {
alert("Please enter a message.");
return;
}
addMessage(prompt, 'user');
promptInput.value = "";
showTypingIndicator();
const generatedText = await generateText(prompt);
addMessage(generatedText, 'bot');
hideTypingIndicator();
}
async function generateText(prompt) {
try {
const response = await fetch("http://127.0.0.1:5000/generate_text_stream", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ prompt }),
});
if (!response.ok) {
console.error("Error:", response.statusText);
return "Error occurred while generating response.";
}
const reader = response.body.getReader();
const decoder = new TextDecoder();
let isFinished = false;
let generatedTextContent = "";
while (!isFinished) {
const { done, value } = await reader.read();
if (done) {
isFinished = true;
break;
}
generatedTextContent += decoder.decode(value, {stream: true});
}
return generatedTextContent;
} catch (error) {
console.error("Error:", error);
return "An error occurred.";
}
}
function addMessage(text, type) {
const messageDiv = document.createElement("div");
messageDiv.className = `message ${type}`;
messageDiv.innerHTML = `${text}`;
chatContainer.appendChild(messageDiv);
chatContainer.scrollTop = chatContainer.scrollHeight;
hideTypingIndicator();
}
let typingTimeout;
function showTypingIndicator() {
clearTimeout(typingTimeout);
typingIndicator.style.display = "inline-block";
}
function hideTypingIndicator() {
typingTimeout = setTimeout(() => {
typingIndicator.style.display = "none";
}, 1000);
}
function handleKeyPress(event) {
if (event.key === "Enter") {
sendMessage();
}
}
function toggleSidebar() {
if (sidebar.style.width === "500px") {
sidebar.style.width = "0";
sidebarContent.style.display = "none";
} else {
sidebar.style.width = "500px";
sidebarContent.style.display = "block";
}
}
window.onload = () => addMessage("Hello! How can I assist you today?", 'bot');< /code>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
text-align: center;
background-color: #f4f4f4;
}
.container {
margin-top: 0;
width: 90%;
max-width: 450px;
margin: 10px auto 0;
background-color: #fff;
border-radius: 12px;
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.1);
padding: 20px;
transition: all 0.3s;
}
.chat {
overflow-y: auto;
height: 400px;
margin-bottom: 20px;
border-bottom: 2px solid #e2e2e2;
}
.message {
display: flex;
margin-bottom: 12px;
}
.message.user {
justify-content: flex-end;
}
.message-bubble {
padding: 12px 18px;
max-width: 70%;
border-radius: 20px;
line-height: 1.6;
font-size: 0.95rem;
}
.message.user .message-bubble {
background-color: #3182ce;
color: white;
}
.message.bot .message-bubble {
background-color: #e2e2e2;
color: #333;
}
input[type="text"] {
width: calc(100% - 110px);
padding: 12px 18px;
border: 2px solid #e2e2e2;
border-radius: 8px 0 0 8px;
font-size: 1rem;
outline: none;
z-index: 2; /* Ensure it's above other elements */
}
.send-button {
width: 110px;
background-color: #3182ce;
color: white;
padding: 12px 18px;
border: none;
border-radius: 0 8px 8px 0;
cursor: pointer;
transition: background-color 0.3s;
}
.send-button:hover {
background-color: #2c5282;
}
.footer {
text-align: center;
padding: 15px 0;
font-size: 0.9rem;
color: #666;
position: static;
border-top: 1px solid #e2e2e2;
background-color: #fff;
position: fixed;
bottom: 0;
width: 100%;
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.fadeIn {
animation: fadeIn 1s;
}
@media (max-width: 600px) {
.container {
width: 95%;
margin: 10px auto 0;
}
.chat {
height: 300px;
}
input[type="text"],
.send-button {
padding: 10px 14px;
font-size: 0.9rem;
}
.footer {
font-size: 0.8rem;
margin-top: 30px;
}
}
.typing-indicator {
display: none;
align-items: center;
justify-content: flex-end;
margin-top: 8px;
width: 10px;
height: 10px;
background-color: #333;
border-radius: 50%;
margin-left: 4px;
animation: typing 1s infinite;
}
@keyframes typing {
0%,
100% {
transform: scale(1);
opacity: 1;
}
50% {
transform: scale(1.2);
opacity: 0.7;
}
}
/* Sidebar Styles */
.sidebar {
position: fixed;
right: 0;
top: 0;
height: 100%;
width: 100%;
max-width: 500px;
background-color: #f4f4f4;
overflow-x: hidden;
transition: 0.5s;
padding-top: 60px;
color: white;
}
.sidebar-content {
display: none;
}
.sidebar-content h2 {
text-align: center;
}
.sidebar-content p {
padding: 10px;
}
.toggle-button {
position: fixed;
right: 0;
top: 0;
padding: 15px;
background-color: #3182ce;
color: white;
border: none;
cursor: pointer;
}
.toggle-button:hover {
background-color: #2c5282;
}
h1 {
color: rgb(0, 0, 0);
padding: 20px 0;
margin: 0 0 20px 0;
}
form {
display: inline-block;
background-color: #fff;
padding: 20px;
border-radius: 10px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
label {
display: block;
margin-bottom: 10px;
font-weight: bold;
}
select {
width: 100%;
padding: 10px;
margin-bottom: 20px;
border-radius: 5px;
border: 1px solid #ccc;
}
button {
padding: 10px 20px;
border: none;
border-radius: 5px;
background-color: #4CAF50;
color: white;
font-size: 16px;
cursor: pointer;
}
button:hover {
background-color: #45a049;
}
img {
max-width: 90%;
margin: 20px 0;
border: 1px solid #ddd;
border-radius: 10px;
}< /code>
Backtesting Engine
Backtesting Engine
☰
ChatBot
Send
Cross-Sectional Model:
EW
MSR
GMV
MDP
EMV
RP
Time-Series Model:
VT
CVT
KL
CPPI
None
Run Backtest
{% if plot_url1 and plot_url2 and plot_url3 %}
Backtesting Results
[img]data:image/png;base64,{{ plot_url1 }}[/img]
[img]data:image/png;base64,{{ plot_url2 }}[/img]
alt="Underlying Asset Performance"
/>
[img]data:image/png;base64,{{ plot_url3 }}[/img]
alt="Portfolio Performance"
/>
{% endif %}
< /code>
< /div>
< /div>
< /p>
функцияfrom flask import Flask, render_template, request
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import yfinance as yf
import quantstats as qs
from scipy.optimize import minimize
from scipy.stats import norm
from io import BytesIO
import base64
app = Flask(__name__)
# Function to get ETF price data
def get_etf_price_data():
tickers = ['AAPL', 'MSFT', 'NVDA', 'GOOG', 'XLK']
etf = yf.Tickers(tickers)
data = etf.history(start='2010-01-01', actions=False)
data.drop(['Open', 'High', 'Low', 'Volume'], inplace=True, axis=1)
data = data.droplevel(0, axis=1)
data.ffill(inplace=True)
df = data.resample('W').last()
return df
df = get_etf_price_data()
# Portfolio Backtesting Engine Class
class GEMTU772:
# Initialization Function
def __init__(self, price, param=52):
# Annualization Parameter
self.param = param
# Intraday Return Rate
self.rets = price.pct_change().dropna()
# Expected Rate of Return
self.er = np.array(self.rets * self.param)
# Volatility
self.vol = np.array(self.rets.rolling(self.param).std() * np.sqrt(self.param))
# Covariance Matrix
cov = self.rets.rolling(self.param).cov().dropna() * self.param
# Transaction Cost per Unit
self.cov = cov.values.reshape(int(cov.shape[0]/cov.shape[1]), cov.shape[1], cov.shape[1])
self.cost = 0.0005
# Cross-Sectional Risk Models Class
class CrossSectional:
#EW
def ew(self, er):
noa = er.shape[0]
weights = np.ones_like(er) * (1/noa)
return weights
def msr(self, er, cov):
noa = er.shape[0]
init_guess = np.repeat(1/noa, noa)
bounds = ((0.0, 1.0), ) * noa
weights_sum_to_1 = {'type': 'eq', 'fun': lambda weights: np.sum(weights) - 1}
def neg_sharpe(weights, er, cov):
r = weights.T @ er # @ means multiplication
vol = np.sqrt(weights.T @ cov @ weights)
return - r / vol
weights = minimize(neg_sharpe, init_guess, args=(er, cov), method='SLSQP', constraints=(weights_sum_to_1,), bounds=bounds)
return weights.x
#GMV
def gmv(self, cov):
noa = cov.shape[0]
init_guess = np.repeat(1/noa, noa)
bounds = ((0.0, 1.0), ) * noa
weights_sum_to_1 = {'type': 'eq', 'fun': lambda weights: np.sum(weights) - 1}
def port_vol(weights, cov):
vol = np.sqrt(weights.T @ cov @ weights)
return vol
weights = minimize(port_vol, init_guess, args=(cov,), method='SLSQP', constraints=(weights_sum_to_1,), bounds=bounds)
return weights.x
#MDP
def mdp(self, vol, cov):
noa = vol.shape[0]
init_guess = np.repeat(1/noa, noa)
bounds = ((0.0, 1.0), ) * noa
weights_sum_to_1 = {'type': 'eq', 'fun': lambda weights: np.sum(weights) - 1}
def neg_div_ratio(weights, vol, cov):
weighted_vol = weights.T @ vol
port_vol = np.sqrt(weights.T @ cov @ weights)
return - weighted_vol / port_vol
weights = minimize(neg_div_ratio, init_guess, args=(vol, cov), method='SLSQP', constraints=(weights_sum_to_1,), bounds=bounds)
return weights.x
#RP
def rp(self, cov):
noa = cov.shape[0]
init_guess = np.repeat(1/noa, noa)
bounds = ((0.0, 1.0), ) * noa
target_risk = np.repeat(1/noa, noa)
weights_sum_to_1 = {'type': 'eq', 'fun': lambda weights: np.sum(weights) - 1}
def msd_risk(weights, target_risk, cov):
port_var = weights.T @ cov @ weights
marginal_contribs = cov @ weights
risk_contribs = np.multiply(marginal_contribs, weights.T) / port_var
w_contribs = risk_contribs
return ((w_contribs - target_risk)**2).sum()
weights = minimize(msd_risk, init_guess, args=(target_risk, cov), method='SLSQP', constraints=(weights_sum_to_1,), bounds=bounds)
return weights.x
#EMV
def emv(self, vol):
inv_vol = 1 / vol
weights = inv_vol / inv_vol.sum()
return weights
# Time-Series Risk Models Class
class TimeSeries:
#VT
def vt(self, port_rets, param, vol_target=0.1):
vol = port_rets.rolling(param).std().fillna(0) * np.sqrt(param)
weights = (vol_target / vol).replace([np.inf, -np.inf], 0).shift(1).fillna(0)
weights[weights > 1] = 1
return weights
#CVT
def cvt(self, port_rets, param, delta=0.01, cvar_target=0.05):
def calculate_CVaR(rets, delta=0.01):
VaR = rets.quantile(delta)
return rets[rets 1] = 1
return weights
#KL
def kl(self, port_rets, param):
sharpe_ratio = (port_rets.rolling(param).mean() * np.sqrt(param) / port_rets.rolling(param).std())
weights = pd.Series(2 * norm.cdf(sharpe_ratio) - 1, index=port_rets.index).fillna(0)
weights[weights < 0] = 0
weights = weights.shift(1).fillna(0)
return weights
#CPPI
def cppi(self, port_rets, m=3, floor=0.7, init_val=1):
n_steps = len(port_rets)
port_value = init_val
floor_value = init_val * floor
peak = init_val
port_history = pd.Series(dtype=np.float64).reindex_like(port_rets)
weight_history = pd.Series(dtype=np.float64).reindex_like(port_rets)
floor_history = pd.Series(dtype=np.float64).reindex_like(port_rets)
for step in range(n_steps):
peak = np.maximum(peak, port_value)
floor_value = peak * floor
cushion = (port_value - floor_value) / port_value
weight = m * cushion
risky_alloc = port_value * weight
safe_alloc = port_value * (1 - weight)
port_value = risky_alloc * (1 + port_rets.iloc[step]) + safe_alloc
port_history.iloc[step] = port_value
weight_history.iloc[step] = weight
floor_history.iloc[step] = floor_value
return weight_history.shift(1).fillna(0)
# Transaction Cost Function (Compound rate of return method assuming reinvestment)
def transaction_cost(self, weights_df, rets_df, cost=0.0005):
prev_weights_df = (weights_df.shift(1).fillna(0) * (1 + rets_df.iloc[self.param-1:,:])) \
.div((weights_df.shift(1).fillna(0) * (1 + rets_df.iloc[self.param-1:,:])).sum(axis=1), axis=0)
# Investment Weight of Previous Period (The backslash ('\') in Python is used as a line continuation character.)
cost_df = abs(weights_df - prev_weights_df) * cost
cost_df.fillna(0, inplace=True)
return cost_df
# Backtesting Execution Function
def run(self, cs_model, ts_model, cost):
# Empty Dictionary
backtest_dict = {}
# Intraday Return Rate DataFrame
rets = self.rets
# Select and Run Cross-Sectional Risk Models
for i, index in enumerate(rets.index[self.param-1:]):
if cs_model == 'EW':
backtest_dict[index] = self.CrossSectional().ew(self.er[i])
elif cs_model == 'MSR':
backtest_dict[index] = self.CrossSectional().msr(self.er[i], self.cov[i])
elif cs_model == 'GMV':
backtest_dict[index] = self.CrossSectional().gmv(self.cov[i])
elif cs_model == 'MDP':
backtest_dict[index] = self.CrossSectional().mdp(self.vol[i], self.cov[i])
elif cs_model == 'EMV':
backtest_dict[index] = self.CrossSectional().emv(self.vol[i])
elif cs_model == 'RP':
backtest_dict[index] = self.CrossSectional().rp(self.cov[i])
# Cross-Sectional Weights DataFrame
cs_weights = pd.DataFrame(list(backtest_dict.values()), index=backtest_dict.keys(), columns=rets.columns)
cs_weights.fillna(0, inplace=True)
# Cross-Sectional Risk Models Return on Assets
cs_rets = cs_weights.shift(1) * rets.iloc[self.param-1:,:]
# Cross-Sectional Risk Models Portfolio Return
cs_port_rets = cs_rets.sum(axis=1)
# Select and Run Time-Series Risk Models
if ts_model == 'VT':
ts_weights = self.TimeSeries().vt(cs_port_rets, self.param)
elif ts_model == 'CVT':
ts_weights = self.TimeSeries().cvt(cs_port_rets, self.param)
elif ts_model == 'KL':
ts_weights = self.TimeSeries().kl(cs_port_rets, self.param)
elif ts_model == 'CPPI':
ts_weights = self.TimeSeries().cppi(cs_port_rets)
elif ts_model == None:
ts_weights = 1
# Final Portfolio Investment Weights
port_weights = cs_weights.multiply(ts_weights, axis=0)
# Transaction Cost DataFrame
cost = self.transaction_cost(port_weights, rets)
# Final Portfolio Return by Assets
port_asset_rets = port_weights.shift() * rets - cost
# Final Portfolio Return
port_rets = port_asset_rets.sum(axis=1)
port_rets.index = pd.to_datetime(port_rets.index).strftime("%Y-%m-%d")
return port_weights, port_asset_rets, port_rets
def performance_analytics(self, port_weights, port_asset_rets, port_rets):
img = BytesIO()
plt.figure(figsize=(12, 7))
port_weights['Cash'] = 1 - port_weights.sum(axis=1)
plt.stackplot(port_weights.index, port_weights.T, labels=port_weights.columns)
plt.title('Portfolio Weights')
plt.xlabel('Date')
plt.ylabel('Weights')
plt.legend(loc='upper left')
plt.savefig(img, format='png')
plt.close()
img.seek(0)
plot_url1 = base64.b64encode(img.getvalue()).decode('utf8')
img = BytesIO()
plt.figure(figsize=(12, 7))
plt.plot((1 + port_asset_rets).cumprod() - 1)
plt.title('Underlying Asset Performance')
plt.xlabel('Date')
plt.ylabel('Returns')
plt.legend(port_asset_rets.columns, loc='upper left')
plt.savefig(img, format='png')
plt.close()
img.seek(0)
plot_url2 = base64.b64encode(img.getvalue()).decode('utf8')
img = BytesIO()
plt.figure(figsize=(12, 7))
plt.plot((1 + port_rets).cumprod() - 1)
plt.title('Portfolio Performance')
plt.xlabel('Date')
plt.ylabel('Returns')
plt.savefig(img, format='png')
plt.close()
img.seek(0)
plot_url3 = base64.b64encode(img.getvalue()).decode('utf8')
return plot_url1, plot_url2, plot_url3
#Route function
@app.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'POST':
cs_model = request.form.get('cs_model') # cs model selection
ts_model = request.form.get('ts_model') # ts model selection
engine = GEMTU772(df) # Run backtesting
res = engine.run(cs_model=cs_model, ts_model=ts_model, cost=0.0005) # Run method
port_weights = res[0]
port_asset_rets = res[1]
port_rets = res[2]
plot_url1, plot_url2, plot_url3 = engine.performance_analytics(port_weights, port_asset_rets, port_rets)
return render_template('index.html', plot_url1=plot_url1, plot_url2=plot_url2, plot_url3=plot_url3) # Rendering
return render_template('index.html')
if __name__ == '__main__':
app.run(debug=True)
Подробнее здесь: [url]https://stackoverflow.com/questions/78752558/unable-to-type-texts-to-chatbot-user-input[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия