您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds a button to robinhood.com that calculates the amount of shares you can buy and initiates the order automatically.
// ==UserScript== // @name Robinhood Order Calculator // @namespace http://tampermonkey.net/ // @version 1.0 // @description Adds a button to robinhood.com that calculates the amount of shares you can buy and initiates the order automatically. // @author Game Abuse Studios // @match https://robinhood.com/* // @license MIT // @grant GM_addStyle // ==/UserScript== (function() { 'use strict'; // --- Injected CSS for the new button style --- GM_addStyle(` @keyframes scanline { 0% { transform: translateY(-100%); } 100% { transform: translateY(100%); } } .tech-btn { /* Gradient Border Technique - BORDER THINNER */ border: 1px solid transparent; /* UPDATED: Inside of button uses #1E2124 */ background: linear-gradient(#1E2124, #1E2124) padding-box, linear-gradient(to right, royalblue, blueviolet) border-box; /* Set to a more standard 'normal' font */ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; font-weight: bold; box-shadow: 0 2px 5px rgba(0,0,0,0.4); transition: all 0.2s ease-in-out; cursor: pointer; position: relative; overflow: hidden; } /* NEW: Style for the text span to create the gradient effect */ .tech-btn span { background: linear-gradient(to right, royalblue, blueviolet); -webkit-background-clip: text; background-clip: text; color: transparent; transition: all 0.2s ease-in-out; } .tech-btn:hover { /* Brighter gradient on hover for the border */ /* UPDATED: Inside of button on hover uses #1E2124 */ background: linear-gradient(#1E2124, #1E2124) padding-box, linear-gradient(to right, dodgerblue, mediumorchid) border-box; transform: scale(1.03); } /* NEW: Update the text span's gradient on hover */ .tech-btn:hover span { background: linear-gradient(to right, dodgerblue, mediumorchid); -webkit-background-clip: text; background-clip: text; } /* Scan line animation on hover */ .tech-btn::after { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(to bottom, transparent 0%, rgba(138, 43, 226, 0.1) 50%, transparent 100%); opacity: 0; transform: translateY(-100%); transition: opacity 0.2s ease; } .tech-btn:hover::after { opacity: 1; animation: scanline 0.6s linear; } `); console.log("Robinhood Tampermonkey script is running!"); /** * Finds and parses a numerical value from an element's text content. * @param {string} textLabel The text label to find (e.g., "buying power available"). * @returns {number|null} The parsed numerical value or null. */ function findAndParseValueByLabel(textLabel) { const potentialElements = document.querySelectorAll('span, div'); let value = null; potentialElements.forEach(element => { const textContent = element.textContent.trim(); if (textContent.includes(textLabel)) { // Assuming the value is in a sibling or a nested span const valueText = (element.previousElementSibling && element.previousElementSibling.textContent) || textContent; const match = valueText.match(/\$([\d,]+\.?\d*)/); if (match && match[1]) { value = parseFloat(match[1].replace(/,/g, '')); } } }); return value; } // Main function to perform the calculation and button click async function runScript() { console.log("Starting script..."); try { console.log("Step 1: Attempting to find buying power and market price."); const buyingPower = findAndParseValueByLabel("buying power available"); const stockPrice = findAndParseValueByLabel("Market Price"); if (buyingPower === null || stockPrice === null) { console.error("Robinhood Script: Could not find one or both of the required values."); return; } console.log(`Robinhood Script: Final stock price found: $${stockPrice}`); console.log(`Robinhood Script: Final buying power found: $${buyingPower}`); // Subtract 7% from buying power as per Robinhood's message const adjustedBuyingPower = buyingPower * 0.93; // Calculate the number of shares to buy const sharesToBuy = Math.floor(adjustedBuyingPower / stockPrice); if (sharesToBuy <= 0) { console.log("Robinhood Script: Cannot buy at least 1 share with available funds."); return; } console.log(`Robinhood Script: Shares to buy: ${sharesToBuy}`); // Input the calculated value into the text box by directly interacting with React state const sharesSelector = '[data-testid="OrderFormRows-Shares"]'; const sharesInput = document.querySelector(sharesSelector); if (!sharesInput) { console.log("Robinhood Script: Could not find the shares input field."); return; } console.log("Robinhood Script: Found the shares input field. Now setting value via React state."); const reactKey = Object.keys(sharesInput).find(key => key.startsWith('__react')); if (reactKey) { const reactProps = sharesInput[reactKey].pendingProps; // Create a synthetic event to trigger React's onChange handler const syntheticEvent = { target: { value: sharesToBuy.toString() } }; // Call the original onChange function to trigger the update if (reactProps && typeof reactProps.onChange === 'function') { reactProps.onChange(syntheticEvent); console.log(`Robinhood Script: Share value successfully set to ${sharesToBuy}.`); } else { console.error("Robinhood Script: React onChange function not found."); } // Also set the value directly on the DOM element for good measure sharesInput.value = sharesToBuy.toString(); } else { console.error("Robinhood Script: Could not find the React internal key on the element."); } } catch (error) { console.error("Robinhood Script: An error occurred during execution:", error); } } // Add the button when the document is ready function addFloatingButton() { // Find the parent of the buttons const referenceSelector = 'div[class*="_1oJVwyMO-j1ETeFAdtVHEW"]'; const referenceElement = document.querySelector(referenceSelector); if (document.getElementById('auto-set-value-btn') || !referenceElement) { return; } const wrapperDiv = document.createElement('div'); wrapperDiv.style.cssText = ` display: flex; justify-content: center; align-items: flex-start; width: 100%; margin-bottom: 12px; `; const button = document.createElement('button'); button.id = 'auto-set-value-btn'; // **UPDATED**: Wrap the text in a <span> for the gradient style to target button.innerHTML = '<span>Calculate And Order</span>'; // Apply the 'tech-btn' class for the new look and feel. button.className = 'tech-btn'; // Keep only the necessary inline styles for layout (size, position, etc.). button.style.cssText = ` border-radius: 24px; padding: 0; font-size: 19px; /* FONT SMALLER */ width: 280.4px; height: 44px; margin-top: -10px; display: flex; align-items: center; justify-content: center; `; button.addEventListener('click', runScript); wrapperDiv.appendChild(button); referenceElement.appendChild(wrapperDiv); console.log("Robinhood Tampermonkey script: 'Auto Calculate & Set Shares' button added as a child of the specified element."); } // Use a MutationObserver to watch for when the order form is added to the page const observer = new MutationObserver(() => { if (document.querySelector('[data-testid="OrderFormRows-Shares"]')) { addFloatingButton(); } }); observer.observe(document.body, { childList: true, subtree: true }); // Also try to add the button on initial page load if the element is already there if (document.querySelector('[data-testid="OrderFormRows-Shares"]')) { addFloatingButton(); } })();