diff --git a/portfolio_management/app/app.py b/portfolio_management/app/app.py new file mode 100644 index 0000000..1532dd3 --- /dev/null +++ b/portfolio_management/app/app.py @@ -0,0 +1,35 @@ +from flask import Flask, jsonify, render_template, request +from web3_interface import get_portfolio, add_stock, rebalance_portfolio +from flask_cors import CORS + +app = Flask(__name__) +CORS(app) + +# Route to render the homepage +@app.route('/') +def index(): + return render_template('index.html') + +# API endpoint to get a portfolio +@app.route('/api/portfolio', methods=['GET']) +def portfolio(): + user_address = request.args.get('address') + portfolio_data = get_portfolio(user_address) + return jsonify(portfolio_data) + +# API endpoint to add a stock +@app.route('/api/add_stock', methods=['POST']) +def add_stock_route(): + data = request.json + add_stock(data['address'], data['symbol'], data['quantity'], data['average_price']) + return jsonify({"message": "Stock added successfully"}) + +# API endpoint to rebalance the portfolio +@app.route('/api/rebalance', methods=['POST']) +def rebalance(): + user_address = request.json.get('address') + rebalance_portfolio(user_address) + return jsonify({"message": "Portfolio rebalanced successfully"}) + +if __name__ == '__main__': + app.run(debug=True) diff --git a/portfolio_management/app/static/script.js b/portfolio_management/app/static/script.js new file mode 100644 index 0000000..5167057 --- /dev/null +++ b/portfolio_management/app/static/script.js @@ -0,0 +1,44 @@ +async function getPortfolio() { + const address = document.getElementById('address').value; + const response = await fetch(`/api/portfolio?address=${address}`); + const portfolioData = await response.json(); + document.getElementById('portfolio-data').innerHTML = JSON.stringify(portfolioData); +} + +async function addStock() { + const address = document.getElementById('address').value; + const symbol = document.getElementById('symbol').value; + const quantity = document.getElementById('quantity').value; + const averagePrice = document.getElementById('averagePrice').value; + + const response = await fetch('/api/add_stock', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + address, + symbol, + quantity, + average_price: averagePrice + }) + }); + + const result = await response.json(); + alert(result.message); +} + +async function rebalancePortfolio() { + const address = document.getElementById('address').value; + + const response = await fetch('/api/rebalance', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ address }) + }); + + const result = await response.json(); + alert(result.message); +} diff --git a/portfolio_management/app/static/style.css b/portfolio_management/app/static/style.css new file mode 100644 index 0000000..b6ce147 --- /dev/null +++ b/portfolio_management/app/static/style.css @@ -0,0 +1,32 @@ +body { + font-family: Arial, sans-serif; + background-color: #f0f0f0; + padding: 20px; +} + +.container { + background-color: #fff; + padding: 20px; + border-radius: 10px; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); + max-width: 600px; + margin: auto; +} + +input { + display: block; + width: 100%; + margin: 10px 0; + padding: 10px; + border-radius: 5px; + border: 1px solid #ccc; +} + +button { + padding: 10px 20px; + background-color: #28a745; + color: white; + border: none; + border-radius: 5px; + cursor: pointer; +} diff --git a/portfolio_management/app/templates/index.html b/portfolio_management/app/templates/index.html new file mode 100644 index 0000000..5055337 --- /dev/null +++ b/portfolio_management/app/templates/index.html @@ -0,0 +1,39 @@ + + + + + + NexTrade Portfolio Manager + + + + +
+

Automated Portfolio Management

+ + +
+ + +
+
+ + +
+

Add Stock to Portfolio

+ + + + +
+ + +
+

Rebalance Portfolio

+ +
+
+ + + + diff --git a/portfolio_management/app/web3_interface.py b/portfolio_management/app/web3_interface.py new file mode 100644 index 0000000..f796a83 --- /dev/null +++ b/portfolio_management/app/web3_interface.py @@ -0,0 +1,34 @@ +from web3 import Web3 + +# Connect to local Ethereum node or testnet +w3 = Web3(Web3.HTTPProvider("http://127.0.0.1:8545")) # Or use Infura for testnets + +# ABI for the PortfolioManager contract +contract_abi = [ + # Add your contract's ABI here +] + +contract_address = Web3.toChecksumAddress('0xYourContractAddress') +portfolio_contract = w3.eth.contract(address=contract_address, abi=contract_abi) + +def get_portfolio(user_address): + user_address = Web3.toChecksumAddress(user_address) + return portfolio_contract.functions.getPortfolio(user_address).call() + +def add_stock(user_address, symbol, quantity, average_price): + user_address = Web3.toChecksumAddress(user_address) + tx = portfolio_contract.functions.addStock(symbol, quantity, average_price).buildTransaction({ + 'from': user_address, + 'nonce': w3.eth.getTransactionCount(user_address) + }) + signed_tx = w3.eth.account.signTransaction(tx, private_key="YourPrivateKey") + w3.eth.sendRawTransaction(signed_tx.rawTransaction) + +def rebalance_portfolio(user_address): + user_address = Web3.toChecksumAddress(user_address) + tx = portfolio_contract.functions.rebalancePortfolio().buildTransaction({ + 'from': user_address, + 'nonce': w3.eth.getTransactionCount(user_address) + }) + signed_tx = w3.eth.account.signTransaction(tx, private_key="YourPrivateKey") + w3.eth.sendRawTransaction(signed_tx.rawTransaction) diff --git a/portfolio_management/contracts/PortfolioManager.sol b/portfolio_management/contracts/PortfolioManager.sol new file mode 100644 index 0000000..328b765 --- /dev/null +++ b/portfolio_management/contracts/PortfolioManager.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +contract PortfolioManager { + struct Stock { + string symbol; + uint256 quantity; + uint256 averagePrice; + } + + mapping(address => Stock[]) public portfolios; + + // Function to add a stock to the portfolio + function addStock(string memory symbol, uint256 quantity, uint256 averagePrice) public { + portfolios[msg.sender].push(Stock(symbol, quantity, averagePrice)); + } + + // Function to get the portfolio for a user + function getPortfolio(address user) public view returns (Stock[] memory) { + return portfolios[user]; + } + + // Function to rebalance the portfolio (simple logic for demonstration) + function rebalancePortfolio() public { + Stock[] storage stocks = portfolios[msg.sender]; + + // Example: Rebalance by updating average prices by some logic (customize further) + for (uint256 i = 0; i < stocks.length; i++) { + stocks[i].averagePrice = (stocks[i].averagePrice * 105) / 100; // Adding 5% to average price + } + } +} diff --git a/portfolio_management/readme.md b/portfolio_management/readme.md new file mode 100644 index 0000000..97292a2 --- /dev/null +++ b/portfolio_management/readme.md @@ -0,0 +1,13 @@ +The NexTrade Portfolio Management Tool is an automated portfolio management feature integrated into the NexTrade platform. It allows users to: +Track their portfolio holdings and performance. +Automatically rebalance their portfolio based on predefined criteria. +Receive market insights, alerts, and risk assessment. +Learn about portfolio management strategies through educational resources. +The tool interacts with the Ethereum blockchain using a Solidity smart contract and the Web3.py library, providing a decentralized and secure solution for managing investments. + +Features +Portfolio Tracking: Users can view their current stock holdings and portfolio performance. +Automated Rebalancing: Rebalance portfolios based on risk tolerance and target allocations. +Market Insights & Alerts: Get real-time insights and notifications on market trends. +Risk Assessment: Analyze portfolio risk and receive suggestions to mitigate risks. +Educational Resources: Learn how to manage your portfolio and investments effectively. \ No newline at end of file