您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
A Robinhood quality of life script
当前为
// ==UserScript== // @name Robinhood QOL Trading // @namespace Trading // @match https://robinhood.com/legend/layout/* // @grant none // @version 1.3 // @license MIT // @author AdSam // @description A Robinhood quality of life script // ==/UserScript== const TIMEOUT = 5; const BUY_KEY = "b"; const SELL_KEY = "s"; const TRAILING_STOP_KEY = "t"; const SET_SHARES_KEY = "z"; const SET_AMOUNT_KEY = "x"; function WaitForElement(selector, index, timeout = 0) { let iter = 0; return new Promise((resolve, reject) => { const interval = setInterval(() => { if (timeout != 0 && iter >= timeout * 1000) { reject(new Error("Timeout")); } const elements = document.querySelectorAll(selector); if (elements[index]) { clearInterval(interval); resolve(elements[index]); } iter++; }, 1); }); } async function buy(shares) { let menuBtn = await WaitForElement( '[data-testid="legend_buy_button"]', 0, TIMEOUT ); menuBtn.click(); let dropdown = await WaitForElement('[role="combobox"]', 0, TIMEOUT); dropdown.click(); let market = await WaitForElement('[role="option"]', 1, TIMEOUT); market.click(); let quantity = await WaitForElement('[name="quantity"]', 0, TIMEOUT); quantity.focus(); document.execCommand("selectAll"); document.execCommand("insertText", false, shares.toString()); while (quantity.value != shares.toString()) {} let buyBtn = await WaitForElement('[type="submit"]', 0, TIMEOUT); buyBtn.click(); } async function sell(shares) { let menuBtn = await WaitForElement( '[data-testid="legend_sell_button"]', 0, TIMEOUT ); menuBtn.click(); let dropdown = await WaitForElement('[role="combobox"]', 0, TIMEOUT); dropdown.click(); let market = await WaitForElement('[role="option"]', 1, TIMEOUT); market.click(); let quantity = await WaitForElement('[name="quantity"]', 0, TIMEOUT); quantity.focus(); document.execCommand("selectAll"); document.execCommand("insertText", false, shares.toString()); while (quantity.value != shares.toString()) {} let sellBtn = await WaitForElement('[type="submit"]', 0, TIMEOUT); sellBtn.click(); } async function trailing_stop(shares, amount) { let menuBtn = await WaitForElement( '[data-testid="legend_sell_button"]', 0, TIMEOUT ); menuBtn.click(); let dropdown = await WaitForElement('[role="combobox"]', 0, TIMEOUT); dropdown.click(); let ts = await WaitForElement('[role="option"]', 4, TIMEOUT); ts.click(); let quantity = await WaitForElement('[name="quantity"]', 0, TIMEOUT); quantity.focus(); document.execCommand("selectAll"); document.execCommand("insertText", false, shares.toString()); let trail = await WaitForElement('[role="combobox"]', 1, TIMEOUT); trail.click(); let a = await WaitForElement('[role="option"]', 8, TIMEOUT); a.click(); let ta = await WaitForElement('[name="trailAmount"]', 1, TIMEOUT); ta.focus(); document.execCommand("selectAll"); document.execCommand("insertText", false, amount.toString()); let tif = await WaitForElement('[role="combobox"]', 2, TIMEOUT); tif.click(); let gtc = await WaitForElement('[role="option"]', 6, TIMEOUT); gtc.click(); while (quantity.value != shares.toString() || !ta.value.includes(amount.toString())) {} await new Promise(r => setTimeout(r, 100)); let sellBtn = await WaitForElement('[type="submit"]', 0, TIMEOUT); sellBtn.click(); } let shares = 0; let amount = 0; let debounce = false; document.addEventListener("keydown", async (event) => { if (!debounce) { debounce = true; try { if (event.ctrlKey && event.key == BUY_KEY) { event.preventDefault(); await buy(shares); } else if (event.ctrlKey && event.key == SELL_KEY) { event.preventDefault(); await sell(shares); } else if (event.ctrlKey && event.key == TRAILING_STOP_KEY) { event.preventDefault(); await trailing_stop(shares, amount) } else if (event.ctrlKey && event.key == SET_SHARES_KEY) { event.preventDefault(); const res = prompt("Enter number of shares:"); if (res != null) { shares = parseFloat(res); } } else if (event.ctrlKey && event.key == SET_AMOUNT_KEY) { event.preventDefault(); const res = prompt("Enter trailing amount:"); if (res != null) { amount = parseFloat(res); } } } catch (e) {} debounce = false; } });
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址