Faquity is a browser-based trading platform where users can practice trading with realtime market data without incurring any actual risk. Faquity's design identity was cloned from Robinhood's beta web application.
- User authentication: end-to-end using BCrypt.
- Asset search: by ticker symbol or asset name.
- Watchlist: "follow" assets without committing to a buy.
- Dashboard: View portfolio value over time, current cash allocation, and holdings diversity.
- Asset Research: View key financial metrics about an asset and its price over time.
- Portfolio: Buy and sell assets at the latest market price.
After logging in, users can view key portfolio performance metrics on their personal dashboard. The PortfolioSnapshot
model generates historical portfolio performance data, while the Cash Allocation and Holdings Diversity charts are generated from Portfolio
model associations.
Users can also view an index of all assets on the platform as well as their current holdings and watched assets in a sticky sidebar.
When navigating to an individual asset page, users can conduct basic research and make trades.
- Asset price history is charted on 1D, 1M, 3M, 1Y, 2Y, and 5Y timeframes.
- Basic data on corporate structure, financials, and trade activity is available through a "Show More" button in the
AssetAbout
component. - Both buys and sells are filled through the
TradeSidebar
component. - The
AssetDetail
component's primary colors are set by the global state'sui.signal
slice, which is in turn determined by the price movement (bullish
orbearish
) in the currently displayedAssetChart
.
The fill
model generates most of the key data for Faquity. For portfolios, the fill
table calculates the value and distribution of holdings, as well as any other desired insights from the available data fields.
This table could also be used to generate information on the asset
side (e.g., trade volume, order book distribution) or for the entire market (e.g., data to trigger circuit breakers).
As the data in the fill
table provides the foundation for all market activities, Faquity validates all incoming data on the database and model level. The platform also creates informative errors when a user attempts to create a fill with invalid inputs.
# /app/models/fill.rb
class Fill < ApplicationRecord
validates :asset_id, :portfolio_id, :price, :size,
:side, presence: true
belongs_to :portfolio,
# [...]
belongs_to :asset,
# [...]
has_one :user,
# [...]
def validate(portfolio_id)
if self.size <= 0
errors[:size].push("Trade size cannot be 0.")
return false
end
if self.side == "buy"
ensure_buying_power(portfolio_id)
else
ensure_portfolio_holdings(portfolio_id)
end
end
def ensure_buying_power(portfolio_id)
if (self.price * self.size) <= User.find(portfolio_id).buying_power
true
else
errors[:size].push("Insufficient buying power")
false
end
end
def ensure_portfolio_holdings(portfolio_id)
portfolio = Portfolio.find(portfolio_id)
if self.size <= portfolio.holdings[self.asset_id]
true
else
errors[:size].push("Insufficient shares")
false
end
end
end
To ensure database portability and avoid persisting unnecessary information, the portfolio
model generates key information about a user's portfolio through various associations.
# /app/models/portfolio.rb
class Portfolio < ApplicationRecord
after_create :take_first_snapshot
validates :user_id, presence: true
belongs_to :user,
# [...]
has_many :fills,
# [...]
has_many :assets,
# [...]
has_many :snapshots,
class_name: 'PortfolioSnapshot',
# [...]
attr_reader :holdings, :value
def holdings
holdings = Hash.new(0)
self.fills.each do |fill|
if fill.side == "buy"
holdings[fill.asset_id] += fill.size
else
holdings[fill.asset_id] -= fill.size
end
end
# remove from holdings if all assets are sold
holdings.delete_if { | asset, num_shares| num_shares == 0 }
holdings
end
def value
value = 0
self.holdings.each do |asset, num_shares|
holdings_value = Asset.find_by(id: asset).latest_price * num_shares
value += holdings_value
end
value
end
def take_first_snapshot
PortfolioSnapshot.create!(
portfolio_id: self.id,
date: Time.now.strftime("%b %d, %Y"),
value: self.user.buying_power,
)
end
end
Users should probably not be able to trade hundreds of thousands of dollars worth of assets with just one click! :) The first priority for future development is to add a multi-step trade confirmation form that also integrates trade errors.
Currently, a user signed-in to a demo account will be automatically logged out if a different user logs into the demo account.
In order to chart portfolio performance over time, Faquity will run a cron job that creates a new PortfolioSnapshot
for each user's portfolio.
Assets will be grouped by tag (e.g., Food
or Finance
) to create a sortable/filterable index.
Asset Detail containers could display a carousel of similar Assets Properties used to determine similarity could include tags
, market_cap
, or assets added by similar users.
A dropdown menu in the primary NavBar
could display notifications of recent actions or key insights about existing holdings.
The IEX API includes detailed asset information on earnings, dividends, and financials. Faquity could leverage this data to display more detailed asset research information in the Asset About container.
Faquity will continue to list new assets from IPOs or exchange transfers. Please contact the administrator for more information on how to be listed on Faquity.