Beta 2.0 Working
This commit is contained in:
parent
21a2c383b8
commit
3ec5857946
3
.idea/.gitignore
vendored
Normal file
3
.idea/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
8
.idea/StocksGame.iml
Normal file
8
.idea/StocksGame.iml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="PYTHON_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$" />
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
12
.idea/inspectionProfiles/Project_Default.xml
Normal file
12
.idea/inspectionProfiles/Project_Default.xml
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<profile version="1.0">
|
||||||
|
<option name="myName" value="Project Default" />
|
||||||
|
<inspection_tool class="PyPep8NamingInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
|
||||||
|
<option name="ignoredErrors">
|
||||||
|
<list>
|
||||||
|
<option value="N801" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</inspection_tool>
|
||||||
|
</profile>
|
||||||
|
</component>
|
6
.idea/inspectionProfiles/profiles_settings.xml
Normal file
6
.idea/inspectionProfiles/profiles_settings.xml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<settings>
|
||||||
|
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||||
|
<version value="1.0" />
|
||||||
|
</settings>
|
||||||
|
</component>
|
4
.idea/misc.xml
Normal file
4
.idea/misc.xml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.8" project-jdk-type="Python SDK" />
|
||||||
|
</project>
|
8
.idea/modules.xml
Normal file
8
.idea/modules.xml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/StocksGame.iml" filepath="$PROJECT_DIR$/.idea/StocksGame.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
6
.idea/vcs.xml
Normal file
6
.idea/vcs.xml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
BIN
src/__pycache__/picker.cpython-38.pyc
Normal file
BIN
src/__pycache__/picker.cpython-38.pyc
Normal file
Binary file not shown.
BIN
src/__pycache__/stock.cpython-38.pyc
Normal file
BIN
src/__pycache__/stock.cpython-38.pyc
Normal file
Binary file not shown.
BIN
src/__pycache__/trading.cpython-38.pyc
Normal file
BIN
src/__pycache__/trading.cpython-38.pyc
Normal file
Binary file not shown.
19
src/main.py
19
src/main.py
|
@ -6,21 +6,4 @@ if __name__ == "__main__":
|
||||||
trader = TradingBot()
|
trader = TradingBot()
|
||||||
while True:
|
while True:
|
||||||
_in = input("> ")
|
_in = input("> ")
|
||||||
words = _in.split(" ")
|
trader.interpret_command(_in.lower())
|
||||||
if len(words) == 0:
|
|
||||||
continue
|
|
||||||
cmd = words.pop(0)
|
|
||||||
args = []
|
|
||||||
kwargs = {}
|
|
||||||
for w in words:
|
|
||||||
components = w.split("=")
|
|
||||||
if len(components) == 1:
|
|
||||||
args.append(w)
|
|
||||||
elif len(components) == 2:
|
|
||||||
kwargs[components[0]] = components[1]
|
|
||||||
else:
|
|
||||||
print("Invalid parameter: " + w)
|
|
||||||
continue
|
|
||||||
|
|
||||||
trader.interpret_command(cmd, *args, **kwargs)
|
|
||||||
# trader.buy("GOOG", 1)
|
|
||||||
|
|
79
src/picker.py
Normal file
79
src/picker.py
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
import mechanicalsoup
|
||||||
|
from stock import StockList
|
||||||
|
|
||||||
|
|
||||||
|
class StockAnalyzer(mechanicalsoup.StatefulBrowser):
|
||||||
|
yahoo_52wk_low = "https://finance.yahoo.com/u/yahoo-finance/watchlists/fiftytwo-wk-low"
|
||||||
|
yahoo_52wk_high = "https://finance.yahoo.com/u/yahoo-finance/watchlists/fiftytwo-wk-high"
|
||||||
|
yahoo_most_added = "https://finance.yahoo.com/u/yahoo-finance/watchlists/most-added"
|
||||||
|
yahoo_active_spacs = "https://finance.yahoo.com/u/yahoo-finance/watchlists/most-active-spacs"
|
||||||
|
yahoo_covid = "https://finance.yahoo.com/u/trea/watchlists/the-fight-against-covid19"
|
||||||
|
yahoo_small_cap = "https://finance.yahoo.com/u/yahoo-finance/watchlists/most-active-small-cap-stocks"
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__(user_agent="Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0")
|
||||||
|
|
||||||
|
def get_prediction(self, symbol: str):
|
||||||
|
status = self.open("https://finance.yahoo.com/quote/" + symbol)
|
||||||
|
if not status.ok:
|
||||||
|
print("Invalid symbol: " + symbol)
|
||||||
|
return "invalid"
|
||||||
|
element = self.page.find("div", {"Fw(b) Fl(end)--m Fz(s) C($primaryColor"})
|
||||||
|
if element is None:
|
||||||
|
return "same"
|
||||||
|
value = element.get_text()
|
||||||
|
if value is None:
|
||||||
|
return "same"
|
||||||
|
if value == "Near Fair Value":
|
||||||
|
return "same"
|
||||||
|
if value == "Overvalued":
|
||||||
|
return "down"
|
||||||
|
if value == "Undervalued":
|
||||||
|
return "up"
|
||||||
|
|
||||||
|
def grab_yahoo_watchlist(self, link):
|
||||||
|
self.open(link)
|
||||||
|
table = self.page.find("table", {"class": "cwl-symbols W(100%)"})
|
||||||
|
data = []
|
||||||
|
for item in table.find_all("td"):
|
||||||
|
data.append(item.get_text())
|
||||||
|
count = len(data) / 9
|
||||||
|
companies = StockList()
|
||||||
|
for i in range(int(count)):
|
||||||
|
start = i * 9
|
||||||
|
# WHY TF ARE THERE 2 SYMBOLS FOR GOOGLE?????
|
||||||
|
if data[start + 1] == "GOOGL":
|
||||||
|
data[start + 1] = "GOOG"
|
||||||
|
company = [
|
||||||
|
data[start + 0],
|
||||||
|
data[start + 1],
|
||||||
|
data[start + 2],
|
||||||
|
data[start + 3],
|
||||||
|
data[start + 4],
|
||||||
|
data[start + 8],
|
||||||
|
1,
|
||||||
|
self.get_prediction(data[start + 0])
|
||||||
|
]
|
||||||
|
companies.add_stock(company)
|
||||||
|
return companies
|
||||||
|
|
||||||
|
def recommend_buy(self, budget):
|
||||||
|
print("Scanning largest 52 week losses...")
|
||||||
|
companies = self.grab_yahoo_watchlist(self.yahoo_52wk_low)
|
||||||
|
print("Scanning largest 52 week gains...")
|
||||||
|
companies.concat(self.grab_yahoo_watchlist(self.yahoo_52wk_high), False)
|
||||||
|
print("Scanning most watched stocks...")
|
||||||
|
companies.concat(self.grab_yahoo_watchlist(self.yahoo_most_added), False)
|
||||||
|
print("Scanning most active SPAC's...")
|
||||||
|
companies.concat(self.grab_yahoo_watchlist(self.yahoo_active_spacs), False)
|
||||||
|
print("Scanning COVID-19 related stocks...")
|
||||||
|
companies.concat(self.grab_yahoo_watchlist(self.yahoo_covid), False)
|
||||||
|
print("Scanning small market cap stocks...")
|
||||||
|
companies.concat(self.grab_yahoo_watchlist(self.yahoo_small_cap), False)
|
||||||
|
print("Sorting results...")
|
||||||
|
companies.keep_recommended()
|
||||||
|
print("Budgeting...")
|
||||||
|
companies.budget(int(budget))
|
||||||
|
return companies
|
||||||
|
|
||||||
|
|
119
src/stock.py
Normal file
119
src/stock.py
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
class StockList:
|
||||||
|
def __init__(self):
|
||||||
|
self.symbol = []
|
||||||
|
self.name = []
|
||||||
|
self.price = []
|
||||||
|
self.change_absolute = []
|
||||||
|
self.change_relative = []
|
||||||
|
self.market_cap = []
|
||||||
|
self.amount = []
|
||||||
|
self.prediction = []
|
||||||
|
|
||||||
|
def sanity_check(self):
|
||||||
|
# debug
|
||||||
|
assert len(self.symbol) == len(self.name)
|
||||||
|
assert len(self.name) == len(self.price)
|
||||||
|
assert len(self.price) == len(self.change_absolute)
|
||||||
|
assert len(self.change_absolute) == len(self.change_relative)
|
||||||
|
assert len(self.change_relative) == len(self.market_cap)
|
||||||
|
assert len(self.market_cap) == len(self.amount)
|
||||||
|
assert len(self.amount) == len(self.prediction)
|
||||||
|
|
||||||
|
def count(self):
|
||||||
|
self.sanity_check()
|
||||||
|
return len(self.symbol)
|
||||||
|
|
||||||
|
def total(self):
|
||||||
|
total = 0
|
||||||
|
for i in range(self.count()):
|
||||||
|
total += self.price[i] * self.amount[i]
|
||||||
|
return total
|
||||||
|
|
||||||
|
def add_stock(self, data, allow_duplicates=True):
|
||||||
|
dupe = data[0] in self.symbol
|
||||||
|
if dupe and not allow_duplicates:
|
||||||
|
index = self.symbol.index(data[0])
|
||||||
|
self.amount[index] += int(data[6])
|
||||||
|
return
|
||||||
|
self.symbol += [str(data[0])]
|
||||||
|
self.name += [str(data[1])]
|
||||||
|
self.price += [float(data[2])]
|
||||||
|
self.change_absolute += [str(data[3])]
|
||||||
|
self.change_relative += [str(data[4])]
|
||||||
|
self.market_cap += [str(data[5])]
|
||||||
|
self.amount += [int(data[6])]
|
||||||
|
self.prediction += [str(data[7])]
|
||||||
|
self.sanity_check()
|
||||||
|
|
||||||
|
def concat(self, stocks, allow_duplicates=True):
|
||||||
|
for i in range(stocks.count()):
|
||||||
|
self.add_stock(stocks.get_stock(i), allow_duplicates)
|
||||||
|
|
||||||
|
def remove_stock(self, index):
|
||||||
|
if self.count() <= index:
|
||||||
|
print("Out of range")
|
||||||
|
return
|
||||||
|
self.symbol.pop(index)
|
||||||
|
self.name.pop(index)
|
||||||
|
self.price.pop(index)
|
||||||
|
self.change_absolute.pop(index)
|
||||||
|
self.change_relative.pop(index)
|
||||||
|
self.market_cap.pop(index)
|
||||||
|
self.amount.pop(index)
|
||||||
|
self.prediction.pop(index)
|
||||||
|
|
||||||
|
def get_stock(self, index):
|
||||||
|
return [
|
||||||
|
self.symbol[index],
|
||||||
|
self.name[index],
|
||||||
|
self.price[index],
|
||||||
|
self.change_absolute[index],
|
||||||
|
self.change_relative[index],
|
||||||
|
self.market_cap[index],
|
||||||
|
self.amount[index],
|
||||||
|
self.prediction[index]
|
||||||
|
]
|
||||||
|
|
||||||
|
def most_expensive(self):
|
||||||
|
index = 0
|
||||||
|
highest = 0
|
||||||
|
for i in range(self.count()):
|
||||||
|
if self.price[i] >= highest:
|
||||||
|
index = i
|
||||||
|
highest = self.price[i]
|
||||||
|
return index
|
||||||
|
|
||||||
|
def least_expensive(self):
|
||||||
|
smallest = 9999999999
|
||||||
|
index = 0
|
||||||
|
for s in range(self.count()):
|
||||||
|
if self.price[s] <= smallest:
|
||||||
|
smallest = self.price[s]
|
||||||
|
index = s
|
||||||
|
return index
|
||||||
|
|
||||||
|
def budget(self, budget):
|
||||||
|
total = self.total()
|
||||||
|
while total > budget:
|
||||||
|
i = self.most_expensive()
|
||||||
|
self.remove_stock(i)
|
||||||
|
total = self.total()
|
||||||
|
print(self.name)
|
||||||
|
if self.count() == 0:
|
||||||
|
print("No stocks found")
|
||||||
|
return
|
||||||
|
while total + self.price[self.least_expensive()] < budget:
|
||||||
|
for stock in range(self.count()):
|
||||||
|
if total + self.price[stock] <= budget:
|
||||||
|
self.amount[stock] += 1
|
||||||
|
total = self.total()
|
||||||
|
|
||||||
|
def keep_recommended(self):
|
||||||
|
i = 0
|
||||||
|
size = self.count()
|
||||||
|
while i < size:
|
||||||
|
while i < size and self.prediction[i] != "up":
|
||||||
|
self.remove_stock(i)
|
||||||
|
size = self.count()
|
||||||
|
i += 1
|
||||||
|
|
181
src/trading.py
181
src/trading.py
|
@ -1,113 +1,6 @@
|
||||||
import mechanicalsoup
|
import mechanicalsoup
|
||||||
import getpass
|
import getpass
|
||||||
import bs4
|
from picker import StockAnalyzer
|
||||||
import selenium
|
|
||||||
|
|
||||||
|
|
||||||
def _convert_symbol(dec: str):
|
|
||||||
mult = 1
|
|
||||||
if dec.find("M") != -1:
|
|
||||||
mult = 1000000
|
|
||||||
elif dec.find("B") != -1:
|
|
||||||
mult = 1000000000
|
|
||||||
dec = dec.replace("M", "")
|
|
||||||
dec = dec.replace("B", "")
|
|
||||||
dec = dec.replace(",", "")
|
|
||||||
return float(dec) * mult
|
|
||||||
|
|
||||||
|
|
||||||
def _convert_decimal(dec: str):
|
|
||||||
dec = dec.replace("%", "")
|
|
||||||
return float(dec) / 100
|
|
||||||
|
|
||||||
|
|
||||||
def _sum_total(stocks: list[dict]):
|
|
||||||
ret = 0
|
|
||||||
for s in stocks:
|
|
||||||
ret += s["price"] * s["amount"]
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
def _most_expensive(stocks: list[dict]):
|
|
||||||
if len(stocks) == 0:
|
|
||||||
return 0
|
|
||||||
largest = 0
|
|
||||||
index = 0
|
|
||||||
for s in range(len(stocks)):
|
|
||||||
if stocks[s]["price"] >= largest:
|
|
||||||
largest = stocks[s]["price"]
|
|
||||||
index = s
|
|
||||||
return index
|
|
||||||
|
|
||||||
|
|
||||||
def _least_expensive(stocks: list[dict]):
|
|
||||||
if len(stocks) == 0:
|
|
||||||
return 0
|
|
||||||
smallest = 9999999999
|
|
||||||
index = 0
|
|
||||||
for s in range(len(stocks)):
|
|
||||||
if stocks[s]["price"] <= smallest:
|
|
||||||
smallest = stocks[s]["price"]
|
|
||||||
index = s
|
|
||||||
return index
|
|
||||||
|
|
||||||
|
|
||||||
class StockAnalyzer(mechanicalsoup.StatefulBrowser):
|
|
||||||
def __init__(self):
|
|
||||||
super().__init__(user_agent="Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0")
|
|
||||||
|
|
||||||
def recommend_buy(self, budget):
|
|
||||||
budget = float(budget)
|
|
||||||
data = []
|
|
||||||
self.open("https://finance.yahoo.com/u/yahoo-finance/watchlists/fiftytwo-wk-low")
|
|
||||||
table = self.page.find("table", {"class": "cwl-symbols W(100%)"})
|
|
||||||
for item in table.find_all("td"):
|
|
||||||
data.append(item.get_text())
|
|
||||||
count = len(data) / 9
|
|
||||||
companies = []
|
|
||||||
cart = []
|
|
||||||
for i in range(int(count)):
|
|
||||||
start = i * 9
|
|
||||||
company = {
|
|
||||||
"symbol": data[start + 0],
|
|
||||||
"name": data[start + 1],
|
|
||||||
"price": float(data[start + 2]),
|
|
||||||
"change-absolute": float(data[start + 3]),
|
|
||||||
"change-relative": _convert_decimal(data[start + 4]),
|
|
||||||
"market-cap": _convert_symbol(data[start + 8]),
|
|
||||||
"amount": 1
|
|
||||||
}
|
|
||||||
if company["price"] >= budget / 2:
|
|
||||||
continue
|
|
||||||
companies.append(company)
|
|
||||||
prediction = self.get_prediction(company["symbol"])
|
|
||||||
if prediction == "up":
|
|
||||||
cart.append(company)
|
|
||||||
|
|
||||||
total = _sum_total(cart)
|
|
||||||
while total > budget:
|
|
||||||
i = _most_expensive(cart)
|
|
||||||
cart.pop(i)
|
|
||||||
total = _sum_total(cart)
|
|
||||||
while total + cart[_least_expensive(cart)]["price"] < budget:
|
|
||||||
for stock in cart:
|
|
||||||
if total + stock["price"] <= budget:
|
|
||||||
stock["amount"] += 1
|
|
||||||
total = _sum_total(cart)
|
|
||||||
return cart
|
|
||||||
|
|
||||||
def get_prediction(self, symbol: str):
|
|
||||||
status = self.open("https://finance.yahoo.com/quote/" + symbol)
|
|
||||||
if not status.ok:
|
|
||||||
print("Invalid symbol: " + symbol)
|
|
||||||
return "invalid"
|
|
||||||
value = self.page.find("div", {"Fw(b) Fl(end)--m Fz(s) C($primaryColor"}).get_text()
|
|
||||||
if value == "Near Fair Value":
|
|
||||||
return "same"
|
|
||||||
if value == "Overvalued":
|
|
||||||
return "down"
|
|
||||||
if value == "Undervalued":
|
|
||||||
return "up"
|
|
||||||
|
|
||||||
|
|
||||||
class TradingBot(mechanicalsoup.StatefulBrowser):
|
class TradingBot(mechanicalsoup.StatefulBrowser):
|
||||||
|
@ -115,7 +8,6 @@ class TradingBot(mechanicalsoup.StatefulBrowser):
|
||||||
super().__init__(user_agent="Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0")
|
super().__init__(user_agent="Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0")
|
||||||
self.logged_in = False
|
self.logged_in = False
|
||||||
self.commands = {
|
self.commands = {
|
||||||
"help": self.help,
|
|
||||||
"quit": quit,
|
"quit": quit,
|
||||||
"login": self.login,
|
"login": self.login,
|
||||||
"buy": self.buy,
|
"buy": self.buy,
|
||||||
|
@ -124,37 +16,26 @@ class TradingBot(mechanicalsoup.StatefulBrowser):
|
||||||
}
|
}
|
||||||
self.analyzer = StockAnalyzer()
|
self.analyzer = StockAnalyzer()
|
||||||
|
|
||||||
def help(self):
|
def interpret_command(self, cmd):
|
||||||
print("Unimplemented")
|
|
||||||
|
|
||||||
def interpret_command(self, cmd, *args, **kwargs):
|
|
||||||
cmd = cmd.lower()
|
|
||||||
if cmd not in self.commands.keys():
|
if cmd not in self.commands.keys():
|
||||||
print("Invalid command " + cmd + ", type help for more info")
|
print("Invalid command " + cmd + ", type help for more info")
|
||||||
return
|
return
|
||||||
return self.commands[cmd](*args, **kwargs)
|
return self.commands[cmd]()
|
||||||
|
|
||||||
def login(self, *args, **kwargs):
|
def login(self, _username="", _password=""):
|
||||||
# Navigate to login page
|
# Navigate to login page
|
||||||
self.open("https://www.howthemarketworks.com/login")
|
self.open("https://www.howthemarketworks.com/login")
|
||||||
self.select_form('form[action="/login"]')
|
|
||||||
# Get login info
|
# Get login info
|
||||||
_username = args[0] if len(args) > 0 else ""
|
|
||||||
_password = args[1] if len(args) > 1 else ""
|
|
||||||
for key in kwargs.keys():
|
|
||||||
key = key.lower()
|
|
||||||
if key == "username" or key == "user":
|
|
||||||
_username = kwargs[key]
|
|
||||||
if key == "password" or key == "pass":
|
|
||||||
_password = kwargs[key]
|
|
||||||
if _username == "":
|
if _username == "":
|
||||||
_username = input("Username: ")
|
_username = input("Username: ")
|
||||||
if _password == "":
|
if _password == "":
|
||||||
_password = getpass.getpass(prompt="Password: ")
|
_password = getpass.getpass(prompt="Password: ")
|
||||||
# Submit form and get result
|
# Submit form and get result
|
||||||
|
self.select_form('form[action="/login"]')
|
||||||
self.__setitem__("UserName", _username)
|
self.__setitem__("UserName", _username)
|
||||||
self.__setitem__("Password", _password)
|
self.__setitem__("Password", _password)
|
||||||
result = self.submit_selected()
|
result = self.submit_selected()
|
||||||
|
|
||||||
self.logged_in = result.ok and self.url == "https://www.howthemarketworks.com/accounting/dashboard"
|
self.logged_in = result.ok and self.url == "https://www.howthemarketworks.com/accounting/dashboard"
|
||||||
if self.logged_in:
|
if self.logged_in:
|
||||||
print("Log-in successful")
|
print("Log-in successful")
|
||||||
|
@ -162,32 +43,34 @@ class TradingBot(mechanicalsoup.StatefulBrowser):
|
||||||
print("Log-in failed")
|
print("Log-in failed")
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def buy(self, *args, **kwargs):
|
def buy(self, symbol="", quantity="", t="", stop=0):
|
||||||
if not self.logged_in:
|
if not self.logged_in:
|
||||||
print("Not logged in")
|
print("Not logged in")
|
||||||
return None
|
return None
|
||||||
|
stop = float(stop)
|
||||||
symbol = args[0] if len(args) > 0 else ""
|
|
||||||
quantity = args[1] if len(args) > 1 else ""
|
|
||||||
for key in kwargs.keys():
|
|
||||||
key = key.lower()
|
|
||||||
if key == "sym" or key == "symbol":
|
|
||||||
symbol = kwargs[key]
|
|
||||||
if key == "quantity" or key == "q":
|
|
||||||
quantity = kwargs[key]
|
|
||||||
|
|
||||||
if symbol == "":
|
if symbol == "":
|
||||||
symbol = input("Stock Symbol: ")
|
symbol = input("Stock Symbol: ")
|
||||||
if quantity == "":
|
if quantity == "":
|
||||||
quantity = input("Quantity: ")
|
quantity = input("Quantity: ")
|
||||||
|
if t == "":
|
||||||
|
trailing = input("Make order trailing stop? Y/N - ")
|
||||||
|
if trailing:
|
||||||
|
t = "Trailing Stop %"
|
||||||
|
stop = input("What percent of price to stop? __/100 - ")
|
||||||
|
else:
|
||||||
|
t = "Market"
|
||||||
|
|
||||||
self.open("https://www.howthemarketworks.com/trading/equities")
|
self.open("https://www.howthemarketworks.com/trading/equities")
|
||||||
self.select_form()
|
self.select_form()
|
||||||
self.__setitem__("Symbol", symbol)
|
self.__setitem__("Symbol", symbol)
|
||||||
self.__setitem__("Quantity", quantity)
|
self.__setitem__("Quantity", quantity)
|
||||||
|
self.__setitem__("OrderType", t)
|
||||||
|
if t == "Trailing Stop %":
|
||||||
|
self.__setitem__("Price", stop)
|
||||||
result = self.submit_selected()
|
result = self.submit_selected()
|
||||||
if result.ok:
|
if result.ok:
|
||||||
print("Successfully bought " + str(quantity) + " shares of " + symbol)
|
print("Successfully bought " + str(quantity) + " shares of " + symbol + " with type " + t)
|
||||||
else:
|
else:
|
||||||
print("Failed to purchase " + symbol + ". Check that the symbol is correct and funds are sufficient")
|
print("Failed to purchase " + symbol + ". Check that the symbol is correct and funds are sufficient")
|
||||||
return result
|
return result
|
||||||
|
@ -199,23 +82,35 @@ class TradingBot(mechanicalsoup.StatefulBrowser):
|
||||||
self.open("https://www.howthemarketworks.com/accounting/accountbalance")
|
self.open("https://www.howthemarketworks.com/accounting/accountbalance")
|
||||||
self.launch_browser()
|
self.launch_browser()
|
||||||
|
|
||||||
def autobuy(self, budget=1000):
|
def autobuy(self, budget=0):
|
||||||
|
if budget == 0:
|
||||||
|
budget = input("Budget for autobuy: ")
|
||||||
print("Analyzing market, this may take time")
|
print("Analyzing market, this may take time")
|
||||||
stocks = self.analyzer.recommend_buy(budget)
|
stocks = self.analyzer.recommend_buy(budget)
|
||||||
total = _sum_total(stocks)
|
total = stocks.total()
|
||||||
symbols = []
|
symbols = []
|
||||||
print("The following stocks have been selected:")
|
print("The following stocks have been selected:")
|
||||||
for s in stocks:
|
for s in range(stocks.count()):
|
||||||
symbols.append(s["symbol"])
|
symbols.append(stocks.symbol[s])
|
||||||
print(s["name"] + " (" + s["symbol"] + ") ---- " + str(s["amount"]) + " share(s) totalling: $" + str(round(s["amount"] * s["price"], 2)))
|
print(stocks.name[s] + " (" + stocks.symbol[s] + ") ---- " + str(stocks.amount[s]) +
|
||||||
|
" share(s) totalling: $" + str(round(stocks.amount[s] * stocks.price[s], 2)))
|
||||||
print("Purchase will total $" + str(round(total, 2)))
|
print("Purchase will total $" + str(round(total, 2)))
|
||||||
|
order_type = "Market"
|
||||||
|
percent = 0
|
||||||
|
trailing = input("Add trailing stop? Y/N - ")
|
||||||
|
if trailing.lower() == "y":
|
||||||
|
order_type = "Trailing Stop %"
|
||||||
|
percent = input("What percent to put the stop? __/100 - ")
|
||||||
print("Make sure you have sufficient funds before continuing")
|
print("Make sure you have sufficient funds before continuing")
|
||||||
decision = input("Finalize purchase? Y/N - ")
|
decision = input("Finalize purchase? Y/N - ")
|
||||||
if decision.lower() != "y":
|
if decision.lower() != "y":
|
||||||
print("Cancelled order")
|
print("Cancelled order")
|
||||||
return
|
return
|
||||||
for s in stocks:
|
for s in range(stocks.count()):
|
||||||
self.buy(s["symbol"], s["amount"])
|
if order_type == "Market":
|
||||||
|
self.buy(stocks.symbol[s], str(stocks.amount[s]), order_type)
|
||||||
|
else:
|
||||||
|
self.buy(stocks.symbol[s], str(stocks.amount[s]), order_type, percent)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
Loading…
Reference in a new issue