Hummingbot
Decentralized
market making
CoinAlpha Inc.
December 24, 2018
Abstract
Tokenization not only brings the promise of increased efficiency in the conveyance of currently tradable assets, it also has the potential to unlock liquidity for previ- ously non-tradable assets. However, one impediment to fully realizing this state is the general lack of liquidity for all but a limited number of top digital assets trading on centralized exchanges. The growth in the number of cryptocurrency exchanges as well as digital assets has far surpassed the increase in the number of and capabilities of cryptocurrency market makers, leading to liquidity fragmentation and inadequacy across exchanges and assets. Contributing to the lack of liquidity for some trading venues, in particular decentralized exchanges, is the increased technical complexity of transacting through native blockchain protocols as well as a lack of technical stan- dardization. Meanwhile, these inefficiencies also create market trading opportunities for capable traders. With the goal of overcoming these limitations, we introduce Hummingbot, open source software that enables users to create custom, automated trading strategies that can transact on both centralized and decentralized exchanges. Hummingbot’s objective is to enable a broader set of users to act as market mak- ers, an activity previously limited to only sophisticated and highly technical market participants, and promote the concept of decentralized market making.
 This is supported by academic research, which has shown that liquidity benefits market participants via efficient price discovery. Liquidity improvement improves the availability of public information about a firm, and improved information will lower the risk premium of the firm, thus decreasing its cost of capital [1].
Yet in practice, tokenization has led to extreme concentration of liquidity. There are thousands of tradeable digital assets and hundreds of exchanges, but liquidity is heavily concentrated in the top assets and venues. The top three digital assets have a combined daily exchange trading volume of $12 billion, 72% of total daily exchange trading volume. Of the more than 2,000 crypto assets listed in CoinMarketCap, 92% have less than $1 million in daily volume [2]. Factoring in over-the-counter trading (OTC) volume between institutions, which deal almost exclusively in the largest digital assets, would likely further increase liquidity concentration.
When the number of markets increases relative to the number of liquidity providers, a power-law distribution for liquidity is the natural equilibrium state. In a hearing on capital markets before the United State House of Representatives in 2011, Eric Noll from Nasdaq spoke about the challenges faced by small-capitalization stocks after the rise of alternative trading systems and dark pools for equities: “The unintended consequences of that market fragmentation have been a lack of liquidity and price discovery in listed securities outside of the top 100 traded names and a disturbing absence of market attention paid to small-growth companies by all market participants, including exchanges [3].”
While tokenization enables assets to trade freely, it does not automatically confer liquidity onto them. In order for the global financial system to fully realize the value of tokenization, there needs to be sufficient actors who are both incentivized and equipped to provide liquidity, especially for the long tail of tokenized assets.
Providers of liquidity on financial markets are called market makers. Market makers play a fundamental role in asset markets by simultaneously quoting bid (offers to buy) and ask (offers to sell) prices for assets on an exchange. By quoting prices at which they stand ready to buy and sell assets, they enable price discovery and liquid trading by other market
participants. In addition, by quoting prices on different trading venues and arbitraging away inter-market dislocations across different markets, market makers increase overall market efficiency.
In traditional securities markets such as equities, regulatory barriers prevent individuals and small firms from filling the market maker role. On the New York Stock Exchange (NYSE), only member organizations who have been granted approval to act as Designated Market Makers and Supplemental Liquidity Providers are allowed to make markets. Similarly, Nasdaq market makers are required to register with FINRA and apply to be a Nasdaq member firm [4].
In addition, competitive barriers also prevent small participants from acting as market makers. In a practice known as co-location, high frequency trading (”HFT”) firms pay exchanges to place servers in close physical proximity to the exchange’s own servers, pro- viding lower latency access to data feeds and trade execution. HFT firms have collectively spent massive sums building networks of wireless towers, fiber optic lines and submarine cables designed to provide millisecond-scale time advantages versus other market partici- pants. Furthermore, fiat exchanges like NYSE and Nasdaq charge as much as $22,000 per month for access to market data feeds [5].
Since HFT firms earn profits by performing a high volume of trades, they tend to focus on making markets in large-capitalization stocks. In a 2011 House of Representatives hearing, Joseph Mecane of NYSE Euronext said, “A lot of the spread compression and increased competition that we have seen has been in the very large liquid stocks where you have seen a lot of algorithmic type trading, high-frequency-type trading, which tends to narrow the spread and make it very cheap and efficient and fast for the large-cap stocks to trade. The unfortunate reality is those same trends haven’t occurred in the small- and mid-cap part of the market. Those stocks don’t have sufficient liquidity for the high-frequency- type automated traders to traffic in those names, and as a result, you have not seen a commensurate level of volume or liquidity or spread compression that you have seen in some of the large-cap names [3].”
Digital markets remove the regulatory and competitive constraints that impede market making in fiat markets. Individual traders have direct market access to digital asset ex- changes, enabling them to provide price quotes and execute trades programmatically using the same APIs as professional firms. Digital asset exchanges also provide market data feeds free of charge.
While certain exchanges provide volume-based fee rebates that favor professional trading firms, they generally do not offer co-location or other features that provide significant
competitive advantages to large players at the expense of smaller ones. In addition, since the digital asset exchange landscape is highly competitive with hundreds of active, globally accessible venues, exchanges who introduce anti-competitive features would likely lose busi- ness from individual traders and small firms who move their activities to other exchanges.
Yet despite the removal of the regulatory and competitive barriers to market making, there remains relatively few market makers compared to the proliferation of digital assets and exchanges, leading to the extreme concentration in liquidity mentioned earlier. Market makers for digital assets, primarily quantitative hedge funds and trading firms, are in high demand, evidenced by the compensation they receive from both exchanges and issuers.
Most exchanges charge higher commissions for takers (traders who fill existing price quotes) and a lower or zero commission for makers (traders who provide price quotes). Some exchanges also provide rebates to market makers that may exceed their total commissions.
Technical barriers prevent additional entrants from making markets for digital assets. Due to the highly volatile nature of digital asset prices, market makers need to utilize an au- tomated, algorithmic approach in order to stay competitive. Unlike in fiat markets where the Financial Information eXchange (FIX) Protocol provides a standardized message for- mat for electronic trading, digital asset exchange APIs vary in both format and reliability. Market making algorithms need to handle edge cases such as stale data, trade execution lag, and API downtime. Writing robust, reliable market making algorithms that can trade on multiple exchanges requires significant specialized engineering resources.
When market making is the exclusive province of large institutions, both fiat and digital markets show that liquidity becomes highly concentrated in the top assets and trading venues. Yet for tokenization to succeed and inject liquidity into formerly illiquid assets, there need to be liquidity providers who are both incentivized and equipped to make mar- kets in a wide range of tokenized assets, not just the top ones.
While direct market access and the absence of competitive barriers like co-location allow for new entrants in digital asset market making, technical barriers remain high. By lowering these technical barriers and introducing new incentive mechanisms, we enable anyone to act as a market maker for digital assets, a new model for liquidity provision that we call decentralized market making.
While market making has historically been exclusive to highly specialized professional trad- ing firms, individuals and long-term investors may actually have structural advantages in filling this function for digital assets.
Since market makers need to hold inventory for each trading pair and venue on which they provide price quotes, they need to factor in the opportunity cost of that inventory, which may be more profitably utilized in a more profitable market. Moreover, since funds and trading firms are capitalized by external investors, return on capital from market making may need to exceed 20% or greater. In thinly traded markets without the volume to support this return on capital threshold, it may not be economically rational for professional market makers to participate.
In contrast, individuals and long-term investors have lower opportunity costs. Since borrow- ing and lending markets for digital assets are still nascent, most individuals and long-term investors buy and hold them in wallets or exchanges and do not earn interest or other incremental income from them. For these investors, their return on capital threshold is 0%, and assuming risk neutrality, they should be willing market makers for any market in which they expect a positive return.
Professional market makers are less likely to have conviction on fundamental value for a digital asset; they generally approach market making from a purely technical perspective. This makes them ill-suited to make markets in illiquid, volatile assets without a lengthy record of trading activity. When prices drop sharply and approach zero, their typical recourse is liquidation.
Individual token holders and long-term investors, however, are more likely to have funda- mental conviction. Since their price floor for an digital asset is utility value (in the case of individuals) or investment valuation (in case of investors), they are better equipped to be buyers of last resort and make markets for illiquid, volatile assets.
As a first step toward enabling decentralized market making, we introduce Hummingbot, an open source software client that allows users to create and customize automated, al- gorithmic trading bots for making markets on both centralized and decentralized digital asset exchanges. Since Hummingbot needs to access sensitive digital asset private keys and exchange API keys to operate automatically, we design it as a user-operated local or hosted client, similar to a cryptocurrency mining node.
Hummingbot builds upon and extends the work of other open source market making tools for digital assets. These include exchange-specific or asset-specific tools for BitMex [6], MakerDAO’s DAI stablecoin [7], and the BitShares decentralized exchange [8].
Furthermore, other open source projects enable automated strategies for market making [9], exchange arbitrage [10], and general algorithmic trading [11] of digital assets.
Hummingbot differs from these other tools in a following areas:
1.
Exchange and asset agnostic: Hummingbot is designed to make markets
across all exchanges and all digital assets
2.
DEX compatibility: Hummingbot supports market making on decentralized ex- changes
3.
Cross exchange
market making: Hummingbot supports a strategy
that profits from differences
from liquidity between exchanges that offer markets in the same trading pair
(see Strategies
section for more details)
4.
Simpler installation and configuration: Hummingbot is designed to be installed and
used by non-technical users
In addition, smart contract-based automated market makers such as Bancor Network and Uniswap [12] provide liquidity for tokenized assets according to deterministic algorithms. Given the dynamic nature of markets, we believe that a deterministic approach alone may not provide a complete liquidity solution. We plan to integrate these services into Hummingbot as additional channels for users to both source and provide liquidity.
Individual
Hobbyists
Hummingbot is aimed at cryptocurrency enthusiasts who want to actively participate in strengthening blockchain-based networks while simultaneously earning passive income. Similar to other software clients such as a mining node in proof-of-work blockchains, a staking node in proof-of-stake blockchain, and a validator node in the Cosmos protocol, Hummingbot enables users to perform a specialized service for profit.
Long-Term
Fund Investors
In addition, Hummingbot enables crypto hedge funds and other long-term investors to utilize their inventory of digital assets for market making. In addition to providing a new, uncorrelated income stream, market making can have a positive halo effect on an existing investment portfolio since improving liquidity for an asset tends to improve price discovery and lower its risk premium.
For this user segment, we plan to offer services and paid modules that address their specific needs, such as:
•
Hosting, deployment, and maintenance
•
Integrations with portfolio and execution management systems
•
Access to historical order book data
•
Custom market making strategies
Hummingbot will enable users to automatically run a set of market making bots based on their custom parameters and strategies. In this section, we discuss the general categories of strategies that Hummingbot helps users define, parametrize, and execute.
The basic action performed by a market maker is to quote tradable bid and ask prices on a single trading venue which can be transacted by other market participants at any time (Figure 1).
Figure 1: Market maker placing orders for 1 unit of Token
Market makers periodically update these bid and ask prices to reflect factors such as changes in market conditions, trades executed, as well as inventory and resulting levels of risk exposure.
Thus, a market maker encounters a decision problem as described in the Glosten-Milgrom model [13] of dealer markets: because she must set prices in an environment where there exist informed and uninformed traders, the market maker is at an information disadvantage. In addition, a market maker acts as an intermediary between buyers and sellers, whose orders may arrive asynchronously, resulting in fluctuating amounts of inventory and risk exposure. In order to compensate for these risks, a market maker quotes a lower bid price and higher ask price, with the difference in prices referred to as the bid-ask spread :
Pbid = Pref − δbid = market maker’s price to buy assets,
Pask = Pref + δask = market maker’s
price to sell assets,
bid-ask spread = Pask −
Pbid = δbid + δask,
where Pref = reference price,
δbid = spread from reference price to bid price,
δask = spread from reference price to ask price.
An example of a market maker
transaction cycle is:
1.
A market maker simultaneously quotes both Pbid and Pask for 1 unit of Token A.
2.
At some
time t1, a trader
fills a market maker’s bid order, selling Token
A to the market maker. This decreases the market maker’s U.S. dollar
holdings by Pbid and increases his inventory of Token A.
3.
A market maker continues to hold
the additional inventory of Token A for some unknown period of time.
4.
At some
later time t2, a trader
fills the market maker’s offer order, buying Token
A from the market maker. This increases the market maker’s
holdings of U.S. dollars
by Pask1 and decreases his inventory of Token A.
The market maker therefore assumes incremental inventory risk for an indeterminate period of time, t2 − t1.
−
In the example
above, the market
maker’s profit is Pask Pbid = bid-ask spread 2. A market maker’s economic objective is to maximize the frequency of crossing trades,
completing the transaction cycles
of buying assets and selling
assets (or, conversely, for a market maker
with inventory, selling assets and
re-buying those assets) in order to capture the bid-ask spread.
Market makers bear risk because:
1.
They have to maintain inventory of
the quote currency in order to be able
to quote ask prices3, exposing
them to negative price movements;
2.
Their inventory of the quote currency may increase
at any point in time in the event that
bid orders are filled;
3.
The amount of time required to find
an offsetting trade is unknown, during which the value of held inventory may drop, and
4.
They are exposed to information disadvantage, since their trade
orders may be filled
at any time by
any trader that may have more
information than the market maker.
A market maker’s
current amount of inventory
and target level of exposure
have implica- tions on its bias for assuming more
or less risk;
naturally, the willingness of a market
maker
1Assuming no
change in prices between t1 and t2 2Ibid
3In a base case,
where shorting assets is not available to the market maker.
managing for a target level of exposure is inversely proportional to its level of holdings. The resulting bias can be expressed in the market maker’s quote through price (or spread), order size, or both:
(qcurrent > qtarget) → [(δbid > δask ∨ sbid < sask)], (1a)
(qcurrent < qtarget) → [(δbid < δask ∨ sbid > sask)], (1b)
where sbid = bid order size,
sask = ask order size,
qcurrent = current level of inventory,
qtarget = target level of exposure.
For example, a risk averse market maker (as in the case of equation (1a), where a market maker’s current holdings exceed target holdings) skews the parameters of its market orders in order to decrease the probability and/or magnitude of acquiring more inventory relative to selling inventory.
Market making is a complex optimization problem [14], in which all information known at a given point in time (including historical data) is used to generate market orders that maximize expected returns of the strategy. The basic algorithm for a market maker is to
(1) establish a reference price for the asset, and then (2) set bid and ask prices, as well as respective order sizes, for orders to be placed on the exchange.
There are multiple approaches for accomplishing both steps, and strategies must be cus- tomized to take into account characteristics of the asset as well as the market maker.
Asset price volatility Target asset exposure Risk bias Risk exposure limits Current amount of inventory Order duration Margin thresholds Quote frequency
Arbitrage trading is the strategy of capturing risk-free4 profits by simultaneously buying an asset at a lower price and selling that same asset at a higher price (Figure 2). From time to time, market dislocations may present such opportunities for a number of reasons.
Figure 2: Arbitrageur simultaneously buys and sells an
asset on different exchanges to capture $1 risk-free profit
Market
Fragmentation in Digital Asset Markets
The relatively nascent
digital asset markets
makes it susceptible to pricing dislocations due to significant market
fragmentation. There are multiple exchanges with different pockets of users: some users
may have access
to some exchanges, while others do not. In addition,
new exchanges continue to be created regularly.
4Arbitrage trading aims to
eliminate market risk or price risk. However,
there may be some residual
risks due to the logistics
of executing or settling trades,
for example risks inherent in the transfer
of assets between exchanges, or the risk of an order being filled or being canceled
prior to the arbitrageur completing that trade.
Some of the broader factors resulting in fragmented cryptocurrency markets include:
•
Centralized
exchanges versus decentralized exchanges:
– Certain traders
may not be able to trade on decentralized exchanges (e.g. due to regulatory requirements or risk
tolerance/reliability concerns) or they may not have the technical expertise
to transact in the native
technologies of the decen-
tralized exchanges, which currently are
generally more complex than transacting on centralized exchanges.
– Price quotes
and trade execution on decentralized exchanges may be subject
to delays arising from dependencies on the underlying blockchain protocols.
•
Geographically ring-fenced exchanges: exchanges in one country
may not be able to open accounts for non-nationals
of that country. Multiple exchanges
exist that are geographically dispersed, with limited or no overlap in user bases.
•
Exchange Proliferation: There currently exist over 200 cryptocurrency exchanges globally[15] with different user and asset bases,
and the ability
to move assets from one
exchange to another
(even for a user with
accounts on each
exchange) may require
complex, time-consuming processes and be subject to fees. Since exchanges may have
silo-ed user bases,
each may have different supply and demand dynamics making them
prone to dislocations.
Since exchanges may have siloed user bases, each may have different supply and demand dynamics making them prone to dislocations.
Information
Asymmetry
There may be ephemeral opportunities arising from a delay in information spreading across multiple markets, time zones, or exchanges. For example, if an account places a large buy order in one exchange which drives prices higher on that exchange, a quick-acting trader may be able to accumulate those assets at lower prices on other exchanges which have not seen that buy order, and then sell those assets at the higher prices on the original exchange. This may be observed across different geographies.
Structural
Fragmentation
In some cases, there may be persisting reasons for market dislocations arising from struc- tural or regulatory reasons. One example of this is is a persisting material pricing discrep- ancy in the Bitcoin market between Korea and the U.S. In fact, this led to a market “crash” as CoinMarketCap removed the elevated Korean exchange prices from its calculations[16]. Korean cryptocurrency prices exceeded those on U.S. exchanges due to high internal de- mand for cryptocurrencies. However, this persisted because of the challenge for Korean
nationals to open accounts in other countries as well as currency controls limiting the amount of cash sent overseas. In this example, a trader with access to both markets could buy cryptocurrencies in the U.S. and sell them in Korea and capture risk-free, arbitrage profits.
Trader / “Fat Finger” Errors
The decentralized and retail nature of cryptocurrencies coupled with the idiosyncratic pric- ing conventions and number systems used by cryptocurrencies gives rise to the possibility of trade entry errors. In addition, the increasing adoption and use of algorithmic strategies and programmatic, automated trading systems further adds to the likelihood of trade entry errors. Such large errors have been witnessed in long-established, traditional markets such as the stock markets (e.g. 2010 Flash Crash [17]). This creates the potential for arbitrage opportunities resulting from pricing errors, as a trader accepting that order may be able to offset the trade at a “normalized” price.
Challenges for Arbitrage Trading
Arbitrage trading is a very attractive trading strategy due to its guarantee of risk-free profit. However, identifying arbitrage opportunities is challenging since (1) they should not exist, as the market naturally works to eliminate such inefficiencies, (2) they are unpredictable, non-recurring, and may be small in size, (3) typically short-lived, and (4) there is high competition to identify and capture such mispricings while there can only be one winner.
Being able to consistently capture arbitrage profits depends on some form of advantage which is difficult for other market participants to replicate. Examples of such advantages may be high speed data connections between different exchanges or locations (such as “high- frequency traders” in the traditional financial markets), access to cryptocurrency exchange accounts across multiple countries, or superior technologies for constantly monitoring and detecting pricing dislocations across multiple exchanges coupled with the ability to reliably respond and execute quickly. Unlike traditional financial markets such as the stock market, the cryptocurrency market continuously trades without a defined market open or close. Searching for arbitrage opportunities requires constant monitoring.
Hummingbot arbitrage strategies will monitor multiple exchanges for any price dislocations and transact whenever a profitable trading opportunity arises. When using an arbitrage strategy, Hummingbot will act a market taker, filling the best available trade orders on different exchanges.
Hummingbot will enable the execution of multiple strategies which will be released in
stages, such as:
1. Basic arbitrage
strategies: singe trading pair on two exchanges
2.
Multiple
exchange strategy : increase likelihood of identifying arbitrage opportu- nities
by monitoring multiple exchanges
(more than two)
3.
Multiple trading pair
strategies / triangular
arbitrage : a common strategy in
foreign exchange markets, using more than a single trading pair for capturing
arbitrage. Increased complexity and additional trading
pairs increase the
likelihood of the occurrence
of a pricing dislocation.
Some of the technologies that will be part of Hummingbot’s arbitrage strategy development include:
•
Integrations with different exchanges: retrieving
order book and price
data, sending trade instructions, and (optional) rebalancing / transfers of assets between exchanges.
•
Exchange order
book analysis:
study multiple exchanges in order to try to iden-
tify highest potential for arbitrage opportunities.
Critical to the success of the arbitrage strategy will be the ability to reliably detect oppor- tunities and respond quickly.
Cross-exchange market making combines elements from both arbitrage trading and basic market making in order to profit from differences in liquidity between trading pairs from two (or more) different exchanges.
In cross-exchange market making, a market maker trades on two different exchanges and uses the best available bid and asks (Figure 3) available on one exchange (“Exchange A”, typically, a larger, highly active and liquid exchange) in order to make markets on another exchange (“Exchange B”, a smaller, less actively-traded exchange). Any time the market maker’s order is filled on Exchange B, the market maker can immediately offset this trade by filling the corresponding order on Exchange A.
The market maker enters orders on Exchange B with a margin δask relative to the best prices on Exchange A (Figure 4). For example, the best offer price on Exchange A is $101;
Figure 3: Asset is quoted on Exchange
A
Figure 4: Market maker enters orders on Exchange B
the market maker can quote an offer of $101 + δask on Exchange B, which in the example is $102.
When a trader fills the sell order on Exchange B, the market maker instantly offsets the trade by buying the asset on Exchange A (Figure 5). Since the market maker sold the asset at $102 on Exchange B and was able to simultaneously buy the asset from Exchange A for a price of $101, the market maker realizes a risk-less profit of $1.
Use Cases
Cross-exchange market making allows market makers to take a more active role in pursuing
Figure 5: Buyer on Exchange B fills Market Maker Sell Order, Market Maker Simultane- ously Buys the Asset on Exchange A
arbitrage opportunities. Whereas in pure arbitrage trading arbitrageurs search for, or wait for, pricing dislocations, cross-exchange market making allows a market maker to actively create the potential for capturing price differentials.
The strategy also enables market makers to “clone liquidity”5 from one exchange to another exchange, particularly in the case of replicating liquidity from a larger, more liquid exchange to smaller, less liquid exchanges. One example of this would be bridging liquidity from centralized exchanges to decentralized exchanges, where the user base is materially smaller.
3.3.1
Cross-Exchange Market Making Implementation Inventory Equilibrium Model
The previous example explains
cross-exchange market making in an efficient markets envi- ronment where
transferring assets across exchanges is instant and friction-less. In practice,
inter-exchange transfer of assets may be inefficient, time-consuming, incur fees, and may contribute to the existence of pricing dislocations in the first
place. For example, transfer- ring of any blockchain-based asset may require the transfer instruction being mined in a
blockchain transaction and confirmed between exchanges. Since pricing dislocations may exist only momentarily, any profitable opportunity may easily dissipate in the amount of time it would take to transfer the assets and complete both sides of the transaction.
One way to address this inefficiency is for a market maker to maintain inventories on multiple exchanges, allowing for the market maker to act immediately when presented with a profitable trading opportunity. As in the example above, the sell order on Exchange A and the buy order on Exchange B occur in the same manner as previously described, allowing the market maker to complete offsetting trades. However, in a cross-exchange, inventory equilibrium model that takes into account inter-exchange asset transfer inefficiency, the market maker would maintain balances of both U.S. dollars (the assumed quote currency of the example) and the asset on both exchanges. In executing the above transaction, no assets are immediately transferred between Exchange A and Exchange B.
In the example shown in Figure 6, the market maker has a total inventory of USD 2,000 and 20 Token A assets, equally distributed between Exchange A and Exchange B.
Figure 6: Market maker maintains an inventory on both exchanges
When a buyer takes the market maker’s sell order on Exchange B for 1 unit of Token A, the market maker simultaneously buys 1 unit of Token A on Exchange A. There is no transfer of assets between exchanges, resulting in a change in the cross-exchange distribution of the market maker’s assets. Following the trade, the market maker’s overall exposure has remained unchanged: the market maker still has an aggregate balance of 20 units of Token A, however, now with 11 units on Exchange A and 9 units on Exchange B. Meanwhile, the market maker’s total cash balance has increased by the $1 profit captured, with a new total
cash balance of $2,001, with $899 and $1,102 on Exchange A and B, respectively (Figure 7).
Figure 7: A buyer on Exchange B takes the market maker’s sell order; market maker simultaneously buys the asset on Exchange A
A fundamental difference between basic market making on a single exchange and cross- exchange market making is the requirement to maintain some amount of inventory for an indeterminate amount of time, whereas as previously discussed, basic market making generally aims to minimize the amount of inventory and the duration of holdings. While the potential to capture incremental arbitrage trading profits increases the expected value of a portfolio, the market maker does retain market and price risk.
The ideal user for such a strategy would be a market maker that has a fundamental invest- ment thesis for the asset and is a long-term holder of the asset. Deploying a cross-exchange market making strategy can provide a market maker with incremental, additive returns without a fundamental change in risk profile as compared to a passive, buy-and-hold strat- egy.
By encapsulating market making algorithms and a trade execution engine in an open-source application available to non-technical users, Hummingbot enables a much wider range of individuals and companies to potentially earn income from running market maker nodes that provide liquidity to crypto-asset pairs that trade on various exchanges.
Hummingbot will effectively be a trading engine to execute transactions with the param- eters provided by users, abstracting some the technical complexities of transacting with centralized and decentralized exchanges, each with their own non-standardized technical specifications. Hummingbot will facilitate trade execution and interaction with different exchanges, performing actions such as price and order book retrieval, submission of trade instructions, and, if specified by the user, handle asset transfers for functions such as re- balancing across different exchange accounts.
The Hummingbot architecture and operation are similar to the operation of open-source, blockchain protocol nodes (Figure 8).
1.
Bot installation : users
download the code
from a public,
open-source code reposi- tory and install the
program locally, either
on their local
machine or on a cloud-hosted remote server.
2.
Program execution : users execute the Hummingbot program either through com- mand line commands or a graphical
user interface (GUI).
3.
Private information (such
as wallet private keys and exchange API keys): are encrypted and stored locally on a user’s machine.
4.
Bot activity and transaction logs: stored on a local database.
5.
Data feeds:
the program connects to blockchains, decentralized exchange APIs, and
centralized exchange APIs to retrieve data, such as market prices and order book data, as well as user specific data
such as asset balances, existing orders and status.
6.
Centralized exchange commands:
the bot uses locally stored
API keys to create
API requests for interacting with centralized exchanges for the retrieval
of information as well as for sending user instructions.
7.
Decentralized exchange commands:
the bot uses the locally
stored wallet key to
sign transactions which are then sent to a blockchain node for execution.
Figure 8: Hummingbot Architecture
Similar to the cryptocurrency market, its associated infrastructure is relatively nascent. In recent months, there have been hundreds of new exchanges created, with limited track records and deploying new, relatively untested technologies. A primary engineering task in the development of Hummingbot is in making it reliable and capable of handling extrinsic failures, some arising from idiosyncratic risks of the cryptocurrency market.
Risk Mitigation for Interexchange
Trading When trading across different exchanges,
it is critical to coordinate transactions across different exchanges, particularly when they are related transactions, such as the offsetting transactions used in arbitrage trading and cross- exchange market making. This is further complicated the use of decentralized exchanges, where there is increased potential of delays in the execution of transactions (e.g. waiting for block confirmations or block reorganizations). An example of the risk of coordination is one leg of traded being executed on one exchange (Exchange B), while in the interim, the offsetting hedging transaction on another exchange (Exchange A) on which that trade was based has gone away (e.g. trade was filled by a third party or orders were withdrawn).
Risk
mitigation:
•
Increase spread buffer for transactions
•
Analysis on speed of transactions on exchanges
•
Order book
depth analysis to optimize trade parameters and account for contingencies (e.g.
taking next best orders)
•
Sourcing offsetting transactions from multiple exchanges
Exchange
Reliability
Unlike the more established exchanges of financial markets, cryptocurrency exchanges have, in their short history, experienced service disruptions. Even some of the major centralized cryptocurrency exchanges have experienced service outages, some for as long as several days [18]. For decentralized exchanges, one additional risk is the occurrence of blockchain congestion [19], while technology changes (e.g. the change in API specifications) can disrupt any software depending on those services.
Risk mitigation:
•
Constant monitoring and reporting of exchange status
•
Flexibility to relocate
trading to different
exchanges
•
Information redundancy (e.g. multiple sources for
asset price feeds)
The initial release of Hummingbot will focus on the cross-exchange market making strategy between a centralized exchange and a decentralized exchange.
Ongoing development will add additional features:
•
Support for additional centralized exchanges
•
Support for additional decentralized exchanges
•
Centralized to centralized exchange market making
•
Stand-alone arbitrage trading or overlay to
market making strategy (e.g. execute taker transactions whenever an trading
opportunity exists)
•
Support for multiple
exchanges (more than two)
Pure market making strategies for making markets for a single asset on a single exchange.
Provide the capabilities for customized user strategies.
•
Initial focus on cross-exchange market making for
decentralized exchanges
•
Add other strategies over time
•
Custom strategies: users can also write their own strategies
When employing a cross-exchange market making strategy, it is increasingly likely with the passage of time that an imbalance in the direction of trading flows will accumulate. In the example above, if higher price levels persist on Exchange B, there will come some point in time where either the market maker’s holdings of Token A on Exchange B and US Dollars on Exchange A will be depleted, or both. This creates the need to rebalance and redistribute assets across exchanges.
Rebalancing can be automated and incorporated into the trading bot strategy, by specifying minimum asset balance thresholds that trigger a rebalancing. Rebalancing is carried out by the bot initiating asset transfers between exchanges.
[1]
Johannes A Skjeltorp and Bernt Arne Ødegaard. Why do listed firms pay for market making in their own stock? March 2013.
[2]
All
Cryptocurrencies. https://coinmarketcap.com/all/views/all/, 2018. [Online;
accessed 30-November-2018].
[3] Committee on Oversight and Government Reform. How Roadblocks
in Public Markets Prevent Job Creation
on Main Street. House of Representatives, November
2011.
[4]
How to Become a Market Maker. http://www.nasdaqtrader.com/Trader.aspx?id= marketmakerprocess,
2018. [Online; accessed 20-November-2018].
[5] Gregory Meyer, Nicole Bullock
and Joe Rennison. How high-frequency trading
hit a speed bump. Financial Times, January 2018.
[6]
BitMex. https://github.com/BitMEX/sample-market-maker, 2018. [Online; ac- cessed 17-December-2018].
[7]
MakerDAO. https://github.com/makerdao/market-maker-keeper, 2018. [Online;
accessed 17-December-2018].
[8] Codaone. https://github.com/Codaone/DEXBot, 2018. [Online; accessed 17-
December-2018].
[9]
Tribeca. https://github.com/michaelgrosner/tribeca, 2018. [Online; accessed 17-December-2018].
[10] Blackbird. https://github.com/butor/blackbird, 2018. [Online; accessed 17- December-2018].
[11] Gekko. https://github.com/askmike/gekko, 2018. [Online; accessed 17-December- 2018].
[12] Cyrus Younessi. A
Unique Exchange<EMAIL_ADDRESS>uniswap-a-unique-exchange-f4ef44f807bf, 2018. [Online; accessed 17-December- 2018].
[13] L.R. Glosten
and P.R. Milgrom. Bid,
Ask and Transaction Prices in a Specialist Market with
Heterogeneously Informed Traders. Journal of Financial Economics,
14:71–100, 1985.
[14] Gu´eant,
O., Lehalle,
C.-A., &
Fernandez-Tapia, J. Dealing
with the
inventory risk: a
solution to the market making problem. Mathematics
and Financial Economics, 7(4):477–507, 2013.
[15] coin.market. Cryptocurrency Market Capitalizations. https://coin.market/coins/ info, 2018. [Online; accessed 17-December-2018].
[16] David
Z. Morris. Cryptocurrency Markets Shocked as CoinMarketCap Removes Korean
Exchange Prices Without Warning. http://fortune.com/2018/01/08/ coinmarketcap-removes-korean-exchange-prices/, 2018. [Online; accessed 17- December-2018].
[17] Wikipedia. 2010 Flash Crash. https://en.wikipedia.org/wiki/2010_Flash_ Crash.
[Online; accessed 17-December-2018].
[18] Fortune. Kraken Bitcoin Exchange Reopens
After Two Anxious Days. http:// fortune.com/2018/01/14/kraken-bitcoin-exchange-reopens/. [Online; accessed 24-December-2018].
[19] Coindesk. Loveable Digital Kittens Are Clogging Ethereum’s Blockchain. https://www.coindesk.com/
loveable-digital-kittens-clogging-ethereums-blockchain. [Online; accessed 24-December-2018].


{{- partial "header.html" . -}}
This is the Single template in the Hugo Three layouts/releases folder.


John Snow's Portfolio
Hi!
I'm
Princess
a
Graphic Designer
PR
O
FILE
Some background information about me
RE
S
UME
Something about my experience and skills.
PORT
F
OLIO
A collection of my work
CO
N
TACT
Say hello or find me.


Team Lead - Alex King
Alex is a software developer from Seattle with a love of coffee,
pleasant user experience, and intentionality. His dedication to
teamwork and passion for delivering solid solutions for everyday
problems were a driving force behind Potluck Planner's
development.
Web UI developer I - Connor McNamee
Connor is a web developer from Massachusetts with an eye for design and a passion for art and video games. Connor's talent with CSS was a major contribution to the Potluck team.
Web UI Developer II - Britt Moyers
Britt is a web developer from Tennessee with a flair for the dramatic and a strong desire to build cool things. When not at the computer, you'll find Britt crafting campaign settings, characters, and tools for the world of Tabletop RPGs.
Front End Architect I - Cassandra Springer
An aspiring entrepreneur as well as a developer, Cassandra's big dreams are matched only by her talent. Her creativity and passion for a broad range of topics - from animals to health and even design - shows in her ever-growing body of top-notch work.
Front End Architect II - Ang Xu
Ang is a Texas based devloper with a background in finance. His time at Lambda has sharpened Ang's unparalleled technical skills; his dream is to take those skills back into the finance world to develop tomorrow's cutting edge, financial technology.
Backend Architect - Erik Sandoval
A developer from southern California, Erik's solid contributions are the backbone of Potluck Planner. When not programming, Erik enjoys gaming and learning about retro Nintendo products.


When do the Argos Black Friday deals start?
Black Friday is nearly here, and with it plenty of shops are lining up to give customers the best deals of the year.
There are some easy hacks to follow to get the most out of the sales, but nothing beats preparation.
Knowing when the sales start gives a helpful head-start, so when does the Argos Black Friday sale start?
Has the Argos Black Friday sale started?
Argos’ Black Friday deals started on Friday 22 November.
Their deals are available online and in-store from now until Cyber Monday.
From TVs to laptops, Dysons to Dre headphones, there are plenty of deals to enjoy.
Argos Black Friday deals already on sale
There could be plenty more added in the run up to Black Friday, but take a look at what’s already available.
Tech
Lenovo IdeaPad S145 15.6 Inch Pentium 4GB 128GB Laptop – Grey – was £299.99, now £199.99
Hitachi 50 Inch 50HK25T74U Smart 4K LED TV – was £369.99, now £249.99
Amazon Fire TV Stick with Alexa Voice Remote – was £39.95, now £19.95
Household
Advertisement Advertisement
Dyson V7 Motorhead Extra Cordless Vacuum Cleaner – was £299.99, now £199.99
Bush MSBSNFWTDW American Fridge Freezer – White – was £529.99, now £399.99
Health and Beauty
Philips Series 3000 Wet and Dry Electric Shaver S3580/06 – was £45.99, now £39.99
Barry M Nail Paint Gift Set x 30 – was £59.99, now £29.99
STAR20 deals
Quote STAR20 in-store or in the online checkout to get 20% off a range of Frozen, Marvel and Star Wars toys until Wednesday 26 November – ideal for parents looking for stocking fillers.
When is Black Friday?
Black Friday 2019 isn’t until 29 November, but many shops like Argos have already started rolling out deals a whole week early.
They aren’t the only ones to do so – you can save on skincare with DECIEM’s 23% off everything all month and NOW TV have launched plenty of early deals.


@main("Playflow") {
| METHOD | URL | DESCRIPTION | RETURNS | PARAMETERS |
|---|---|---|---|---|
| GET | /api/projects | lists all active projects | JSON workItems | url: 'state' (initial, in_process, completed) |
| GET | /api/projects/:projectId | gets one project | JSON workItem | |
| POST | /api/projects | creates a new project | JSON workItem | body: new project JSON |
| PUT | /api/projects/:projectId | updates a project | JSON workItem | body: project JSON to update |
| DELETE | /api/projects/:projectId | deletes project | ||
| POST | /api/projects/:projectId/assign | assigns a project to a factory (unassigns for null 'factoryId') | JSON workItem | url: 'factoryId', 'transitionerId', 'comment' |
| METHOD | URL | DESCRIPTION | RETURNS | PARAMETERS |
|---|---|---|---|---|
| GET | /api/workItems | lists active workItems | JSON workItems | url: 'projectId', 'assigneeId', 'stationId', 'state' (initial, unassigned, in_process, processed, completed) |
| GET | /api/workItems/:workItemId | get single workItem | JSON workItem | |
| POST | /api/workItems | creates a new workItem | JSON workItem | body: new workItem JSON |
| PUT | /api/workItems/:workItemId | updates a workItem | JSON workItem | body: workItem JSON to update |
| DELETE | /api/workItems/:workItemId | deletes workItem | ||
| POST | /api/workItems/:workItemId/assign | assigns a workItem to a user (unassigns for null 'assigneeId') | JSON workItem | url: 'assigneeId', 'transitionerId', 'comment' |
| POST | /api/workItems/:workItemId/process | indicates that a workItem has been processed | JSON workItem | url: 'transitionerId', 'comment' |
| POST | /api/workItems/:workItemId/next | moves a workItem to the next station (out of all stations for null 'nextStationId') | JSON workItem | url: 'nextStationId', 'transitionerId', 'comment' |
| METHOD | URL | DESCRIPTION | RETURNS | PARAMETERS |
|---|---|---|---|---|
| GET | /api/workItems/:workItemId/history | gets history of workItem state transitions | JSON workItemStateTransitions |
| METHOD | URL | DESCRIPTION | RETURNS | PARAMETERS |
|---|---|---|---|---|
| GET | /api/factories | lists active factories | JSON factories | |
| GET | /api/factories/:factoryId | get single factory | JSON factory | |
| POST | /api/factories | creates a new factory | JSON factory | body: new factory JSON |
| PUT | /api/factories/:factoryId | updates a factory | JSON factory | body: factory JSON to update |
| DELETE | /api/factories/:factoryId | deletes factory |
| METHOD | URL | DESCRIPTION | RETURNS | PARAMETERS |
|---|---|---|---|---|
| GET | /api/stations | lists active stations | JSON stations | url: 'factoryId', 'projectId', 'workerId' |
| GET | /api/stations/:stationId | get single station | JSON station | |
| POST | /api/stations | creates a new station | JSON station | body: new station JSON |
| PUT | /api/stations/:stationId | updates a station | JSON station | body: station JSON to update |
| DELETE | /api/stations/:stationId | deletes station |
| METHOD | URL | DESCRIPTION | RETURNS | PARAMETERS |
|---|---|---|---|---|
| GET | /api/users | lists active users | JSON users | |
| GET | /api/users/:userId | get single user | JSON user | |
| POST | /api/users | creates a new user | JSON user | body: new user JSON |
| PUT | /api/users/:userId | updates a user | JSON user | body: user JSON to update |
| DELETE | /api/users/:userId | deletes user |


Elementos
OK
OK
Cores
OK
OK
OK
OK
OK
OK
OK
OK
OK
Cores
OK
OK
OK
OK
OK
OK
OK
OK
Tamanho
OK
OK
OK
Desativado
OK
OK
OK


class: center, middle, inverse, title-slide # Recap I ### Geneva R Bootcamp
www.therbootcamp.com
### November 2018 --- layout: true
 Geneva, November 2018                                           www.therbootcamp.com
 --- # Essentials: The 24 Lessons of the R Bootcamp .pull-left4[ 1. Everything is an object 2. Use `<-` to create/change objects 3. Name objects using `_` 4. Objects have classes 5. Everything happens through functions 6. Functions have (default) arguments 7. Functions expect certain object classes 8. View help files using `?` 9. Study errors and warnings 10. Data is stored in data frames 11. Select variables (vectors) using `$` 12. Use RStudio and projects 13. Use editor and shortcuts 14. First load packages and data 15. Use auto-complete 16. Comment and format for readability ] --- # 3 Object types for data .pull-left4[ R has 3 main data objects... <high>`list`</high> - R's multi-purpose container - Can carry any data, incl. lists - Often used for function outputs <high>`data_frame`</high> - R's spreadsheet - Specific type of `list` - Typical data format - For multi-variable data sets <high>`vectors`</high> - R's data container - Actually carries the data - Contain data of 1 of many types ] .pull-right55[  ] --- .pull-left4[ # Functions Functions have 3 elements: 1 - <high>Name</high>: Used to refer to the function and call (execute) it. 2 - <high>Arguments</high>: Used to provide (data) inputs and to control what the function does. Arguments with default values (e.g., `use = "everything"`) need not be specified. Arguments without default values (e.g., `x`) need be specified. <high>Inputs must have the appropriate class!</high> 3 - <high>Body</high>: The code that uses the inputs (arguments) to produce the desired output. The code of the functions body is based <high>copies of the inputs</high>, which are named according to the arguments names. ] .pull-right55[

  ] --- # Documentation .pull-left5[ R documentation (<high>help files</high> and <high>vignettes</high>) will become very to use once you are familiar with the basic R vocabulary. Pay attention to... <high>Usage</high> - shows how to use function, its arguments and their defaults.
<high>Arguments</high> - describes arguments, and their `class`.
<high>Value</high> - describes what the function returns.
<high>Examples</high> - provide working R code. ```r # To access help files ?name_of_function # search help files ??name_of_function ``` ] .pull-right5[ ```r ?cor ```

 ] --- # The almighty `tidyverse` Among its many packages, R newly contains a collection of high-performance, user-friendly packages (libraries) known as the [tidyverse](https://www.tidyverse.org/). The tidyverse includes: 1. `ggplot2` -- creating graphics. 2. `dplyr` -- data manipulation. 3. `tidyr` -- tidying data. 4. `readr` -- read wild data. 5. `purrr` -- functional programming. 6. `tibble` -- modern data frame.

  --- .pull-left35[

 <hfont><high>Questions?</high></hfont>
 Link to schedule
 ] .pull-right6[  ]


Component libraries for web application frameworks often need to provide resource files along with implementation classes. For example, JavaServer Faces Renderers often need JavaScript, CSS and image resources.
Although dropping in an implementation JAR does make these components libraries available, the resource files must be extracted into the web application root.
This can easily lead to inconsistency problems between implementation code and resource files.
Weblets aims to solve this problem, without placing undue burden on the application developer. Although JavaServer Faces is mentioned as an explicit example. Weblets aims to solve the general problem in a non-Faces-specific way, and then provide an integration with Faces.
This users documentation should help you to easily get started with Weblets and should give a short introduction into the usage of this small but hopefully helpful project.


| �ӿ� | ˵�� |
|---|---|
| Resolver |
A resolver interface that can resolver various types of addresses and
specific protocol numbers and types to a human readable name.
|
| �� | ˵�� |
|---|---|
| AbstractResolver |
Default adaptor class for Resovler interface.
|
| AbstractResolver.TimeoutEntry |
Internal class that keeps track of timeout and which key to time out.
|
| IEEEOuiPrefixResolver |
A resolver that resolves the first 3 bytes of a MAC address to a manufacturer
code.
|
| IpResolver |
A resolver object that knows how to convert IP addresses into hostnames.
|
| ö�� | ˵�� |
|---|---|
| Resolver.ResolverType |
Type of resolver that can be registered with JRegistry.
|


{% extends "base.html" %} {% import "bootstrap/wtf.html" as wtf %} {% block title %}JeffPD - Administrator{% endblock %} {% block page_content %}
Hello, {% if current_user.is_authenticated() %}{{ current_user.first_name }}{% else %}Stranger{% endif %}!
Use this page to checkout all the logs {{ teacher.first_name }} {{teacher.last_name }} has had created about him/her!
| Teacher | Coach | Date / Time | What coach did | What coach is doing next | Minutes logged | Tags | Send coach a message about this? |
|---|---|---|---|---|---|---|---|
| {{ teacher.first_name }} {{teacher.last_name }} | {{ log.coach.first_name }} {{ log.coach.last_name }} | {{ log.timestamp.strftime("%Y-%m-%d %H:%M") }} | {{ log.body }} | {{ log.next }} | {{ log.time }} | {% for tag in log.tags %} {{ tag.name }}, {% endfor %} | {{ log.coach.email }} |


Creates a stripes background pattern. - Use `background-color` to set a white background. - Use `background-image` with a `radial-gradient()` value to create a vertical stripe. - Use `background-size` to specify the pattern's size. - **Note:** The fixed `height` and `width` of the element is for demonstration purposes only.


Under head coach Ali Johnstone in just her second year at the helm, the Bobcats finished the season above .500 for the first time since 2012, and Johnstone only expected things to improve in 2020.
Except Ohio didn’t play in 2020, thanks to circumstances beyond its control. COVID-19 forced the Mid-American Conference to push back the start of fall sports prior to the usual start of the season, and the Bobcats didn’t begin their season until the next spring. When the season finally began, Johnstone didn’t see her players get the experience they were supposed to have.
Johnstone had plenty to say about her players and what they went through. The emotional toll of the season was clear to her as someone who wants the best for her players.
“It was not fun to watch the team go through that,” Johnstone said. “It was just really, really, really tough mentally and trying to get everybody on the same page.”
Instead of playing the sport they came to Athens to play, the Bobcats instead had to spend most of their day inside of their dorms and houses focusing on their classes. Some had to experience this as freshmen or all the way from countries like Germany or New Zealand. These players had flown across the world to play field hockey, but Johnstone wasn’t even allowed to see them.
The Bobcats were ready to make sacrifices and take risks, but that alone didn’t keep morale high.
“Just trying to keep the positivity and the morale up through to the end was pretty difficult with everyone being completely burnt out by the end,” Johnstone said.
Most of the players’ time outside was for practice and warming up for games. Even then, practice wasn’t quite what it used to be.
In the winter, when the team trained in Ping Recreation Center, the Bobcats couldn’t train together and instead had to train in separate groups. Team meetings were relegated to Zoom calls. The team wasn’t together, and motivation was at an all time low.
A lack of team chemistry makes wins that much more difficult to earn.
“When you get frustrated and try and play individually and take it to the next level without using your teammates,” Johnstone said. “Things don’t look so great.”
The combination of the stress from school and the strange circumstances around COVID-19 took a toll on the Bobcats’ performance, which shows in their disappointing 5-9 overall record in 2021. Now, Johnstone only wants her players to get over the burnout from this season.
“What I want them to reflect on is really understanding what everybody has gone through this last year and what they did accomplish,” Johnstone said. “Nothing in the win column, obviously, but in the fact that we played four games down and people are in and out of quarantine and bouncing back from losing games.”
Johnstone hopes that things will be back to normal come fall. She wants her team to be able to talk about things other than COVID-19 and for the Bobcats to feel like a team again.
There were signs of unity throughout the season. Ohio’s best games, such as its wins over Ball State and Longwood, showed the team was still on the same page.
“When you're playing hard and you're playing hard for the person next to you,” Johnstone said. “(That) is when you really start to play some good hockey.”
Ohio was also able to end the season on a high note with two wins against Bellarmine. The Bobcats already knew there was no shot to win the MAC and the games were right before finals week. The Bobcats were exhausted.
“We knew we’re not winning a MAC Championship at that point,” Johnstone said. “And they’re still holding it in and literally working their tails off.”
Not all seniors get to walk away with a win, which is why Johnstone was happy to see her graduating players have one final highlight after what had been a burning season for them. There’s always hope for next year to be consistent and for a return to normal, but for now Johnstone just wants her players to take a well-earned rest.
“The only way to come back ready is to take a complete break and reevaluate,” Johnstone said.


Over the last few weeks I have been investigating how to reduce the write load of emoncms to explore if it might be possible to achieve long term logging on SD cards.
A brief summary
Through a mix of buffered writing of feed data to disk, reduction of the number of meta and average data files written to and use of the FAT filesystem, my home raspberrypi now has a write load of 0.4kb_wrtn/s down from 197kb_wrtn/s.. almost 500x less and the writes are all append only (there's no regular writing of the same part of a file again and again). The question is could this mean years of SD card logging rather than months?
Write buffering
A single Emoncms PHPFina (PHP Fixed Interval No averaging) or PHPTimeSeries datapoint uses between 4 and 9 bytes. The write load on the disk however is a bit more complicated than that. Most filesystems and disk's have a minimum IO size that is much larger than 4-9 bytes, on a FAT filesystem the minimum IO size is 512 bytes this means that if you try and write 4 bytes the operation will actually cause 512 bytes of write load. But its not just the datafile that gets written to, every file has inode meta data which can also result in a further 512 bytes of write load. A single 4 byte write can therefore cause 1kb of write load.
By buffering writes for as long as we can in memory and then writing in larger blocks its possible to reduce the write load significantly. The full investigation with a lot of benchmarking of different configurations including differences between FAT and Ext4 can be found here:
https://github.com/openenergymonitor/documentation/blob/master/BuildingB...
A minimal version of emoncms in python
To make the investigation easier I simplified emoncms down to the core parts needed on a raspberrypi to get basic timeseries graphing: serial listener, node decoder, basic feed engine and a ui consisting of a nodelist and a single rawdata visualisation type and wrote the result in python making use of Jerome and Paul's (pb66) excellent work on the emonhub serial listener and node decoder.
Here's a diagram of the main components of the python app:
And some screenshots of what it looks like:
Node list:
Basic graphing:
The source code and an installation guide for this minimal python version of emoncms can be found here:
https://github.com/emoncms/development/tree/master/experimental/emon-py
I posted on the EmonHub issues list about this on friday and I've been having a bit of a discussion there with Paul https://github.com/emonhub/emonhub/issues/48
Interested to hear people's thoughts on it.
Further development questions (copied from the end of the write load investigation page)
Is the reduced write load and longer SD card lifespan that might result from using the FAT filesystem worth the increased chance of data corruption from power failure that Ext4 might prevent?
It would be interesting to compare the performance of the FAT filesystem + 5 min application based commit time with the EXT4 filesystem with Journaling turned off and filesystem delayed allocation set to 5 min instead of write buffering in the application.
Re: Reducing emoncms write load for long term SD card logging and a minimal python version of emoncms
Done some further testing with the Ext2 filesystem this time which is a non-journaling filesystem, the results appear to be exactly the same as Ext4 suggesting that journaling is not as large a source of write load as I initially thought and that the main difference between the write load on FAT vs Ext4/Ext2 is probably the block size 512 vs 4096 which sounds logical to me.
Re: Reducing emoncms write load for long term SD card logging and a minimal python version of emoncms
Looking into it, its possible to set the Ext2/3/4 filesystem blocksize to 1024 rather than 4096. After backing up the 3rd data partition on the sd card I just ran:
sudo umount /dev/mmcblk0p3
sudo mkfs.ext4 -b 1024 /dev/mmcblk0p3
sudo mount -a
Copied the data back on to it, it then takes a while for the Ext4 partition to fully setup (there's a process in the background called ext4lazyinit that writes quite heavily for a few minutes) But after it finishes the write load drops to ~1.4 kb_wrtn/s down from ~3.2 kb_wrtn/s.
So potentially a 2x reduction by dropping the block size from 4096 to 1024 on Ext4.
The FAT filesystem with a blocksize of 512 bytes writes at 0.4 kb_wrtn/s for the same commit rate and number of feeds.
Re: Reducing emoncms write load for long term SD card logging and a minimal python version of emoncms
Hi, really nice work with reducing the write load! I'm currently testing your low write load-image and till now it seems to be all fine.
Just a little question: the feeds "Input on-time" and "Power to kwhd" seems not present in this version. Can I add them anyhow?
Or is there another way to count the on-time of an input?
Re: Reducing emoncms write load for long term SD card logging and a minimal python version of emoncms
simsasaile: I will try and do a blog post on this, the approach for the calculation of kwhd is different so instead of calculating daily values you instead either calculate accumulating watt hours on the emontx or use the power to kwh input processor. That generates an every increasing graph. You can then use either the myelectric page which pulls out the daily values or the newly update bargraph visualisation which has under vis > bargraph a property called delta, if you set that to 1 it will calculate the difference between the total watt hours of each day giving you daily watt hours.
The input on time process needs to be re-implemented in the same way producing an accumulating graph but there isnt a process to produce that accumulating graph yet of on-time.
The reason for the change is that the low write image feed engines are append only which makes the buffering mechanism easier to implement and helps to reduce the amount of writes to the same sectors on the disk. But a move to calculating daily data on the fly from accumulating graphs provides its own advantages too as you can pull out daily totals at any timezone, or you can extract hourly, or monthly totals too.
Re: Reducing emoncms write load for long term SD card logging and a minimal python version of emoncms
Hi Trystan,
thanks for your really fast reply and the help! I'm glad there is a way (or even two) to calculate the kWh/d-values the on-time is not so important.
Cheers, Simsasaile
Re: Reducing emoncms write load for long term SD card logging and a minimal python version of emoncms
Hi,
I would like to test the new emonSD-13-08-14 image on my Raspberry model B.
One can see here that this ready-to-go SD card image has been tested to work on the new model B+.
Will it work on my RPI model B ?
Thank's
Eric
Re: Reducing emoncms write load for long term SD card logging and a minimal python version of emoncms
Hi Eric, Yes it will work on either.
Paul
Re: Reducing emoncms write load for long term SD card logging and a minimal python version of emoncms
Thank's Paul.
I did a try and it works as expected on the model B.
Some points that may be added in this great guide :
- how to expand the file system (I 'm using a 8 Go sd card)
- how to modify the mysql root password (it's only mentioned how to modify the root password and the ssh password)
In this low write buffer version, there is no kwh/d and history processes. I'm wondering why these processes (and its associated engines) have not been implemented yet in this version.
Is it because one can't reduce the disk write load when using these engines/processes ?
Or is it because it was not needed to implement these engines/processes to validate the low write buffer approach ?
Regards,
Eric
Re: Reducing emoncms write load for long term SD card logging and a minimal python version of emoncms
this is great job. I was looking for something like this to make my SD card last. Thanks a lot and hope to get more updates from this :D
Re: Reducing emoncms write load for long term SD card logging and a minimal python version of emoncms
Hello Eric, the main reason for not yet implementing the power to kwh/d input processors is that the way the buffer works in the low write version means the writes can only be append only. It would be great to improve on this initial implementation to support editing/updating last or order datapoints, It's in the development plan I started writing here https://github.com/emoncms/emoncms/issues/244
The need however for power to kwh/d input processors is reduced however as you can now either calculate accumulating watt hours on the emontx or use the power to kwh input processor to generate an ever increasing watt hour graph. The myelectric page and new version of the bar graph visualisation can then pull out daily/monthly/any time division totals with the plus point of being able to do this at any timezone the user wishes at visualization time rather than pre-storage.
There's some more on this here: http://openenergymonitor.org/emon/node/3995
Trystan
Re: Reducing emoncms write load for long term SD card logging and a minimal python version of emoncms
Hi,
Thank's for replying Trystan. I understand that the need for kwh/d input processes is reduced but it will still be needed in some case. As a example to plot a multigraph that use both dayly and instantaneous data. (See attached). EDIT : kwh/D also needed for the zoom graph which is a very nice graph.
I have difficulties in using the new version of the bar graph visualization. On EmonCMS.org, I tried to plot the kwh used per day in my home but I got a wrong graph (See attached). I guess I'm using a wrong config (See attached). Is there a documentation on how to use that new bar graph vis ?
Eric
Re: Reducing emoncms write load for long term SD card logging and a minimal python version of emoncms
Eric,
for me the daily kWh bargraph works if I set the delta to 1. Don't ask why (or what the delta value means). Probably 1 for 'Yes'?
Jörg.
PS: and the description behind the edit fields is shifted. So behind the Delta setting there should be the description 'Show diff (Wh feeds)'. Then it makes sense that 1 means YES.
Re: Reducing emoncms write load for long term SD card logging and a minimal python version of emoncms
Yes need to improve documentation and naming there, ideally have a dropdown for yes/no. Delta for show difference between each bar.


Our Incridable Team Members
During this project we knew that our members completes each other, long sleepless nights and hardword but at the end it will pay off, below we are introducing our team members:
During this project we knew that our members completes each other, long sleepless nights and hardword but at the end it will pay off, below we are introducing our team members:


API
–
API & Web Service
–
HTTP
–
XML
–
JSON
–
SOAP
–
REST
Hi there!
This is HTML5 Boilerplate with
404 Page
.


About
Product
Blog
Career
Log In
Sign Up
Log In
Sign Up
About
Product
Blog
Career
Members of The Team
Thomas Hessburg
Team Lead
Hamidou Diallo
UI Developer
Lily Zhou
UI Developer
Anthony Piazza
Front End Developer
Dwayne Pearson
Back End Developer


laraveleg\options
You can create options, reuse them and rely on them at a later time. Inspired by the WordPress system and built on the Laravel
framework.
Install
composer require laraveleg/options
Usage
You can manage options in a simple way by helpers.
Cache Mode
add_option
You can add an option through the following line :-
add_option($key, $value, $expiration);
$key
: The option ID that you will use to fetch its value.
$value
: Put the value of any type of data.
$expiration
: Expiration date. This can be unused and saved all the time. Ex: add_option($key, $value)
.
get_option
Fetching value for a specific option :-
get_option($key, $default)
$key
: The option ID.
$default
: You can specify a default value if the option is not found.
has_option
Make sure the option is there :-
has_option($key)
$key
: The option ID.
remove_option
You can delete any option :-
remove_option($key)
$key
: The option ID.
Eloquent Mode
You can put the settings to a specific element in a specific model.
Set config
Go to laraveloptions.php
file in configs directory
'eloquent_mode' => true, // Enable Eloquent Mode
Use for model
Add the trait in your specific model.
use LaravelEG\LaravelOptions\Traits\LaravelOptionEloquentMode;
class Unit extends Model
{
use LaravelOptionEloquentMode;
add_option
You can add an option through the following line :-
$unit = Unit::find(1);
$unit->addOption($key, $value, $expiration);
$key
: The option ID that you will use to fetch its value.
$value
: Put the value of any type of data.
$expiration
: Expiration date. This can be unused and saved all the time. Ex: add_option($key, $value)
.
get_option
Fetching value for a specific option :-
$unit = Unit::find(1);
$unit->getOption($key, $default)
$key
: The option ID.
$default
: You can specify a default value if the option is not found.
has_option
Make sure the option is there :-
$unit = Unit::find(1);
$unit->hasOption($key)
$key
: The option ID.
remove_option
You can delete any option :-
$unit = Unit::find(1);
$unit->removeOption($key)
$key
: The option ID.
You an use this
Trait
in any model on your app.
Testing
Run the tests with:
vendor/bin/phpunit
Contributing
Please see CONTRIBUTING for details.
Security
If you discover any security-related issues, please email<EMAIL_ADDRESS>instead of using the issue tracker.
License
The MIT License (MIT). Please see License File for more information.


It looks like you have taken an interest in either learning or training yourself in Web-security.
You have taken the first step in this path, as a token of appreciation here's your first flag => web-sec{th1s_is_th3_w3lc0m3_fl4g}
As a reminder, unless otherwise noted all our flags are in the format -- web-sec{some_text_here}
As you are starting out in the Security field we would recommend you to read The Hacker Manifesto
P.S: Ignore the bad HTML and CSS


Compliment Keeper
This looks like a nice place to put a compliment...
Enter it here:
Save it
Delete Last Compliment
Reset
Saved Compliments
{% for post in posts %} {% block post %}
{{post.body}}
{% endblock %} {% endfor %}


--- title: LiveHTTPHeaders version 0.13.1 is available! date: 2006-11-13 23:57:15 +1100 modified: 2006-11-14 10:57:15 +1100 uid: http://paul.annesley.cc/articles/2006/11/14/livehttpheaders-version-0131-is-available layout: post ---
LiveHTTPHeaders has finally been released for Firefox 2.0


|
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object atg.security.SecurityConfiguration
Configuration information that defines all of the elements needed to create and manage access control lists for an object.
| Field Summary | |
static java.lang.String |
CLASS_VERSION
|
| Constructor Summary | |
SecurityConfiguration()
Creates a new, unconfigured, security configuration object. |
|
SecurityConfiguration(SecurityConfiguration pConfig)
Copies a security configuration. |
|
SecurityConfiguration(SecurityConfiguration pConfiguration,
AccessRight[] pAccessRights,
java.util.Map pAccessRightsMap)
Creates a new security configuration object out of an existing security configuration, replacing its access rights and map with the specified rights and map. |
|
SecurityConfiguration(SecurityPolicy pPolicy,
UserAuthority pUserAuthority,
AccessRight[] pAccessRights,
java.util.Map pAccessRightsMap)
Creates a new security configuration object using the indicated list of access rights and associated map. |
| Method Summary | |
AccessRight[] |
getAccessRights()
Returns a list of access rights that are appropriate for the object. |
java.util.Map |
getAccessRightsMap()
Returns a mapping of access rights by name. |
SecurityPolicy |
getSecurityPolicy()
Returns the security policy that is in effect in this configuration. |
UserAuthority |
getUserAuthority()
Returns the user authority for converting an account name to a persona that may be used in an access control list. |
void |
setAccessRights(AccessRight[] pAccessRights)
Changes the list of access rights that are appropriate for the object. |
void |
setAccessRightsMap(java.util.Map pRightsMap)
Returns a mapping of access rights by name. |
void |
setSecurityPolicy(SecurityPolicy pPolicy)
Changes the security policy that is in effect in this configuration. |
void |
setUserAuthority(UserAuthority pUserAuthority)
Changes the user authority for converting an account name to a persona that may be used in an access control list. |
| Methods inherited from class java.lang.Object |
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
| Field Detail |
public static java.lang.String CLASS_VERSION
| Constructor Detail |
public SecurityConfiguration()
public SecurityConfiguration(SecurityConfiguration pConfig)
public SecurityConfiguration(SecurityPolicy pPolicy, UserAuthority pUserAuthority, AccessRight[] pAccessRights, java.util.Map pAccessRightsMap)
public SecurityConfiguration(SecurityConfiguration pConfiguration, AccessRight[] pAccessRights, java.util.Map pAccessRightsMap)
| Method Detail |
public SecurityPolicy getSecurityPolicy()
public void setSecurityPolicy(SecurityPolicy pPolicy)
public UserAuthority getUserAuthority()
public void setUserAuthority(UserAuthority pUserAuthority)
public AccessRight[] getAccessRights()
public void setAccessRights(AccessRight[] pAccessRights)
public java.util.Map getAccessRightsMap()
public void setAccessRightsMap(java.util.Map pRightsMap)
|
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |


Import Grid Set
Hydraulic Grid Sets combine a series of depth or water surface elevation grids with frequencies to create a plan for HEC-FDA.
To create the proper specifications of the WSP file for HEC-FDA an invert value must be defined for each stationing, because of that requirement, a terrain dataset must be selected as a part of a Hydraulic Grid set. It is advised that the terrain used to produce the grid files should be selected.
Each WSP must be associated with a year, so a year selection based on the analysis years defined for the study has been provided.
HEC-FDA requires 8 frequency profiles to define a WSP. To meet these qualifications it is required that 8 grids are defined. Each grid must be associated with a frequency. Grids are expected to be tiled pyramidded compressed GeoTif files. If they are not, they will be converted when the user selects "Ok". Frequencies must be between 0 and 1. All grids must be either depth or water surface elevation grids.
To import a grid set, follow these steps:
- Enter the name of the hydraulic data.
- (Optional) Enter a description of the data.
- Select the watershed name.
- Select the year.
- Browse to the location of the gridded data.
- Use the arrows to select the available grids.
- Press the Ok button when finished, or press the close button to cancel.
Example
After clicking the Ok button...


BMI Calculator
Patient Resource
First Name:
Last Name:
Gender:
Date of Birth:
Body Mass Index (BMI)
Observation Resource
Height:
Weight:


My first paragraph.
choose the size:
Size: Large Medium Small| One | Two | Three | Four |
|---|---|---|---|
| Five | six | seven | Eight |
| name | english | math | science |
|---|---|---|---|
| alice | 80 | 80 | 80 |
| sally | 80 | 80 | 80 |
| vanessa | 80 | 80 | 80 |
| john | 80 | 80 | 80 |
calculate for alice:
calculate for sally:
calculate for vanessa:
calculate for john:


Simple RDoc Reference (written in RDoc!)
#
#–
# RDoc will not process what’s between the – and ++, so you can
# put notes or messages here (like FIXMEs or TODOs, that will not
# end up in your documenation.
#++
#
# = Heading 1
# == Heading 2
# === Heading 3
# ==== Heading 4
#
# == Lists
#
# * First List
# * first list first item
# * second list second item
# * Second List
# * second list first item
# * second list second item
#
# == Numbered Lists
#
# 1. Item number one
# 2. Item number two
# 3. Item number three
#
# == Links
#
# Visit {My Personal Blog}[http://www.ozmox.com]
#
# == Text Formatting
#
# Text can be shown in bold and italic. You can even
# denote +code_word+ to appear as typewritter with pluses.
#
# A lot of people write their options out like this:
#
# :option – description of what to pass
#
# class Indented
# def text(appears)
# as code
# end
# end
#
# label:: With double colons
#
# :title: RDoc Simple Reference


This file contains a test cases for different circumstances in which the Privly button should appear. It shows its position relative to the height of the textarea / editable divs.
Parent div has border.
Textarea has border.
Child textarea has 10px top margin. Parent div has a border.
Textarea has border.
Textarea has border.
Textarea has border.
Div has border.
Div has border. Click in the lower part of the div.


The journey
Our journey began when we decided we were going to spend our honeymoon in New Zealand.
Preparations for the trip lasted about 6 months, where we decided everything: the cities, the hotels and the tours.
On 29 August, we boarded the plane and travel to this wonderful country!