// ==UserScript==
// @name AGSV股票自动挂单买卖
// @namespace http://tampermonkey.net/
// @version 1.2
// @description 根据设定的价格条件自动买入、卖出、借入和归还股票
// @author AGSV骄阳
// @match https://stock.agsvpt.cn/*
// @grant GM_xmlhttpRequest
// ==/UserScript==
(async function () {
'use strict';
// API基础URL
const API_BASE_URL = 'https://stock.agsvpt.cn/api';
const CONFIG = {
STOCK_INFO_URL: `${API_BASE_URL}/stocks/info`, // 股票信息请求的URL
TOKEN_KEY: 'auth_token', // 存储token的键名
};
// 自动弹出设置框,获取用户输入的交易参数
const userInput = await createInputDialog();
if (!userInput) return; // 如果用户取消,则退出
main(userInput); // 进入主逻辑
// 创建输入对话框以获取用户的交易设置
function createInputDialog() {
return new Promise((resolve) => {
const dialogHtml = `
<div id="inputDialog" style="position:fixed; top:50%; left:50%; transform:translate(-50%, -50%); background:white; padding:20px; border:1px solid #ccc; z-index:1000;">
<h2>设置股票交易参数</h2>
<label for="operationMode">选择交易模式:</label>
<select id="operationMode">
<option value="trade">本金模式</option>
<option value="borrow">借入模式</option>
</select><br><br>
<div id="tradeSettings">
<label for="stockCode">股票代码:</label>
<select id="stockCode">
<option value="TSLA">TSLA</option>
<option value="AAPL">AAPL</option>
<option value="GOOGL">GOOGL</option>
</select><br><br>
<label for="buyPrice">买入价格:</label>
<input type="number" id="buyPrice" value="1600" step="0.01"><br><br>
<label for="sellPrice">卖出价格:</label>
<input type="number" id="sellPrice" value="1900" step="0.01"><br><br>
<label for="buyQuantity">买入数量:</label>
<input type="number" id="buyQuantity" value="10" min="1"><br><br>
<label for="sellQuantity">卖出数量:</label>
<input type="number" id="sellQuantity" value="10" min="1"><br><br>
</div>
<div id="borrowSettings" style="display:none;">
<label for="borrowPrice">借入价格:</label>
<input type="number" id="borrowPrice" value="1800" step="0.01"><br><br>
<label for="returnPrice">归还价格:</label>
<input type="number" id="returnPrice" value="1650" step="0.01"><br><br>
<label for="borrowQuantity">借入数量:</label>
<input type="number" id="borrowQuantity" value="10" min="1"><br><br>
<label for="returnQuantity">归还数量:</label>
<input type="number" id="returnQuantity" value="10" min="1"><br><br>
</div>
<label for="checkInterval">检查间隔 (秒):</label>
<input type="number" id="checkInterval" value="30" min="1"><br><br>
<button id="submitBtn">确认</button>
<button id="cancelBtn">取消</button>
</div>
<div id="overlay" style="position:fixed; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,0.5); z-index:999;"></div>
`;
// 将对话框HTML插入到页面中
document.body.insertAdjacentHTML('beforeend', dialogHtml);
// 根据操作模式显示相应的设置
const operationModeSelect = document.getElementById('operationMode');
operationModeSelect.onchange = function () {
const tradeSettings = document.getElementById('tradeSettings');
const borrowSettings = document.getElementById('borrowSettings');
if (operationModeSelect.value === 'trade') {
tradeSettings.style.display = 'block'; // 显示本金模式设置
borrowSettings.style.display = 'none'; // 隐藏借入模式设置
} else {
tradeSettings.style.display = 'none'; // 隐藏本金模式设置
borrowSettings.style.display = 'block'; // 显示借入模式设置
}
};
// 确认按钮事件
document.getElementById('submitBtn').onclick = function () {
const operationMode = document.getElementById('operationMode').value; // 获取操作模式
const stockCode = document.getElementById('stockCode').value; // 获取股票代码
const buyPrice = parseFloat(document.getElementById('buyPrice').value); // 获取买入价格
const sellPrice = parseFloat(document.getElementById('sellPrice').value); // 获取卖出价格
const borrowPrice = parseFloat(document.getElementById('borrowPrice').value); // 获取借入价格
const returnPrice = parseFloat(document.getElementById('returnPrice').value); // 获取归还价格
const buyQuantity = parseInt(document.getElementById('buyQuantity').value, 10); // 获取买入数量
const sellQuantity = parseInt(document.getElementById('sellQuantity').value, 10); // 获取卖出数量
const borrowQuantity = parseInt(document.getElementById('borrowQuantity').value, 10); // 获取借入数量
const returnQuantity = parseInt(document.getElementById('returnQuantity').value, 10); // 获取归还数量
const checkInterval = parseInt(document.getElementById('checkInterval').value, 10) * 1000; // 转换为毫秒
// 输入验证
if (operationMode === 'trade' &&
(isNaN(buyPrice) || isNaN(sellPrice) || isNaN(buyQuantity) || isNaN(sellQuantity) ||
buyQuantity <= 0 || sellQuantity <= 0)) {
alert('请输入有效的买入和卖出价格及数量');
return;
}
if (operationMode === 'borrow' &&
(isNaN(borrowPrice) || isNaN(returnPrice) || isNaN(borrowQuantity) || isNaN(returnQuantity) ||
borrowQuantity <= 0 || returnQuantity <= 0)) {
alert('请输入有效的借入和归还价格及数量');
return;
}
// 关闭对话框并返回用户输入
document.getElementById('inputDialog').remove();
document.getElementById('overlay').remove();
resolve({ operationMode, stockCode, buyPrice, sellPrice, borrowPrice, returnPrice, buyQuantity, sellQuantity, borrowQuantity, returnQuantity, checkInterval });
};
// 取消按钮事件
document.getElementById('cancelBtn').onclick = function () {
document.getElementById('inputDialog').remove();
document.getElementById('overlay').remove();
resolve(null);
};
});
}
// 获取当前股票价格
async function getCurrentPrice(stockCode) {
const url = `${CONFIG.STOCK_INFO_URL}?code=${stockCode}`; // 股票信息请求
try {
const response = await fetch(url, {
method: 'GET',
headers: {
'Authorization': 'Bearer ' + localStorage.getItem(CONFIG.TOKEN_KEY) // 使用本地存储中的token
}
});
if (!response.ok) {
throw new Error('网络响应不正常');
}
// 解析响应数据
const data = await response.json();
const stockInfo = data.find(stock => stock.code === stockCode); // 查找对应的股票信息
return stockInfo ? stockInfo.price : undefined; // 返回价格
} catch (error) {
console.error('获取当前价格时发生错误:', error);
return undefined; // 发生错误返回undefined
}
}
// 借入股票的函数
async function borrowStock(stockCode, quantity) {
const url = `${API_BASE_URL}/stocks/${stockCode}/borrow`; // 借入股票的API URL
try {
const response = await fetch(url, {
method: 'POST', // 使用POST方法
headers: {
'Authorization': 'Bearer ' + localStorage.getItem(CONFIG.TOKEN_KEY), // 认证token
'Content-Type': 'application/json' // 请求体格式为JSON
},
body: JSON.stringify({ quantity: quantity }) // 请求体内容
});
if (!response.ok) {
throw new Error('借入请求失败');
}
console.log(`成功借入 ${quantity} 股 ${stockCode}`); // 打印成功信息
} catch (error) {
console.error('借入股票时发生错误:', error); // 打印错误信息
}
}
// 归还股票的函数
async function returnStock(stockCode, quantity) {
const url = `${API_BASE_URL}/stocks/${stockCode}/return`; // 归还股票的API URL
try {
const response = await fetch(url, {
method: 'POST', // 使用POST方法
headers: {
'Authorization': 'Bearer ' + localStorage.getItem(CONFIG.TOKEN_KEY), // 认证token
'Content-Type': 'application/json' // 请求体格式为JSON
},
body: JSON.stringify({ quantity: quantity }) // 请求体内容
});
if (!response.ok) {
throw new Error('归还请求失败');
}
console.log(`成功归还 ${quantity} 股 ${stockCode}`); // 打印成功信息
} catch (error) {
console.error('归还股票时发生错误:', error); // 打印错误信息
}
}
// 买入股票的函数
async function buyStock(stockCode, quantity) {
const url = `${API_BASE_URL}/stocks/${stockCode}/buy`; // 买入股票的API URL
try {
const response = await fetch(url, {
method: 'POST', // 使用POST方法
headers: {
'Authorization': 'Bearer ' + localStorage.getItem(CONFIG.TOKEN_KEY), // 认证token
'Content-Type': 'application/json' // 请求体格式为JSON
},
body: JSON.stringify({ quantity: quantity }) // 请求体内容
});
if (!response.ok) {
throw new Error('买入请求失败');
}
console.log(`成功买入 ${quantity} 股 ${stockCode}`); // 打印成功信息
} catch (error) {
console.error('买入股票时发生错误:', error); // 打印错误信息
}
}
// 卖出股票的函数
async function sellStock(stockCode, quantity) {
const url = `${API_BASE_URL}/stocks/${stockCode}/sell`; // 卖出股票的API URL
try {
const response = await fetch(url, {
method: 'POST', // 使用POST方法
headers: {
'Authorization': 'Bearer ' + localStorage.getItem(CONFIG.TOKEN_KEY), // 认证token
'Content-Type': 'application/json' // 请求体格式为JSON
},
body: JSON.stringify({ quantity: quantity }) // 请求体内容
});
if (!response.ok) {
throw new Error('卖出请求失败');
}
console.log(`成功卖出 ${quantity} 股 ${stockCode}`); // 打印成功信息
} catch (error) {
console.error('卖出股票时发生错误:', error); // 打印错误信息
}
}
// 主逻辑函数,根据用户输入进行操作
async function main(userInput) {
const { operationMode, stockCode, buyPrice, sellPrice, borrowPrice, returnPrice, buyQuantity, sellQuantity, borrowQuantity, returnQuantity, checkInterval } = userInput;
while (true) {
try {
const currentPrice = await getCurrentPrice(stockCode); // 获取当前价格
console.log(`当前价格: ${currentPrice}`); // 打印当前价格
if (currentPrice !== undefined) {
if (operationMode === 'trade') {
// 本金模式
if (currentPrice <= buyPrice) {
await buyStock(stockCode, buyQuantity); // 触发买入操作
} else if (currentPrice >= sellPrice) {
await sellStock(stockCode, sellQuantity); // 触发卖出操作
}
} else if (operationMode === 'borrow') {
// 借入模式
if (currentPrice >= borrowPrice) {
await borrowStock(stockCode, borrowQuantity); // 触发借入操作
} else if (currentPrice <= returnPrice) {
await returnStock(stockCode, returnQuantity); // 触发归还操作
}
}
} else {
console.warn(`无法获取 ${stockCode} 的当前价格`); // 如果当前价格获取失败,打印警告信息
}
await new Promise(resolve => setTimeout(resolve, checkInterval)); // 根据设定的间隔检查价格
} catch (error) {
console.error('发生错误:', error); // 发生错误时打印错误信息
await new Promise(resolve => setTimeout(resolve, checkInterval)); // 遇到错误时也延迟检查
}
}
}
})();