727 lines
26 KiB
HTML
727 lines
26 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh-CN">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>模拟交易 - Tradus</title>
|
|
<link rel="stylesheet" href="/static/css/style.css">
|
|
<style>
|
|
.trading-page {
|
|
min-height: 100vh;
|
|
background: var(--bg-primary);
|
|
padding: 20px;
|
|
}
|
|
|
|
.trading-container {
|
|
max-width: 1400px;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
.trading-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 30px;
|
|
padding-bottom: 20px;
|
|
border-bottom: 1px solid var(--border);
|
|
}
|
|
|
|
.trading-title {
|
|
font-size: 24px;
|
|
font-weight: 300;
|
|
color: var(--text-primary);
|
|
}
|
|
|
|
.trading-title span {
|
|
color: var(--accent);
|
|
}
|
|
|
|
.refresh-btn {
|
|
padding: 8px 16px;
|
|
background: transparent;
|
|
border: 1px solid var(--accent);
|
|
color: var(--accent);
|
|
font-size: 14px;
|
|
cursor: pointer;
|
|
transition: all 0.2s;
|
|
}
|
|
|
|
.refresh-btn:hover {
|
|
background: var(--accent);
|
|
color: var(--bg-primary);
|
|
}
|
|
|
|
/* 统计卡片 */
|
|
.stats-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
|
gap: 16px;
|
|
margin-bottom: 30px;
|
|
}
|
|
|
|
.stat-card {
|
|
background: var(--bg-secondary);
|
|
border: 1px solid var(--border);
|
|
border-radius: 4px;
|
|
padding: 16px;
|
|
}
|
|
|
|
.stat-label {
|
|
font-size: 12px;
|
|
color: var(--text-secondary);
|
|
margin-bottom: 6px;
|
|
}
|
|
|
|
.stat-value {
|
|
font-size: 24px;
|
|
font-weight: 300;
|
|
color: var(--accent);
|
|
}
|
|
|
|
.stat-value.positive {
|
|
color: #00ff41;
|
|
}
|
|
|
|
.stat-value.negative {
|
|
color: #ff4444;
|
|
}
|
|
|
|
/* 标签页 */
|
|
.tabs {
|
|
display: flex;
|
|
gap: 0;
|
|
margin-bottom: 20px;
|
|
border-bottom: 1px solid var(--border);
|
|
}
|
|
|
|
.tab {
|
|
padding: 12px 24px;
|
|
background: transparent;
|
|
border: none;
|
|
color: var(--text-secondary);
|
|
font-size: 14px;
|
|
cursor: pointer;
|
|
border-bottom: 2px solid transparent;
|
|
transition: all 0.2s;
|
|
}
|
|
|
|
.tab:hover {
|
|
color: var(--text-primary);
|
|
}
|
|
|
|
.tab.active {
|
|
color: var(--accent);
|
|
border-bottom-color: var(--accent);
|
|
}
|
|
|
|
/* 表格 */
|
|
.orders-table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
background: var(--bg-secondary);
|
|
border: 1px solid var(--border);
|
|
}
|
|
|
|
.orders-table th,
|
|
.orders-table td {
|
|
padding: 12px 16px;
|
|
text-align: left;
|
|
border-bottom: 1px solid var(--border);
|
|
}
|
|
|
|
.orders-table th {
|
|
background: var(--bg-primary);
|
|
color: var(--text-secondary);
|
|
font-weight: 400;
|
|
font-size: 12px;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.orders-table td {
|
|
color: var(--text-primary);
|
|
font-size: 14px;
|
|
}
|
|
|
|
.orders-table tr:hover {
|
|
background: var(--bg-tertiary);
|
|
}
|
|
|
|
/* 状态标签 */
|
|
.status-badge {
|
|
display: inline-block;
|
|
padding: 4px 8px;
|
|
border-radius: 2px;
|
|
font-size: 12px;
|
|
}
|
|
|
|
.status-badge.open {
|
|
background: rgba(0, 255, 65, 0.1);
|
|
color: #00ff41;
|
|
}
|
|
|
|
.status-badge.closed_tp {
|
|
background: rgba(0, 255, 65, 0.1);
|
|
color: #00ff41;
|
|
}
|
|
|
|
.status-badge.closed_sl {
|
|
background: rgba(255, 68, 68, 0.1);
|
|
color: #ff4444;
|
|
}
|
|
|
|
.status-badge.closed_manual {
|
|
background: rgba(255, 165, 0, 0.1);
|
|
color: orange;
|
|
}
|
|
|
|
/* 方向标签 */
|
|
.side-badge {
|
|
display: inline-block;
|
|
padding: 4px 8px;
|
|
border-radius: 2px;
|
|
font-size: 12px;
|
|
}
|
|
|
|
.side-badge.long {
|
|
background: rgba(0, 255, 65, 0.1);
|
|
color: #00ff41;
|
|
}
|
|
|
|
.side-badge.short {
|
|
background: rgba(255, 68, 68, 0.1);
|
|
color: #ff4444;
|
|
}
|
|
|
|
/* 等级标签 */
|
|
.grade-badge {
|
|
display: inline-block;
|
|
padding: 2px 6px;
|
|
border-radius: 2px;
|
|
font-size: 12px;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.grade-badge.A {
|
|
background: rgba(255, 215, 0, 0.2);
|
|
color: gold;
|
|
}
|
|
|
|
.grade-badge.B {
|
|
background: rgba(192, 192, 192, 0.2);
|
|
color: silver;
|
|
}
|
|
|
|
.grade-badge.C {
|
|
background: rgba(205, 127, 50, 0.2);
|
|
color: #cd7f32;
|
|
}
|
|
|
|
/* 盈亏显示 */
|
|
.pnl {
|
|
font-weight: 500;
|
|
}
|
|
|
|
.pnl.positive {
|
|
color: #00ff41;
|
|
}
|
|
|
|
.pnl.negative {
|
|
color: #ff4444;
|
|
}
|
|
|
|
/* 按等级统计 */
|
|
.grade-stats {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
|
gap: 16px;
|
|
margin-top: 30px;
|
|
}
|
|
|
|
.grade-card {
|
|
background: var(--bg-secondary);
|
|
border: 1px solid var(--border);
|
|
border-radius: 4px;
|
|
padding: 16px;
|
|
}
|
|
|
|
.grade-card-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 12px;
|
|
}
|
|
|
|
.grade-card-title {
|
|
font-size: 16px;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.grade-card-stats {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 8px;
|
|
}
|
|
|
|
.grade-stat-row {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
font-size: 14px;
|
|
}
|
|
|
|
.grade-stat-label {
|
|
color: var(--text-secondary);
|
|
}
|
|
|
|
/* 空状态 */
|
|
.empty-state {
|
|
text-align: center;
|
|
padding: 60px 20px;
|
|
color: var(--text-secondary);
|
|
}
|
|
|
|
.empty-state svg {
|
|
width: 48px;
|
|
height: 48px;
|
|
margin-bottom: 16px;
|
|
opacity: 0.5;
|
|
}
|
|
|
|
/* 监控状态 */
|
|
.monitor-status {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
font-size: 14px;
|
|
color: var(--text-secondary);
|
|
}
|
|
|
|
.monitor-dot {
|
|
width: 8px;
|
|
height: 8px;
|
|
border-radius: 50%;
|
|
background: #ff4444;
|
|
}
|
|
|
|
.monitor-dot.running {
|
|
background: #00ff41;
|
|
animation: pulse 2s infinite;
|
|
}
|
|
|
|
@keyframes pulse {
|
|
0%, 100% { opacity: 1; }
|
|
50% { opacity: 0.5; }
|
|
}
|
|
|
|
/* 价格显示 */
|
|
.price-list {
|
|
display: flex;
|
|
gap: 16px;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.price-item {
|
|
background: var(--bg-tertiary);
|
|
padding: 8px 12px;
|
|
border-radius: 4px;
|
|
font-size: 13px;
|
|
}
|
|
|
|
.price-item .symbol {
|
|
color: var(--text-secondary);
|
|
margin-right: 8px;
|
|
}
|
|
|
|
.price-item .price {
|
|
color: var(--accent);
|
|
font-family: monospace;
|
|
}
|
|
|
|
/* 加载状态 */
|
|
.loading {
|
|
text-align: center;
|
|
padding: 40px;
|
|
color: var(--text-secondary);
|
|
}
|
|
|
|
/* 操作按钮 */
|
|
.action-btn {
|
|
padding: 4px 8px;
|
|
background: transparent;
|
|
border: 1px solid var(--border-bright);
|
|
color: var(--text-secondary);
|
|
font-size: 12px;
|
|
cursor: pointer;
|
|
transition: all 0.2s;
|
|
}
|
|
|
|
.action-btn:hover {
|
|
border-color: var(--accent);
|
|
color: var(--accent);
|
|
}
|
|
|
|
.action-btn.danger:hover {
|
|
border-color: #ff4444;
|
|
color: #ff4444;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div id="app">
|
|
<div class="trading-page">
|
|
<div class="trading-container">
|
|
<!-- 头部 -->
|
|
<div class="trading-header">
|
|
<h1 class="trading-title">模拟交易 <span>Paper Trading</span></h1>
|
|
<div style="display: flex; align-items: center; gap: 20px;">
|
|
<div class="monitor-status">
|
|
<div class="monitor-dot" :class="{ running: monitorRunning }"></div>
|
|
<span>{{ monitorRunning ? '监控中' : '未启动' }}</span>
|
|
</div>
|
|
<button class="refresh-btn" @click="refreshData">刷新数据</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 统计卡片 -->
|
|
<div class="stats-grid">
|
|
<div class="stat-card">
|
|
<div class="stat-label">总交易数</div>
|
|
<div class="stat-value">{{ stats.total_trades }}</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="stat-label">胜率</div>
|
|
<div class="stat-value">{{ stats.win_rate.toFixed(1) }}%</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="stat-label">总盈亏</div>
|
|
<div class="stat-value" :class="stats.total_pnl >= 0 ? 'positive' : 'negative'">
|
|
${{ stats.total_pnl.toFixed(2) }}
|
|
</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="stat-label">盈亏比</div>
|
|
<div class="stat-value">{{ stats.profit_factor === Infinity ? '∞' : stats.profit_factor.toFixed(2) }}</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="stat-label">平均盈利</div>
|
|
<div class="stat-value positive">${{ stats.average_win.toFixed(2) }}</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="stat-label">平均亏损</div>
|
|
<div class="stat-value negative">${{ stats.average_loss.toFixed(2) }}</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 实时价格 -->
|
|
<div v-if="Object.keys(latestPrices).length > 0" style="margin-bottom: 20px;">
|
|
<div class="stat-label" style="margin-bottom: 8px;">实时价格</div>
|
|
<div class="price-list">
|
|
<div class="price-item" v-for="(price, symbol) in latestPrices" :key="symbol">
|
|
<span class="symbol">{{ symbol }}</span>
|
|
<span class="price">${{ price.toLocaleString() }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 标签页 -->
|
|
<div class="tabs">
|
|
<button class="tab" :class="{ active: activeTab === 'active' }" @click="activeTab = 'active'">
|
|
活跃订单 ({{ activeOrders.length }})
|
|
</button>
|
|
<button class="tab" :class="{ active: activeTab === 'history' }" @click="activeTab = 'history'">
|
|
历史订单
|
|
</button>
|
|
<button class="tab" :class="{ active: activeTab === 'stats' }" @click="activeTab = 'stats'">
|
|
详细统计
|
|
</button>
|
|
</div>
|
|
|
|
<!-- 活跃订单 -->
|
|
<div v-if="activeTab === 'active'">
|
|
<div v-if="loading" class="loading">加载中...</div>
|
|
<div v-else-if="activeOrders.length === 0" class="empty-state">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
|
<path d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"/>
|
|
</svg>
|
|
<p>暂无活跃订单</p>
|
|
</div>
|
|
<table v-else class="orders-table">
|
|
<thead>
|
|
<tr>
|
|
<th>订单ID</th>
|
|
<th>交易对</th>
|
|
<th>方向</th>
|
|
<th>等级</th>
|
|
<th>入场价</th>
|
|
<th>止损</th>
|
|
<th>止盈</th>
|
|
<th>仓位</th>
|
|
<th>开仓时间</th>
|
|
<th>操作</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr v-for="order in activeOrders" :key="order.order_id">
|
|
<td>{{ order.order_id.slice(-12) }}</td>
|
|
<td>{{ order.symbol }}</td>
|
|
<td><span class="side-badge" :class="order.side">{{ order.side === 'long' ? '做多' : '做空' }}</span></td>
|
|
<td><span class="grade-badge" :class="order.signal_grade">{{ order.signal_grade }}</span></td>
|
|
<td>${{ order.entry_price?.toLocaleString() }}</td>
|
|
<td>${{ order.stop_loss?.toLocaleString() }}</td>
|
|
<td>${{ order.take_profit?.toLocaleString() }}</td>
|
|
<td>${{ order.quantity }}</td>
|
|
<td>{{ formatTime(order.opened_at) }}</td>
|
|
<td>
|
|
<button class="action-btn danger" @click="closeOrder(order)">平仓</button>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- 历史订单 -->
|
|
<div v-if="activeTab === 'history'">
|
|
<div v-if="loading" class="loading">加载中...</div>
|
|
<div v-else-if="historyOrders.length === 0" class="empty-state">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
|
<path d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
|
</svg>
|
|
<p>暂无历史订单</p>
|
|
</div>
|
|
<table v-else class="orders-table">
|
|
<thead>
|
|
<tr>
|
|
<th>订单ID</th>
|
|
<th>交易对</th>
|
|
<th>方向</th>
|
|
<th>等级</th>
|
|
<th>入场价</th>
|
|
<th>出场价</th>
|
|
<th>盈亏</th>
|
|
<th>状态</th>
|
|
<th>平仓时间</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr v-for="order in historyOrders" :key="order.order_id">
|
|
<td>{{ order.order_id.slice(-12) }}</td>
|
|
<td>{{ order.symbol }}</td>
|
|
<td><span class="side-badge" :class="order.side">{{ order.side === 'long' ? '做多' : '做空' }}</span></td>
|
|
<td><span class="grade-badge" :class="order.signal_grade">{{ order.signal_grade }}</span></td>
|
|
<td>${{ order.filled_price?.toLocaleString() }}</td>
|
|
<td>${{ order.exit_price?.toLocaleString() }}</td>
|
|
<td>
|
|
<span class="pnl" :class="order.pnl_amount >= 0 ? 'positive' : 'negative'">
|
|
{{ order.pnl_percent >= 0 ? '+' : '' }}{{ order.pnl_percent?.toFixed(2) }}%
|
|
(${{ order.pnl_amount >= 0 ? '+' : '' }}{{ order.pnl_amount?.toFixed(2) }})
|
|
</span>
|
|
</td>
|
|
<td><span class="status-badge" :class="order.status">{{ formatStatus(order.status) }}</span></td>
|
|
<td>{{ formatTime(order.closed_at) }}</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- 详细统计 -->
|
|
<div v-if="activeTab === 'stats'">
|
|
<h3 style="color: var(--text-primary); font-weight: 300; margin-bottom: 16px;">按信号等级统计</h3>
|
|
<div class="grade-stats">
|
|
<div class="grade-card" v-for="(data, grade) in stats.by_grade" :key="grade">
|
|
<div class="grade-card-header">
|
|
<span class="grade-card-title">
|
|
<span class="grade-badge" :class="grade">{{ grade }}</span> 级信号
|
|
</span>
|
|
</div>
|
|
<div class="grade-card-stats">
|
|
<div class="grade-stat-row">
|
|
<span class="grade-stat-label">交易数</span>
|
|
<span>{{ data.count }}</span>
|
|
</div>
|
|
<div class="grade-stat-row">
|
|
<span class="grade-stat-label">胜率</span>
|
|
<span>{{ data.win_rate.toFixed(1) }}%</span>
|
|
</div>
|
|
<div class="grade-stat-row">
|
|
<span class="grade-stat-label">总盈亏</span>
|
|
<span :class="data.total_pnl >= 0 ? 'positive' : 'negative'">
|
|
${{ data.total_pnl.toFixed(2) }}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<h3 style="color: var(--text-primary); font-weight: 300; margin: 30px 0 16px;">按交易对统计</h3>
|
|
<div class="grade-stats">
|
|
<div class="grade-card" v-for="(data, symbol) in stats.by_symbol" :key="symbol">
|
|
<div class="grade-card-header">
|
|
<span class="grade-card-title">{{ symbol }}</span>
|
|
</div>
|
|
<div class="grade-card-stats">
|
|
<div class="grade-stat-row">
|
|
<span class="grade-stat-label">交易数</span>
|
|
<span>{{ data.count }}</span>
|
|
</div>
|
|
<div class="grade-stat-row">
|
|
<span class="grade-stat-label">胜率</span>
|
|
<span>{{ data.win_rate.toFixed(1) }}%</span>
|
|
</div>
|
|
<div class="grade-stat-row">
|
|
<span class="grade-stat-label">总盈亏</span>
|
|
<span :class="data.total_pnl >= 0 ? 'positive' : 'negative'">
|
|
${{ data.total_pnl.toFixed(2) }}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
|
|
<script>
|
|
const { createApp } = Vue;
|
|
|
|
createApp({
|
|
data() {
|
|
return {
|
|
activeTab: 'active',
|
|
loading: false,
|
|
activeOrders: [],
|
|
historyOrders: [],
|
|
stats: {
|
|
total_trades: 0,
|
|
winning_trades: 0,
|
|
losing_trades: 0,
|
|
win_rate: 0,
|
|
total_pnl: 0,
|
|
average_win: 0,
|
|
average_loss: 0,
|
|
profit_factor: 0,
|
|
by_grade: {},
|
|
by_symbol: {}
|
|
},
|
|
monitorRunning: false,
|
|
latestPrices: {},
|
|
refreshInterval: null
|
|
};
|
|
},
|
|
mounted() {
|
|
this.refreshData();
|
|
// 每10秒自动刷新
|
|
this.refreshInterval = setInterval(() => {
|
|
this.refreshData();
|
|
}, 10000);
|
|
},
|
|
beforeUnmount() {
|
|
if (this.refreshInterval) {
|
|
clearInterval(this.refreshInterval);
|
|
}
|
|
},
|
|
methods: {
|
|
async refreshData() {
|
|
this.loading = true;
|
|
try {
|
|
await Promise.all([
|
|
this.fetchActiveOrders(),
|
|
this.fetchHistoryOrders(),
|
|
this.fetchStatistics(),
|
|
this.fetchMonitorStatus()
|
|
]);
|
|
} catch (e) {
|
|
console.error('刷新数据失败:', e);
|
|
} finally {
|
|
this.loading = false;
|
|
}
|
|
},
|
|
|
|
async fetchActiveOrders() {
|
|
const response = await fetch('/api/paper-trading/orders/active');
|
|
const data = await response.json();
|
|
if (data.success) {
|
|
this.activeOrders = data.orders;
|
|
}
|
|
},
|
|
|
|
async fetchHistoryOrders() {
|
|
const response = await fetch('/api/paper-trading/orders?status=closed&limit=50');
|
|
const data = await response.json();
|
|
if (data.success) {
|
|
this.historyOrders = data.orders;
|
|
}
|
|
},
|
|
|
|
async fetchStatistics() {
|
|
const response = await fetch('/api/paper-trading/statistics');
|
|
const data = await response.json();
|
|
if (data.success) {
|
|
this.stats = data.statistics;
|
|
}
|
|
},
|
|
|
|
async fetchMonitorStatus() {
|
|
const response = await fetch('/api/paper-trading/monitor/status');
|
|
const data = await response.json();
|
|
if (data.success) {
|
|
this.monitorRunning = data.running;
|
|
this.latestPrices = data.latest_prices || {};
|
|
}
|
|
},
|
|
|
|
async closeOrder(order) {
|
|
const price = this.latestPrices[order.symbol];
|
|
if (!price) {
|
|
alert('无法获取当前价格');
|
|
return;
|
|
}
|
|
|
|
if (!confirm(`确定要以 $${price.toLocaleString()} 平仓吗?`)) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const response = await fetch(`/api/paper-trading/orders/${order.order_id}/close`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ exit_price: price })
|
|
});
|
|
const data = await response.json();
|
|
if (data.success) {
|
|
alert(`平仓成功!盈亏: ${data.result.pnl_percent.toFixed(2)}%`);
|
|
this.refreshData();
|
|
} else {
|
|
alert('平仓失败: ' + (data.detail || '未知错误'));
|
|
}
|
|
} catch (e) {
|
|
alert('平仓失败: ' + e.message);
|
|
}
|
|
},
|
|
|
|
formatTime(timeStr) {
|
|
if (!timeStr) return '-';
|
|
const date = new Date(timeStr);
|
|
return date.toLocaleString('zh-CN', {
|
|
month: '2-digit',
|
|
day: '2-digit',
|
|
hour: '2-digit',
|
|
minute: '2-digit'
|
|
});
|
|
},
|
|
|
|
formatStatus(status) {
|
|
const map = {
|
|
'open': '持仓中',
|
|
'closed_tp': '止盈',
|
|
'closed_sl': '止损',
|
|
'closed_manual': '手动平仓'
|
|
};
|
|
return map[status] || status;
|
|
}
|
|
}
|
|
}).mount('#app');
|
|
</script>
|
|
</body>
|
|
</html>
|