Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Topics - litepresence

Pages: [1] 2
1
General Discussion / BitShares Shorting Attack Avenger
« on: April 18, 2020, 09:12:35 pm »
 :o






Ensure you always have adequate collateral backing each debt.
Ensure you never have too much collateral backing each debt.

In either case, when out of bounds:
Returns your collateral to the middle of the band specified by the user,
by via

Code: [Select]
Call_order_update(collateral_delta)
https://github.com/litepresence/BitShares-Shorting-Attack-Avenger


2
General Discussion / Quadratic Pegged Assets
« on: February 07, 2020, 05:15:49 pm »
I've been contemplating issuing a concept I'm calling "quadratic pegged assets".

The aim is to back them with BTS and have the IPO come in near 1:1, then control the price feeds with a combination of "MPA" logic like "bitassets" or "honest mpas" and "APA" logic like "hertz" or "hero".

So the risk and reward of each is leveraged by a squared factor instead of typical coefficient leverage provided by centralized exchanges

this means for example:

BTC:USD goes up by factor 2X the QPA goes up by factor 4X
BTC:USD goes up by factor 10X the QPA goes up by factor 100X

and then on the down side:

BTC:USD goes down by factor 0.5X the QPA goes down by factor 0.25X; 75% loss


These are the 4 equations I'm currently considering,
each contains a coefficient times a market pair price; quantity squared:
(coeff * price) ^ 2

Bitcoin to US Dollar Quadratic Pegged Asset
Code: [Select]
(0.0001*BTC:USD) ^ 2
(0.0001 × 9,732) ^ 2 = 0.95 IPO


Bitshares to Bitcoin Quadratic Pegged Asset
Code: [Select]
(300000×BTS:BTC)^2
(300000*0.00000333)^2 = 0.99 IPO


Silver to Gold Quadratic Pegged Asset
Code: [Select]
(100 * XAG / XAU) ^ 2
(100 * 0.01128) ^ 2 = 1.27 IPO


S&P Commodity Index to S&P Stock Index Quadratic Pegged Asset
Code: [Select]
(10*SPGSCI/SP500) ^ 2
(10*296.87 / 3,335.15) ^ 2 = 0.79 IPO


3
General Discussion / ANN: HONEST Market Pegged Assets
« on: January 21, 2020, 04:46:28 am »
www.litepresence.com presents:

         


and then DEX MPA's were finally HONEST...

HONEST MARKET PEGGED ASSETS
Code: [Select]
The right of nullification is a natural right,
which all admit to be a remedy against insupportable oppression.

    $$$ James Madison $$$

If it had not been for the justice of our cause,
and the consequent interposition of Providence,
in which we had faith, we must have been ruined.

    $$$ Ben Franklin $$$

Resistance and disobedience in economic activity
is the most moral human action possible.

    $$$ Samuel Edward Konkin III $$$




  1.3.5641 HONEST.CNY CHINESE YUAN FIAT
  1.3.5650 HONEST.BTC CENTRALIZED EXCHANGE BITCOIN
  1.3.5649 HONEST.USD UNITED STATES DOLLAR FIAT
  1.3.5651 HONEST.XAU GOLD TROY OUNCE 
  1.3.5652 HONEST.XAG SILVER TROY OUNCE 


UNDERLYING MARKET PEGGED ASSET TECHNOLOGY:
https://bitshares.org/technology/price-stable-cryptocurrencies/

OPEN SOURCE PRICE FEED SCRIPTS:
https://github.com/litepresence/Honest-MPA-Price-Feeds/tree/master/honest

PRICE FEED WHITEPAPER:
https://github.com/litepresence/Honest-MPA-Price-Feeds/blob/master/docs/whitepaper.md

CALL TO ARMS:
https://github.com/litepresence/Honest-MPA-Price-Feeds/blob/master/docs/call_to_arms.md

ASSUMPTIONS
An MPA is a derivative smart contract with the sole purpose of tracking the value of its underlying asset 1:1.
MPA pricefeeds should be timely, accurate, and honest; always always representing the global median price, with truth and precision.
Long term borrowers of an MPA will be required to adjust their collateral over time to prevent margin call.
The purses and interests of the owners of an MPA are more important than the purses of the borrowers of that MPA.
Borrowers have a duty and personal responsibility to maintain the collateral of MPA's, which they have speculated into existance.
Holders are lay users who expect and deserve peg and continuity of MPA's, which they own. 
MPA holders expect their owned assets will remain true to their purpose by definition.
We seek to maintain MPA's near their respective price peg most of the time.
We can accept extreme short term deviation from peg to achieve liquidation of under collateralized positions.
Deviation from peg cannot be so extreme as to result in a market wide default via core blockchain mechanisms.
The mean peg of an MPA over time is far more important than immediate peg of the MPA in any momentary instance.
We are willing to allow considerable deviation from the peg in the instant, in order to minimize the time spent off peg.
It is acceptable and expected for an MPA to be slightly overvalued or undervalued relative to the 1:1 peg, in bull or bear markets respectively. 
Monetary policy should NOT be implemented for marketing purposes or to induce borrowing with the aim of inflating the monetary supply.
Monetary policy should NOT be implemented to adjust for deviation from peg during bullish or bearish market trends.
Monetary policy should allow market participants the greatest freedom possible to make their own decisions and be repsonsible for the outcome.
Monetary policy should not waver over time as to benefit some market participants at the expense of others; whenever possible policy should be set in stone.
Monetary policy  should place the burden of default on the individual borrower, rather than the collective holders.
Monetary policy restrictions should only be implemented to prevent edge case scenarios which result in prolonged loss of peg or freezing of holder assets.
Under no circumstance should monetary policy induce an MPA to become pegged to the backing asset (typically BTS).
Under no circumstance should monetary policy induce an MPA to become frozen by the chain - "supergao".


SCELETUS
Sceletus is a neologism; latin for skeleton.   We are calculating the minimum necessary to enact a dust transaction hourly, such that there is 0.3% price precision drawn on the charts.   Whereas publishing price feed allows for borrowing; it does not draw an actual historic chart that people can see.   Sceletus is filling in that functionality.    We have managed to do a full matrix of markets across bitassets to honest pairs, plus GDEX.btc to honest pairs.  30 total pairs.   So once hourly, sceletus buys whatever quantifies as minimum dust; in graphene sense, this means that
Code: [Select]
min(base_amount, quote_amount) > 300   In USD terms this amounts to about 5 US cents transacted.  Most simply put, it is wash trading for the sake of a "reference rate" in a nascent market as opposed to wash trading for the sake of "volume".  This service of "reference rate" historic charts is provided by our feed producers.  HONEST.CNY to BTS, GDEX.BTC, bitUSD, bitCNY markets have been sceletus'd since January 25th 2020.  The remaining HONEST markets below have been sceletus'd since Feb 1st. 


HONEST to BTS markets:
https://wallet.bitshares.org/#/market/HONEST.CNY_BTS
https://wallet.bitshares.org/#/market/HONEST.USD_BTS
https://wallet.bitshares.org/#/market/HONEST.XAG_BTS
https://wallet.bitshares.org/#/market/HONEST.XAU_BTS
https://wallet.bitshares.org/#/market/HONEST.BTC_BTS

Use these links to exit from fraudulent bitCNY and bitUSD to HONEST MPA's
https://wallet.bitshares.org/#/market/HONEST.CNY_CNY
https://wallet.bitshares.org/#/market/HONEST.USD_CNY
https://wallet.bitshares.org/#/market/HONEST.XAG_CNY
https://wallet.bitshares.org/#/market/HONEST.XAU_CNY
https://wallet.bitshares.org/#/market/HONEST.BTC_CNY
https://wallet.bitshares.org/#/market/HONEST.CNY_USD
https://wallet.bitshares.org/#/market/HONEST.USD_USD
https://wallet.bitshares.org/#/market/HONEST.XAG_USD
https://wallet.bitshares.org/#/market/HONEST.XAU_USD
https://wallet.bitshares.org/#/market/HONEST.BTC_USD

Intra HONEST Markets with legit exchange rates as found in global markets:
https://wallet.bitshares.org/#/market/HONEST.CNY_HONEST.BTC
https://wallet.bitshares.org/#/market/HONEST.USD_HONEST.BTC
https://wallet.bitshares.org/#/market/HONEST.XAG_HONEST.BTC
https://wallet.bitshares.org/#/market/HONEST.XAU_HONEST.BTC
https://wallet.bitshares.org/#/market/HONEST.CNY_HONEST.XAU
https://wallet.bitshares.org/#/market/HONEST.USD_HONEST.XAU
https://wallet.bitshares.org/#/market/HONEST.XAG_HONEST.XAU
https://wallet.bitshares.org/#/market/HONEST.BTC_HONEST.XAU
https://wallet.bitshares.org/#/market/HONEST.CNY_HONEST.XAG
https://wallet.bitshares.org/#/market/HONEST.USD_HONEST.XAG
https://wallet.bitshares.org/#/market/HONEST.BTC_HONEST.XAG
https://wallet.bitshares.org/#/market/HONEST.XAU_HONEST.XAG
https://wallet.bitshares.org/#/market/HONEST.CNY_HONEST.USD
https://wallet.bitshares.org/#/market/HONEST.XAG_HONEST.USD
https://wallet.bitshares.org/#/market/HONEST.XAU_HONEST.USD
https://wallet.bitshares.org/#/market/HONEST.BTC_HONEST.USD
https://wallet.bitshares.org/#/market/HONEST.USD_HONEST.CNY
https://wallet.bitshares.org/#/market/HONEST.XAG_HONEST.CNY
https://wallet.bitshares.org/#/market/HONEST.XAU_HONEST.CNY
https://wallet.bitshares.org/#/market/HONEST.BTC_HONEST.CNY

HONEST to GDEX.BTC markets:
https://wallet.bitshares.org/#/market/HONEST.CNY_GDEX.BTC
https://wallet.bitshares.org/#/market/HONEST.USD_GDEX.BTC
https://wallet.bitshares.org/#/market/HONEST.XAG_GDEX.BTC
https://wallet.bitshares.org/#/market/HONEST.XAU_GDEX.BTC
https://wallet.bitshares.org/#/market/HONEST.BTC_GDEX.BTC


FEED PRODUCERS AND MPA SPECIFICATIONS
http://cryptofresh.com/a/HONEST.CNY
http://cryptofresh.com/a/HONEST.USD
http://cryptofresh.com/a/HONEST.BTC
http://cryptofresh.com/a/HONEST.XAU
http://cryptofresh.com/a/HONEST.XAG

TOP HOLDERS
https://bts.ai/asset/HONEST.CNY
https://bts.ai/asset/HONEST.USD
https://bts.ai/asset/HONEST.BTC
https://bts.ai/asset/HONEST.XAU
https://bts.ai/asset/HONEST.XAG


Be warned this project is very nascent; there are currently ONLY 4 feed producers and 2 more actively deploying their setup

An additional 12 candidates have been selected as potential feed producers and/or HONEST asset advisors due to their Bitshares community merit, technical expertise, and free market aligned philosophy.

We aim to provide 24/7 hourly updates of legitimate price feeds HONEST: CNY, USD, SILVER, GOLD and BTC to the Bitshares DEX.

NOTE: There will be KEY differences in implementation vs. the traditional "Bitassets" with the aim to provide:

LIQUID, FREE MARKETS, with IMMEDIATE PRICE DISCOVERY

1) we WILL NOT seek nor be held ransom by worker funding

2) tx fees will be distributed among feed producers as an incentive to provide HONEST price feeds
3) witnesses and committee members will NOT, by default, be feed producers
4) our price feed scripts will be open source
5) our price feed calculation data matrix will be published live at www.jsonbin.io for each feed producer
6) MSSR will be set to 125 instead of 101, this means YOU WILL get margin called up to 20% below market value default
7) There will be NO "flat max" market fee to benefit large transactions
8) The only retained permission/flag is to adjust market fees, all others have been permanently abandoned:

NO OWNER PERMISSIONS EXCEPT "MARKET FEE"

    YES Enable market fee:
    NO Require holders to be white-listed:   
    NO Asset owner may transfer asset back to himself:   
    NO Asset owner must approve all transfers:   
    NO Disable force settling:   
    NO Allow asset owner to force a global settling:   
    NO Disable confidential transactions:   
    NO Allow witnesses to provide feeds:   
    NO Allow committee members to provide feeds:

9) Force Settlement Delay is 60 minutes
10) Feed lifetime is 4h
11) 2% Force Settlement Offset
12) Max Settlement volume is 100%
14) Price Feed producers will be required to run the price feed scripts provided as described in the whitepaper.


We are striving to make it highly unlikely that these MPA will ever globally settle through our asset settings.


These features currently match traditional Bitassets:

MCR = 160
Total supply = 100,000,000,000 HONEST.CNY
Precision = 4 (0.0001) HONEST.CNY

Further:

We will NOT engange in "open market" corrective operations or tweaks to MCR, MSSR, etc. with an aim to achieve price parity. 
We reserve the right to move MSSR up or down at any time, but it will never approach "Bitasset 101"; as to make liquidation infeasible.
We reserve the right to move MCR up or down at any time, but our producers are obligated to never increase more than +5 daily (ie 160 + 5 = 165 MCR)
We strongly recommend YOU RESPONSIBLY CHOOSE an ICR of 200+ given the volatile nature of crypto markets and the zero restrictions we've placed on liquidation of mal investement.
We also strongly recommend that YOU follow the market prices of your collateralized investments, maintain your collateral position, and invest wisely to make PROFIT while you hold our MPAs.
We intend to act as a traditional margin market with a TREND towards price parity with the pegged asset, but with an underlying expectation of volatility.
We intend to discourage TRENDS away from price parity through IMMEDIATE liquidation of mal investment coupled with HONEST price feeds.
It is our goal to keep the HONEST markets as free and unregulated as possible within the constraints of the blockchain environment.

NOTE: I am currently the "asset owner" but my intention is to form a multisig governance around them as soon as this project gets off the ground.

It is our hope that these markets catch on like wildfire and we can soon faithfully offer additional HONEST MPA fiats, cryptos, and precious metals.

ALSO: (coming soon) I have created "HONEST" as the base UIA, there are 100,000 non divisible tokens which I will be self issuing.  This project was built entirely pro bono; I intend to offer them on the books for 100 BTS each as a tip cup.  Much love.

For more on MCR, MSSR, and ICR please visit.
https://www.investopedia.com/terms/m/margin.asp
https://en.wikipedia.org/wiki/Margin_(finance)

You can find the first feed producer price calculation data matrixes here:

https://api.jsonbin.io/b/5e221d218d761771cc92b200/latest
https://api.jsonbin.io/b/5e3622e23d75894195e3226d/latest
https://api.jsonbin.io/b/5e25c8055df640720838d768/latest
https://api.jsonbin.io/b/5e361c8850a7fe418c57ff17/latest
(additional feed producer jsonbins coming soon)

Please visit litepresence.com and check out some of my other work:

BitsharesQuant; an open source algo trading platform for the DEX,

CypherVault; an open source CLI password manager, and

NordVPN switcher; which maintains a high speed VPN connection through adversity for high bot trading up time

A final note...  Yes! This is a response:  There cannot be a need for nullification and interposition, unless there is an underlying injustice and oppression being overcome.    These MPA's are not just a new novel asset class put forth for fun; or as some idle experiment or alternative.  HONEST price feeds are in fact a remedy, for an inherent dysfunction, in the previous political order, which has led to the destruction of Bitassets, as a viable market pegged instrument.  Beyond Bitshares, HONEST MPA's are also a reaction to the events which have led to a dearth of CNY:BTC markets globally.

Long Live Bitshares!

Long Live FREE Markets!



for individual liberty,

litepresence2020


ps... if you have some time and you care to learn more about free market theory, please read this paper I type scripted a few years back by Kyle O’Donnell:

Planning the End of Planning:
Disintervention and the Knowledge Problem


http://www.ronpaulforums.com/showthread.php?492708-Planning-the-End-of-Planning-Disintervention-and-the-Knowledge-Problem

Quote
"Interventionism is distortive, disruptive, and potentially socially destructive because it attempts to defy the criticisms and possibilities of centralized planning according to the market process view of the dynamic market. Yet disintervention faces the same problems. When disintervening, political actors with necessarily limited information and knowledge must somehow decide, not only what to liberalize, but how and when. [] there is no tendency in piecemeal disintervention to successfully liberalize via correctly discovering the proper order, rate, or even what and where to disintervene."  This raises the distinct possibility that nothing short of radical movement towards anarcho-capitalism might ever achieve an outcome close to its original goals.


4
Stakeholder Proposals / BSIP86: 1000:1 Core BTS Token Reverse Split
« on: December 30, 2019, 08:27:22 pm »
https://github.com/litepresence/bsips/blob/patch-1/bsip-0086.md

Code: [Select]
    BSIP: BSIP 86
    Title: 1000:1 Reverse Split of Core BTS Token
    Authors: litepresence [email protected]
    Status: Draft
    Type: Protocol
    Created: 2019-12-30
    Discussion: https://bitsharestalk.org/index.php?topic=31970.0


# Abstract

As we approach Jan 1, 2020, the current trading price for BTS core token vs. BTC has fallen below 200 satoshi.  It also fell below 200 satoshi in February 2018.  Since inception, the price of the core BTS token has spent about 50% of its time below 1000 satoshi vs. BTC.  Beneath 1000 satoshi, BTS has only had 3 significant figures to trade at centralized exchanges.  Significant figures of a number are the non-leading-zero digits, which carry meaning - contributing to its measurement resolution.

In stock markets, stock splits and reverse stock splits are routine actions performed by corporations, upon consent of shareholders.  We find in traditional stock markets, prices are maintained such that there are always between 4 and 5 significant figures vs. the national currency.   That is, most stock prices, in high volume markets, typically range from 10.00 to 999.99.   When they get outside of that range, a stock split; or reverse stock split is a routine consideration taken up among shareholders and initiated by corporate management.   

Exchanges do not tend to change their user interface or back-end to accommodate assets, which do not fit within their existing framework.  In Bitcoin markets, that framework allows for precision up to 8 digits; 0.00000000.  Likewise in USD and CNY markets, the precision offered is typically 0.00.   


# Motivation

The motivation of this split is to increase share price immediately; to prevent delisting risk, encourage listing acceptance at new exchanges, and more generally encourage higher trade volume at centralized exchanges, by removing the delisting threat.   


# Rational

Exchanges generally specify a minimum bid price for an asset to be listed.  If the asset falls below this bid price and remains lower than that threshold level over a certain period, it risks being delisted from the exchange.  In the cryptocurrency space this price threshold is often proprietary, though experience shows it is typically set between 200 and 500 satoshi.  Secondly, in fear of being stuck with a delisted asset, traders are hesitant to purchase a currency who's exchange price is approaching the delisting threshold.   Over time, this rational fear decreases trading volume, which has a cascading effect on the price of an already weakened asset.  Further, when a coin is delisted from exchange there is a typically a sharp, immediately negative effect on market price.   

Additionally, when an asset price is at the bottom end of 3 significant figures, such as is the current case of Bitshares at 200 satoshi; there is now 0.5% change in value for every up or down tick in price.  At 100 satoshi, that becomes one full percent change in value for every tick in tradable asset price vs BTC (the core currency BTS is traded against at most centralized exchanges).  The core properties of money are Durability, Portability, Divisibility and Intrinsic value.   When price is moving in ticks of half-a-percent measurment resolution at every trade, the properties of Divisibility and Intrinsic Value come into question. 

In traditional stock markets, upon a reverse stock split, there is an immediate and proportional change in market price to the split ratio.   Instead of trading at 0.00000200 in CEX markets, Bitshares would immediately trade at 0.00200000.   Markets are very reliable and resilient in this regard.   There would be no immediate effect on market cap or the vaule of individual holdings vs. USD, CNY, or BTC.  However, the delisting risk profile would immediately and permanently change. 

The BTS:USD price, likewise would move from $0.0149 (current) to $14.90 on markets.  This would open doors for the BTS:USD pairing, where exchanges specify price in cents, to be a rational consideration.


# Specifications

The specification for this change is simple:

- 1000:1 reverse split
- Core token asset precision changed from 5 to 8
- All open orders on DEX vs the core BTS token would be scaled accordingly
- All loans used to issue bitASSETs would also be scaled

Currently the chain supports 15 digits in format:

Code: [Select]
    X,XXX,XXX,XXX.XXXXX
   
After the split it still supports 15 digits in the new format:

Code: [Select]
    X,XXX,XXX.XXXXXXXX
Current maximum supply is:

Code: [Select]
    3,600,570,502.00000
   
After the split maximum supply is:

Code: [Select]
    3,600,570.00000000 (or if possible 3,600,570.50200000)
Put simply:

However many BTS are in existence is divided by 1000.  However many you have personally is divided by 1000. 

If there is rounding to be done, round down.

If it is technically less challenging to "air drop" a new token at 1000:1 ratio and rename it:

Code: [Select]
    newBTS, BTS3, bitBTS, coreBTS, BTS2020, etc.
Then lock trading / transfer of the original BTS core token, to initiate the reverse split; this would be acceptable as well, so long as all major exchanges are put on notice of the upcoming change and agree to distribute the air drop after the protocol upgrade.


# Discussion

https://bitsharestalk.org/index.php?topic=31970.0


# Summary for Shareholders


Significant figures in financial markets send key signals to both traders and exchange operators.   BTS has consistently traded at 3 significant figures vs BTC in satoshis; and less than 1 US Dollar (currently 1.5 cents).   Making this change to the core protocol, will eliminate delisting risk at centralized exchanges due to the very concrete issue of divisibility vs. the value of Bitcoin; while opening doors to USD markets which trade with 2 decimal precision.


# Copyright:

WTFPL - wtfpl.net


# See Also

Quote
The number one reason for a reverse stock split is because the stock exchanges—like the NYSE or Nasdaq—set minimum price requirements for shares that trade on their exchanges. And when a company’s shares decline to near - or below - that level, the easiest way to stay in compliance with the exchange is to reduce the number of outstanding shares so that the price of the individual shares - like magic - automatically rises. And when that happens, the company’s shares can remain trading on the exchange.

- https://cabotwealth.com/daily/how-to-invest/reverse-stock-splits-shareholders/

# Additional Resources

- https://www.investopedia.com/terms/r/reversesplit.asp
- https://www.investopedia.com/ask/answers/06/reversestocksplit.asp
- https://www.fool.com/knowledge-center/whats-a-reverse-stock-split-and-can-it-really-help.aspx
- https://www.wallstreetmojo.com/reverse-stock-split
- https://en.wikipedia.org/wiki/Reverse_stock_split
- https://www.upcounsel.com/reverse-stock-split
- https://www.stocksplithistory.com/reverse-stock-splits
- https://finance.zacks.com/reverse-stock-split-good-bad-2298.html

5
Technical Support / 1000 Candles of Historical HLOC from the DEX
« on: February 17, 2019, 05:00:46 pm »
BTS/bitUSD



list of dicts of human readable numpy arrays

Code: [Select]
from websocket import create_connection as wss  # handshake to node
from json import dumps as json_dumps
from json import loads as json_loads
import matplotlib.pyplot as plt
from datetime import datetime
from pprint import pprint
import numpy as np
import time


def public_nodes():
    return [
        'wss://altcap.io/wss',
        'wss://api-ru.bts.blckchnd.com/ws',
        'wss://api.bitshares.bhuz.info/wss',
        'wss://api.bitsharesdex.com/ws',
        'wss://api.bts.ai/ws',
        'wss://api.bts.blckchnd.com/wss',
        'wss://api.bts.mobi/wss',
        'wss://api.bts.network/wss',
        'wss://api.btsgo.net/ws',
        'wss://api.btsxchng.com/wss',
        'wss://api.dex.trading/ws',
        'wss://api.fr.bitsharesdex.com/ws',
        'wss://api.open-asset.tech/wss',
        'wss://atlanta.bitshares.apasia.tech/wss',
        'wss://australia.bitshares.apasia.tech/ws',
        'wss://b.mrx.im/wss',
        'wss://bit.btsabc.org/wss',
        'wss://bitshares.crypto.fans/wss',
        'wss://bitshares.cyberit.io/ws',
        'wss://bitshares.dacplay.org/wss',
        'wss://bitshares.dacplay.org:8089/wss',
        'wss://bitshares.openledger.info/wss',
        'wss://blockzms.xyz/ws',
        'wss://bts-api.lafona.net/ws',
        'wss://bts-seoul.clockwork.gr/ws',
        'wss://bts.liuye.tech:4443/wss',
        'wss://bts.open.icowallet.net/ws',
        'wss://bts.proxyhosts.info/wss',
        'wss://btsfullnode.bangzi.info/ws',
        'wss://btsws.roelandp.nl/ws',
        'wss://chicago.bitshares.apasia.tech/ws',
        'wss://citadel.li/node/wss',
        'wss://crazybit.online/wss',
        'wss://dallas.bitshares.apasia.tech/wss',
        'wss://dex.iobanker.com:9090/wss',
        'wss://dex.rnglab.org/ws',
        'wss://dexnode.net/ws',
        'wss://england.bitshares.apasia.tech/ws',
        'wss://eu-central-1.bts.crypto-bridge.org/wss',
        'wss://eu.nodes.bitshares.ws/ws',
        'wss://eu.openledger.info/ws',
        'wss://france.bitshares.apasia.tech/ws',
        'wss://frankfurt8.daostreet.com/wss',
        'wss://japan.bitshares.apasia.tech/wss',
        'wss://kc-us-dex.xeldal.com/ws',
        'wss://kimziv.com/ws',
        'wss://la.dexnode.net/ws',
        'wss://miami.bitshares.apasia.tech/ws',
        'wss://na.openledger.info/ws',
        'wss://ncali5.daostreet.com/wss',
        'wss://netherlands.bitshares.apasia.tech/ws',
        'wss://new-york.bitshares.apasia.tech/ws',
        'wss://node.bitshares.eu/ws',
        'wss://node.market.rudex.org/wss',
        'wss://nohistory.proxyhosts.info/wss',
        'wss://openledger.hk/wss',
        'wss://paris7.daostreet.com/wss',
        'wss://relinked.com/wss',
        'wss://scali10.daostreet.com/wss',
        'wss://seattle.bitshares.apasia.tech/wss',
        'wss://sg.nodes.bitshares.ws/ws',
        'wss://singapore.bitshares.apasia.tech/ws',
        'wss://status200.bitshares.apasia.tech/wss',
        'wss://us-east-1.bts.crypto-bridge.org/ws',
        'wss://us-la.bitshares.apasia.tech/ws',
        'wss://us-ny.bitshares.apasia.tech/ws',
        'wss://us.nodes.bitshares.ws/wss',
        'wss://valley.bitshares.apasia.tech/ws',
        'wss://ws.gdex.io/ws',
        'wss://ws.gdex.top/wss',
        'wss://ws.hellobts.com/wss',
        'wss://ws.winex.pro/wss'
    ]


def wss_handshake(node):
    global ws
    ws = wss(node, timeout=5)


def wss_query(params):
    query = json_dumps({"method": "call",
                        "params": params,
                        "jsonrpc": "2.0",
                        "id": 1})
    ws.send(query)
    ret = json_loads(ws.recv())
    try:
        return ret['result']  # if there is result key take it
    except:
        return ret


def rpc_market_history(currency_id, asset_id, period, start, stop):

    ret = wss_query(["history",
                     "get_market_history",
                     [currency_id,
                      asset_id,
                      period,
                      to_iso_date(start),
                      to_iso_date(stop)]])
    return ret


def chartdata(pair, start, stop, period):
    pass  # as per extinctionEVENT cryptocompare call


def rpc_lookup_asset_symbols(asset, currency):
    ret = wss_query(['database',
                     'lookup_asset_symbols',
                     [[asset, currency]]])
    asset_id = ret[0]['id']
    asset_precision = ret[0]['precision']
    currency_id = ret[1]['id']
    currency_precision = ret[1]['precision']

    return asset_id, asset_precision, currency_id, currency_precision

def backtest_candles(raw):  # HLOCV numpy arrays

    # gather complete dataset so only one API call is required
    d = {}
    d['unix'] = []
    d['high'] = []
    d['low'] = []
    d['open'] = []
    d['close'] = []
    for i in range(len(raw)):
        d['unix'].append(raw[i]['time'])
        d['high'].append(raw[i]['high'])
        d['low'].append(raw[i]['low'])
        d['open'].append(raw[i]['open'])
        d['close'].append(raw[i]['close'])
    del raw
    d['unix'] = np.array(d['unix'])
    d['high'] = np.array(d['high'])
    d['low'] = np.array(d['low'])
    d['open'] = np.array(d['open'])
    d['close'] = np.array(d['close'])

    # normalize high and low data
    for i in range(len(d['close'])):
        if d['high'][i] > 2 * d['close'][i]:
            d['high'][i] = 2 * d['close'][i]
        if d['low'][i] < 0.5 * d['close'][i]:
            d['low'][i] = 0.5 * d['close'][i]

    return d

def from_iso_date(date):  # returns unix epoch given iso8601 datetime
    return int(time.mktime(time.strptime(str(date),
                                         '%Y-%m-%dT%H:%M:%S')))


def to_iso_date(unix):  # returns iso8601 datetime given unix epoch
    return datetime.utcfromtimestamp(int(unix)).isoformat()


def parse_market_history():

    ap = asset_precision  # quote
    cp = currency_precision  # base
    history = []
    for i in range(len(g_history)):
        h = ((float(int(g_history[i]['high_quote'])) / 10 ** cp) /
            (float(int(g_history[i]['high_base'])) / 10 ** ap))
        l = ((float(int(g_history[i]['low_quote'])) / 10 ** cp) /
            (float(int(g_history[i]['low_base'])) / 10 ** ap))
        o = ((float(int(g_history[i]['open_quote'])) / 10 ** cp) /
            (float(int(g_history[i]['open_base'])) / 10 ** ap))
        c = ((float(int(g_history[i]['close_quote'])) / 10 ** cp) /
            (float(int(g_history[i]['close_base'])) / 10 ** ap))
        cv = (float(int(g_history[i]['quote_volume'])) / 10 ** cp)
        av = (float(int(g_history[i]['base_volume'])) / 10 ** ap)
        vwap = cv / av
        t = int(min(time.time(),
               (from_iso_date(g_history[i]['key']['open']) + 86400)))
        history.append({'high': h,
                        'low': l,
                        'open': o,
                        'close': c,
                        'vwap': vwap,
                        'currency_v': cv,
                        'asset_v': av,
                        'time': t})
    return history

print("\033c")

node_id = 2
calls = 5  # number of requests
candles = 200  # candles per call
period = 86400  # data resolution
asset = 'BTS'
currency = 'USD'

# fetch node list
nodes = public_nodes()
# select one node from list
wss_handshake(nodes[node_id])
# gather cache data to describe asset and currency
asset_id, asset_precision, currency_id, currency_precision = (
    rpc_lookup_asset_symbols(asset, currency))
print(asset_id, asset_precision, currency_id, currency_precision)


full_history = []
now = time.time()
window = period * candles
for i in range((calls - 1), -1, -1):
    print('i', i)
    currency_id = '1.3.121'
    asset_id = '1.3.0'
    start = now - (i + 1) * window
    stop = now - i * window
    g_history = rpc_market_history(currency_id,
                                   asset_id,
                                   period,
                                   start,
                                   stop)
    print(g_history)
    history = parse_market_history()
    full_history += history

pprint(full_history)
print(len(full_history))

data = backtest_candles(full_history)

fig = plt.figure()
ax = plt.axes()
fig.patch.set_facecolor('black')
ax.patch.set_facecolor('0.1')
ax.yaxis.tick_right()
ax.spines['bottom'].set_color('0.5')
ax.spines['top'].set_color(None)
ax.spines['right'].set_color('0.5')
ax.spines['left'].set_color(None)
ax.tick_params(axis='x', colors='0.7', which='both')
ax.tick_params(axis='y', colors='0.7', which='both')
ax.yaxis.label.set_color('0.9')
ax.xaxis.label.set_color('0.9')
plt.yscale('log')

x = data['unix']
plt.plot(x, data['high'], color='white')
plt.plot(x, data['low'], color='white')
plt.plot(x, data['open'], color='aqua')
plt.plot(x, data['close'], color='blue')

plt.show()

RPC call to public node

get_market_history()

Is in graphene format; ie no decimal places, no human readable pricing

(min_to_receive/10^receive_precision) / (amount_to_sell/10^sell_precision)

gives you this:



I give you this:



crypto long, moar coinz short!

- uncle lp

6
General Discussion / microDEX <-> metaNODE <-> manualSIGNING
« on: February 14, 2019, 05:29:58 pm »


I have set out to ensure UI buy/sell/cancel ALWAYS works when I push buttons and never have to think about which node to pick, slow connectivity, idiosyncrasies of graphene speak, or the bugs of "full featured software". 

Just on demand buy/sell/cancel.

Go to my github repo...

`github/litepresence/extinction-event/EV`

You get copy of each of these and plop in one folder

microDEX.py
manualSIGNING.py
metaNODE.py


each script is about 50kb; 1500 lines; very small, quick/easy to read

all dependencies are `pip3 install` the stack does NOT require pybitshares

Code: [Select]
SYSTEM REQUIREMENTS
linux / python3

MODULES YOU WILL NEED
ecdsa
numpy
tkinter
requests
secp256k1
websocket-client


metaNODE
is statistically curated public api data
you run this in a separate terminal before launching microDEX

manualSIGNING
is your private authenticated ops api
microDEX imports the broker(order) method from manualSIGNING to sign transactions with a WIF key.  manualSIGNING is a purpose built fork of pybitshares for signing limit orders about 1/40th the size of the full package.

microDEX
is your buy/sell/cancel user interface
built on tkinter, it communicates with metaNODE at nanosecond speed and places orders via manualSIGNING to the fastest nodes in the network.

it runs 24/7 maintaining 100ms response time on button clicks
all buy/sell/cancel ops occur in timed out parallel process to the UI process; nothing can get hung
extremely reactive, 99.99% uptime, never rogue or stale; statistically curated public api data
when new version is available microDEX will inform you at startup and allow in script update

I maintain a "heavily commented", "minimal dependencies", "minimal viable product", "pep8", and "procedural-style" script.

you can demo the platform without providing any acct details

there is also metaNODEwhitepaper and manualSIGNGwhitepaper in my repo

enjoy, pro bono

crypto long, moar coinz short!

-uncle lp





POST SCRIPT:

YES! this stack does take your wif key, and performs ECDSA. 
<THIS SHOULD CONCERN YOU>
Scammers can use these methods to take all ur cryptoz!!!
<THIS SHOULD CONCERN YOU>
You should NOT blindly trust ANYONE to write a GUI wallet for you. 
You should read ANY script with access to your funds before giving it your keys!

7
General Discussion / API Node Latency Map
« on: December 07, 2018, 10:30:21 pm »
for data you go here:

https://api.jsonbin.io/b/5c06e4f71deea01014bd4261/latest#Bitshares_Latency

This jsonbin api is at a stationary location.

I update the latency info hourly via python script; I'm on east coast US.

at the link you will find json dictionary with keys:

['GEO', 'COUNT', 'PING', 'URLS', 'LIVE', 'SOURCE_CODE', 'MAP_URL', 'MISSION', 'UTC', 'UNIX', 'OWNER', 'LOCATION', 'UNIVERSE']

UNIVERSE is all known bitshares public api nodes mentioned in various github projects; I suspect I have the largest known list of bitshares public api domains

URLS are github urls where node lists can be found; this tool does not contain a list of nodes.  Instead it goes to many different repos on github (such as bitshares, cryptobridge, rudex) etc.  where people have configuration files with lists of nodes; if they update their repo with new nodes, the script finds them with web scraping methods

LIVE is a list of tested nodes that respond within 10 seconds and have a head block number that is not stale. 

PING is list of tuples of ping time for each LIVE node

GEO is geo location data (country, city, longitude, latitude) for each LIVE node as provided by ip-api.com or ipinfo.io

COUNT is number of live nodes vs number of nodes in universe

SOURCE_CODE is my github were you can get this tool and run it yourself to produce your own web hosted latency map in distributed fashion.  The latency script will also give you information as to why each down node failed to connect.  A full report looks like this:

https://pastebin.com/JL4DZzwY

You can also pick up copy of metaNODE and ExtinctionEvent while you're there :D

UNIX and UTC are time stamp when this jsonbin was last updated

MAP_URL is a link to a visual image of the data on the jsonbin;
the map url will change every hour!


it will be something like:
https://vgy.me/dgCE1C.png


and look like one frame of this gif





source code is here, WTFPL:

https://github.com/litepresence/extinction-event/blob/master/EV/bitshares-latency.py

todo list... upload 24hr animations instead of still images


thanks to free and easy to use api services that make this project is possible:

ip-api.com
jsonbin.io
vgy.me



8
General Discussion / [ANN] metaNODE = Bitshares_Trustless_Client()
« on: June 06, 2018, 01:52:45 pm »
metaNODE = Bitshares_Trustless_Client()

There were two ways to get data from Bitshares blockchain:

- a private node that uses lots of RAM, prefers its own machine, and is technical to tend
- a public node that is difficult to stay connected to and may provide rogue data

I've created a 3rd path; connect to several random nodes in the public network... ask them each for latest market data; then move on to other nodes in the network continually. Finally, perform statistical analysis on the combined feeds and maintain a streaming curated output file; the metaNODE.

python script and whitepaper, including usage:

https://github.com/litepresence/extinction-event/tree/master/metaNODE

Code: [Select]
LICENSE:

'litepresence 2018'

def WTFPL_v0_March_1765():
    if any([stamps, licenses, taxation, regulation, fiat, etat]):
        try:
            print('no thank you')
        except:
            return [tar, feathers]

Mission:

1/10 the RAM usage of a personal node
99.9999 six sigma uptime
99.9999 six sigma accurate data feed
less than 5000ms latency


metaNODE is a streaming text file that contains statistically curated dex data from all public nodes for a single market on a single account.  metaNODE currently curates the following feeds:

- last
- market history
- open orders
- orderbook
- market-account balance


Run time has been demonstrated in excess of 2 weeks. 
metaNODE.txt is updated about once per second with live data.

metaNODE
is entirely independent of pybitshares.
Public database calls are made with websocket-client.


This project has received funding through the DEXbot worker.  Additional funding has been earmarked for incorporation of metaNODE into future release of the DEXbot platform.

metaNODE10 has already been incorporated into the Extinction Event dex algo trading framework EV.py; learn more at

www.litepresence.com





9
General Discussion / Bitshares Database Pocket Reference - Python
« on: April 27, 2018, 08:43:56 pm »
Code: [Select]
#Python3

' Bitshares Database Api Websocket Calls Pocket Reference'

# https://github.com/bitshares/bitshares-core/blob/master/libraries/app/database_api.cpp#L77

'litepresence 2018'

import websocket  #pip install websocket-client
websocket.enableTrace(False)

# EXAMPLE DATABASE REQUEST PARAMETERS
node = 'wss://api.bts.mobi/wss'#'wss://bts-seoul.clockwork.gr' # websocket address
asset = 'BTS' # symbol
currency = 'OPEN.BTC' #symbol
start = '2017-01-01T11:22:33' # iso date
stop = '2018-01-01T11:22:33' # iso date
account_name = 'litepresence1' # string
account_names = '["xeroc", "litepresence1"]' # list of string names
account_id = '1.2.743179' # a.b.c vector
block_num = 26444444 # int block number
block_nums = [26444444, 26444445, 26444446] # list of block numbers
trx_in_block = 4 # int index of item
transaction_id = '1.7.66209049'
transaction_id_type = 'cancel'
skip_order_book = 'false' # bool - non pythonic 'true' or 'false'
limit = 5 # int depth of data called
object_id_type = '' # a.b.c vector
object_ids = []
asset_id = '1.3.0'
asset_id2 = '1.3.861'
subscribe = 'false' # bool - non pythonic 'true' or 'false'
public_key = "BTS7d4MpYzecprWMfso8f6o1Ln8fQyxuQGD5LM83PRTfQBkodk4Ck"
witness_id = '1.6.65'
trx = '{"expiration":"2018-04-27T14:16:35","extensions":[],"operation_results":[[1,"1.7.66407704"]],"operations":[[1,{"amount_to_sell":{"amount":71055254,"asset_id":"1.3.0"},"expiration":"2018-05-04T14:16:04","extensions":[],"fee":{"amount":578,"asset_id":"1.3.0"},"fill_or_kill":false,"min_to_receive":{"amount":1922091,"asset_id":"1.3.121"},"seller":"1.2.879926"}]],"ref_block_num":8413,"ref_block_prefix":4199813419}'

# '{"id":1,"method":"call","params":["database","get_ticker",["OPEN.BTC","BTS"]]}'
Z = '{"id":1,"method":"call","params":["database",'

'Objects'
get_objects                     = Z + ''

'Subscriptions'
set_subscribe_callback          = Z + ''
set_pending_transaction_callback = Z + ''
set_block_applied_callback      = Z + ''
cancel_all_subscriptions        = Z + ''

'Blocks and transactions'
get_block_header                = Z + '"get_block_header",["%s"]]}' % block_num
get_block_header_batch          = Z + '"get_block_header_batch",["%s"]]}' % (block_nums)
get_block                       = Z + '"get_block",["%s"]]}' % block_num
get_transaction                 = Z + '"get_transaction",["%s", "%s"]]}' % (block_num, trx_in_block)
get_recent_transaction_by_id    = Z + ''

'Globals' # DONE
get_chain_properties            = Z + '"get_chain_properties",[]]}'
get_global_properties           = Z + '"get_global_properties",[]]}'
get_config                      = Z + '"get_config",[]]}'
get_chain_id                    = Z + '"get_chain_id",[]]}'
get_dynamic_global_properties   = Z + '"dynamic_global_properties",[]]}'

'Keys'
get_key_references              = Z + '"get_key_references",[["%s",]]]}' % public_key
is_public_key_registered        = Z + '"is_public_key_registered",["%s"]]}' % public_key

'Accounts'
get_accounts                    = Z + '"get_accounts",[["%s",]]]}' % account_id
get_full_accounts               = Z + '"get_full_accounts",[["%s",],%s]]}' % (account_name, subscribe)
get_account_by_name             = Z + '"get_account_by_name",["%s"]]}' % account_name
get_account_references          = Z + '"get_account_references",["%s",]]}' % account_id
lookup_account_names            = Z + '"lookup_account_names",[%s]]}' % account_names
lookup_accounts                 = Z + '"lookup_accounts",["%s", "%s"]]}' % (account_name, limit)
get_account_count               = Z + '"get_account_count",[]]}'

'Balances'
get_account_balances            = Z + '"get_account_balances",["%s", [] ]]}' % (account_id)
get_named_account_balances      = Z + '"get_named_account_balances",["%s", [] ]]}' % (account_name)
get_balance_objects             = Z + ''
get_vested_balances             = Z + ''
get_vesting_balances            = Z + '"get_vesting_balances",["%s"]]}' % account_id

'Assets'
get_assets                      = Z + '"get_assets",[["%s",]]]}' % asset_id
list_assets                     = Z + '"list_assets",["%s","%s"]]}' % (asset, limit)
lookup_asset_symbols            = Z + '"lookup_asset_symbols",[["%s",]]]}' % asset

'Markets / feeds'
get_order_book                  = Z + '"get_order_book",["%s","%s","%s"]]}' % (currency, asset, limit)
get_limit_orders                = Z + '"get_limit_orders",["%s","%s","%s"]]}' % (asset_id, asset_id2, limit)
get_call_orders                 = Z + '"get_call_orders",["%s","%s"]]}' % (asset_id, limit)
get_settle_orders               = Z + '"get_settle_orders",["%s","%s"]]}' % (asset_id, limit)
get_margin_positions            = Z + '"get_margin_positions",["%s"]]}' % account_id
get_collateral_bids             = Z + ''
subscribe_to_market             = Z + ''
unsubscribe_from_market         = Z + ''
get_ticker                      = Z + '"get_ticker",["%s","%s","%s"]]}' % (currency, asset, skip_order_book)
get_24_volume                   = Z + '"get_24_volume",["%s","%s"]]}' % (currency, asset)
get_top_markets                 = Z + '"get_top_markets",["%s"]]}' % limit
get_trade_history               = Z + '"get_trade_history",["%s","%s","%s","%s","%s"]]}' % (currency, asset, start, stop, limit)
get_trade_history_by_sequence   = Z + ''

'Witnesses'
get_witnesses                   = Z + ''
get_witness_by_account          = Z + '"get_witness_by_account",["%s"]]}' % witness_id
lookup_witness_accounts         = Z + '"lookup_witness_accounts",["%s","%s"]]}' % (witness_id, limit)
get_witness_count               = Z + '"get_witness_count",[]]}'

'Committee members'
get_committee_members           = Z + ''
get_committee_member_by_account = Z + ''
lookup_committee_member_accounts = Z + ''
get_committee_count             = Z + '"get_committee_count",[]]}'

'Workers'
get_all_workers                 = Z + ''
get_workers_by_account          = Z + ''
get_worker_count                = Z + '"get_worker_count",[]]}'

'Votes'
lookup_vote_ids = Z + ''

'Authority / validation'
get_transaction_hex             = Z + '"get_transaction_hex",[%s]]}' % trx
get_required_signatures         = Z + ''
get_potential_signatures        = Z + '"get_potential_signatures",[%s]]}' % trx
get_potential_address_signatures  = Z + '"get_potential_address_signatures",[%s]]}' % trx
verify_authority                = Z + '"verify_authority",[%s]]}' % trx
verify_account_authority        = Z + ''
validate_transaction            = Z + '"validate_transaction",[%s]]}' % trx
get_required_fees               = Z + ''

'Proposed transactions'
get_proposed_transactions = Z + '"get_proposed_transactions",["%s"]]}' % account_id

'Blinded balances'
get_blinded_balances = Z + ''

'Withdrawals'
get_withdraw_permissions_by_giver = Z + ''
get_withdraw_permissions_by_recipient = Z + ''


all_calls = [get_objects,set_subscribe_callback,set_pending_transaction_callback,set_block_applied_callback,cancel_all_subscriptions,get_block_header,get_block_header_batch,get_block,get_transaction,get_recent_transaction_by_id,get_chain_properties,get_global_properties,get_config,get_chain_id,get_dynamic_global_properties,get_key_references,is_public_key_registered,get_accounts,get_full_accounts,get_account_by_name,get_account_references,lookup_account_names,lookup_accounts,get_account_count,get_account_balances,get_named_account_balances,get_balance_objects,get_vested_balances,get_vesting_balances,get_assets,list_assets,lookup_asset_symbols,get_order_book,get_limit_orders,get_call_orders,get_settle_orders,get_margin_positions,get_collateral_bids,subscribe_to_market,unsubscribe_from_market,get_ticker,get_24_volume,get_top_markets,get_trade_history,get_trade_history_by_sequence,get_witnesses,get_witness_by_account,lookup_witness_accounts,get_witness_count,get_committee_members,get_committee_member_by_account,lookup_committee_member_accounts,get_committee_count,get_all_workers,get_workers_by_account,get_worker_count,lookup_vote_ids,get_transaction_hex,get_required_signatures,get_potential_signatures,get_potential_address_signatures,verify_authority,verify_account_authority,validate_transaction,get_required_fees,get_proposed_transactions,get_blinded_balances,get_withdraw_permissions_by_giver,get_withdraw_permissions_by_recipient,]


object_calls = []

subscription_calls = []

block_calls =      [get_block,
                    get_block_header,
                    get_block_header_batch,
                    get_transaction]

global_calls =     [get_chain_properties,
                    get_global_properties,
                    get_config,
                    get_chain_id,
                    get_dynamic_global_properties]

key_calls =        [get_key_references,
                    is_public_key_registered]

account_calls =    [get_accounts,
                    get_full_accounts,
                    get_account_by_name,
                    get_account_references,
                    lookup_account_names,
                    lookup_accounts,
                    get_account_count]

asset_calls =      [get_assets,
                    list_assets,
                    lookup_asset_symbols]

balance_calls =    [get_account_balances,
                    get_named_account_balances,
                    get_vesting_balances]

market_calls =     [get_order_book,
                    get_ticker,
                    get_trade_history,
                    get_limit_orders,
                    get_call_orders,
                    get_settle_orders,
                    get_margin_positions,
                    get_24_volume,
                    get_top_markets, ]

witness_calls =    [get_witness_by_account,
                    lookup_witness_accounts,
                    get_witness_count]

committe_calls =   [get_committee_count]

worker_calls =     [get_worker_count]

vote_calls = []

authority_calls =  [get_transaction_hex,
                    get_potential_signatures,
                    get_potential_address_signatures,
                    verify_authority,
                    validate_transaction]

proposed_calls = []
blindied_calls = []
withdrawal_calls = []


for call in asset_calls:

    try:
        ws = websocket.create_connection(node)
        print('')
        print((call.split(',"params":')[1]).rstrip('}'))
        print('-----------------------------------------------------------')
        ws.send(call)
        ret = ws.recv()
        print (ret)
        ws.close()
    except Exception as e:
        print (e.args)
        pass

# you can also make https requests in this manner
'''
import requests
data = '{"id":1,"method":"call","params":["database","get_ticker",["CNY","USD"]]}'
response = requests.post('https://api.bts.mobi/wss;echo', data=data)
'''


also here:

https://github.com/litepresence/extinction-event
https://github.com/litepresence/extinction-event/blob/master/tools/bitshares-database-reference.py

10
get named balances returns an asset id without its human readable name....
and an amount - without the location of its decimal point!

this is kind of thing makes neckbeard itchy

Code: [Select]
["database","get_named_account_balances",["abc123", [] ]]
-----------------------------------------------------------
[{'asset_id': '1.3.0', 'amount': 12019967}, {'asset_id': '1.3.1382', 'amount': 100}, {'asset_id': '1.3.1578', 'amount': 100000000}, {'asset_id': '1.3.2419', 'amount': 500000}, {'asset_id': '1.3.2841', 'amount': 12000}, {'asset_id': '1.3.2931', 'amount': 10000}, {'asset_id': '1.3.3248', 'amount': 2580000}, {'asset_id': '1.3.3261', 'amount': 1000}, {'asset_id': '1.3.3279', 'amount': 10000}, {'asset_id': '1.3.3389', 'amount': 1000000000}, {'asset_id': '1.3.3431', 'amount': 1000}, {'asset_id': '1.3.3530', 'amount': 100000000}, {'asset_id': '1.3.3540', 'amount': 100000000}, {'asset_id': '1.3.3830', 'amount': '25000000000'}]

we can fix this... so get asset details

which is another api call and gives us "precision"; location of decimal, and the asset "symbol"; ie OPEN.BTC or BTS


but then we have to merge those dictionaries and they do not contain a common key; one has "asset_id" the other "id"

grrr

every call for what the asset is called and where its decimal point goes also contains bit of spam for every shitcoin donated to your account, on every bot tick, which brings in a huge page of asset banner ads like this silliness:


Code: [Select]
'{"main":"WARNING, DANGER, RED-ALERT, PANIC! PANIC! PANIC!\\n\\nYOU HAVE BEEN INFECTED,\\n\\nZOMBIES HAVE BEEN RELEASED! \\n\\nZombies are going to appear from nowhere & infest your portfolio,\\nSome zombies will come from your friends and family,\\nAND YES there are even some sickos out there that will want to buy Zombies too :s\\n\\n\\nThese VILE undead human corpses have risen, The Mission, BURN Zombies :)\\nHelp FILL THE POOL, Zombies are BURNED when there sent to the pool.\\n\\n\\nDisclaimer: NO REAL ZOMBIES WILL BE HURT IN THE CREATION OF THIS TOKEN ;)","short_name":"Zombies",

be thankful you're not on data plan!

nonetheless, hocus pocus account balances:

Code: [Select]
>>>
balances
{'TURION': 0.1, 'FREECOIN': 10000.0, 'SOLOMON': 0.1, 'BIRMINGHAMGOLD': 100.0, 'ZOMBIES': 12.0, 'DECENTRALIZED': 10.0, 'ANONYMOUS': 1.0, 'BTS': 120.19967, 'BTSJON': 1000.0, 'BADCOIN': 10000.0, 'HERTZ': 0.01, 'URTHONA': 50.0, 'SEED': 258.0, 'UNIVERSAL': 25000.0}


Code: [Select]
'litepresence 2018'

import websocket  #pip install websocket-client
websocket.enableTrace(False)
from ast import literal_eval as literal

def database_call(node, call):

    while 1:
        try:
            call = call.replace("'",'"') # never use single quotes
            ws = websocket.create_connection(node)
            print('')
            print((call.split(',"params":')[1]).rstrip('}'))
            print('-----------------------------------------------------------')
            ws.send(call)
            # 'result' key of literally evaluated
            # string representation of dictionary from websocket
            ret = literal(ws.recv())['result']
            print (ret)
            ws.close()
            return ret
        except Exception as e:
            print (e.args)
            pass

def account_balances(node, account_name):

    Z = '{"id":1,"method":"call","params":["database",'
    # make call for raw account balances as returned by api
    get_named_account_balances = Z + '"get_named_account_balances",["%s", [] ]]}' % (account_name)
    raw_balances = database_call(node, get_named_account_balances)
    # make list of asset_id's in raw account balances
    asset_ids = []
    for i in range(len(raw_balances)):
        asset_ids.append(raw_balances[i]['asset_id'])
    # make a second api request for additional data about each asset
    get_assets = Z + '"get_assets",[%s]]}' % asset_ids
    raw_assets = database_call(node, get_assets)
    # create a common key "asset_id" for both list of dicts
    # also extract the symbol and precision
    id_sym_prec = []
    for i in range(len(raw_assets)):
        id_sym_prec.append({'asset_id':raw_assets[i]['id'],
                            'symbol':raw_assets[i]['symbol'],
                            'precision':raw_assets[i]['precision'], })
    # merge the two list of dicts with common key "asset_id"
    data = {}
    lists = [raw_balances, id_sym_prec]
    for each_list in lists:
       for each_dict in each_list:
           data.setdefault(each_dict['asset_id'], {}).update(each_dict)
    # convert back to list
    data = list(data.values())
    # create a new dictionary containing only the symbol and quantity
    ret = {}
    for i in range(len(data)):
        qty = float(data[i]['amount'])/10**float(data[i]['precision'])
        ret[data[i]['symbol']] = qty
    return raw_balances, ret

#node = 'wss://bts-seoul.clockwork.gr' # websocket address
node = 'wss://api.bts.mobi/wss'
account_name = 'abc123' # string
raw_balances, balances = account_balances(node, account_name)


print('')
print('balances')
print(balances)

I'll also host this on my github

https://github.com/litepresence/extinction-event
https://github.com/litepresence/extinction-event/blob/master/tools/bitshares-account_balances.py

11
General Discussion / [ANN] microDEX - low latency minimalist UI
« on: March 27, 2018, 12:14:18 am »

What if the UI maintained DEX connection for months at a time?
What if the orderbook was updated several times per second?
What if the data feed was not dependent on a single whitelisted node?
What if historical CEX data and latest DEX data were on the same chart?

What if you could read and trust all the code that makes it happen
over a single cup of coffee?



[ANN] microDEX

Code: [Select]
                                     ______   ________  ____  ____ 
                                    (_   _ `.(_   __  |(_  _)(_  _)
     __  __  ____  ___  ____   ___    | | `. \ | |_ \_|  \ \__/ /   
    (  \/  )(_  _)/ __)(  _ \ / _ \   | |  | | |  _) _    ) __ (   
     )    (  _||_( (__  )   /( (_) ) _| |_.' /_| |__/ | _/ /  \ \_ 
    (_/\/\_)(____)\___)(_)\_) \___/ (______.'(________|(____)(____)
   =================================================================
           microDEX v0.00000009 - low latency minimalist UI
   =================================================================


BUY/SELL/CANCEL
LIVE LOW LATENCY MULTI NODE BOOKS
NEVER OUT OF SYNC
ALWAYS BLOCKCHAIN CONNECTED


minimal dependencies:

python3
pybitshares
tkinter
matplotlib


Code:

https://github.com/litepresence/extinction-event/blob/master/microDEX/microDEX.py

Installation:

https://github.com/litepresence/extinction-event/blob/master/Installation




more coming soon!


'till then, need botscript?  check me out at


litepresence.com



ETA:



how's this for soon?  v0.00000009 is live:





The Fastest DEX Orderbooks in the Business!



All that and just 1300 fluffy lines of script :D



12
General Discussion / 5 Node Verified Price Feed - Python
« on: March 18, 2018, 01:39:28 am »
developing here:

https://github.com/litepresence/extinction-event/tree/master/EV


working under the assumption that any node can provide rogue price feeds at any given time,
I sort all nodes by latency every two minutes
then check last price on 5 low latency nodes to verify authenticity of the data every 30 seconds


5 NODE VERIFIED LAST PRICE

nodes.py and last.py should be run in seperate terminals

nodes.py creates file nodes.txt
last.py creates file last.txt and appends to file blacklist.txt

nodes.txt is the top 10 latency sorted nodes of about 50 known nodes; updated approx every 2 minutes

last.py uses nodes.txt to get price from 5 nodes, then makes a list "prices", updated approx ever 30 seconds

then process that list of prices from 5 different nodes pseudocode:


if the spread of the prices is too wide:

    append to file blacklist.txt the list of prices and the list of nodes used to gather them


if all prices are same:
   
    last = latest price

elif latest price less than 2% different than mean(prices):
   
    last = latest price
 
else:
    try: last = mode(prices)
    except: last = median(prices)

write last to last.txt



the good news:

I ran this all day on BTS/BTC and no set of 5 prices were more than 2% different... meaning I never encountered a rogue node.

the better news:

this price feed can be used with confidence to feed bots with latest price data without risk of node going stale or going rogue

the best news:

I work on bid/ask tomorrow

:D

13
I am not an expert here, I'm simply an algo trader looking to integrate to the Bishares DEX environment by connecting to existing node architecture - without running my own node.  I have asked a lot of questions lately to Node Admins and have concluded there is a good deal of terminology involved that needs clarification.   There are also risks when dealing with existing nodes, that need to be mitigated.  So, please if you are an expert, chime in and I'll update this OP to summarize key points.   

This OP was initial populated with cut/paste commentary via Node Admin channel on Telegram.


NODES


some universal truisms:

- nodes are in no way uniform
- however, all nodes store all blocks
- any node can go rogue at any time
- every node is a man-in-the-middle between you and the blockchain


A node can be:

P2P

RPC

API - exposed to a network, either LAN or WAN

FULL -  nodes which provide full histories;  nodes which provide full histories; needs several tens of gigs of RAM; x5670 with 100G ram should be good for full history node

SEED - full nodes with publicly reachable p2p port

WITNESS - is a matter of votes, but you can run a witness node wich locally validates the blocks

PRODUCTION

LOAD BALANCED

PUBLIC

DOCKER

PAID

DELAY NODE

OWN USE

BLOCK PRODUCING

WHITE LISTED

BLACK LISTED

ACTIVE

STANDBY

LOW LATENCY

UNRESPONSIVE

TESTNET - testnet is actually used to determine if it's mainnet or testnet

SYNCHRONIZED

DATACENTER

HARDENED

SSL

VPS

DELAYED

INITIAL

FAKE - fake.automatic-selection is a hard-coded psuedo server

BITSHARES OFFICIAL - deployed with bitshares UI

CRYPTOBRIDGE OFFICIAL - deployed with cryptobridge UI

UP TO DATE - has a head block that is less than 3 seconds old

STALE - has a head block that is greater than 3 seconds old

PROPERLY DEPLOYED

LATEST VERSION

VERSION 171105a - if there are many wicks in price chart, it's on this version

pre-VERSION 1802xx - if owner key signature is not able to change active permissions, it's before 1802xx

ROGUE - a node can delay, refuse, or reorder your buy/sell/cancel or other requests.   A rogue node can also return inaccurate information to all or any one individual.  A rogue node can NOT modify or create a buy/sell/cancel operation on your behalf.  A rogue node can provide false account ID in an attempt to get you to send funds to bad address.


WORKING

VERIFIED



WALLETS


CLI - command line interface
PYBITSHARES
LIGHT
WEB WALLET
FAUCET - a pool of funds used to pay the registration fee for the new accounts, there are currently several public faucets up



PASSWORDS and KEYS


BRAIN

PASSPHRASE


14
When I get this error and it attempts a retry, it never actually does connect because the node itself is down or having issues.

Code: [Select]
Retrying in 2 seconds
Retrying in 4 seconds
Retrying in 6 seconds
etc.

How can I "catch" this retry-attempt like an error? 
How can I provide an argument to prevent any retry at all?

currently the only way I have found, is to use a `multiprocess.Process` approach to enforce a timeout that overrides the retry attempt by starting a side process to contain the node connect attempt, then breaking that process if it takes too long.   

I would rather it just break as soon as it says
Code: [Select]
Retrying in 2 seconds
as I've yet to see a retry actually accomplish anything.

Using a timeout approach has limitations; the timeout must be long enough to account for latency fluctuation, while being short enough to not eat up too much script time.

From my perspective, it would be advantageous if the pybitshares module, rather than attempting a retry on a down node, throws an exception that I can handle with try/except.  Upon exception, I can then specify a new node to attempt... rather than waiting for a timeout to expire.



related pybitshares code:

https://github.com/xeroc/python-bitshares/blob/9250544ca8eadf66de31c7f38fc37294c11f9548/bitsharesapi/websocket.py

beginning line 291

Code: [Select]
    def run_forever(self):
        """ This method is used to run the websocket app continuously.
            It will execute callbacks as defined and try to stay
            connected with the provided APIs
        """
        cnt = 0
        while not self.run_event.is_set():
            cnt += 1
            self.url = next(self.urls)
            log.debug("Trying to connect to node %s" % self.url)
            try:
                # websocket.enableTrace(True)
                self.ws = websocket.WebSocketApp(
                    self.url,
                    on_message=self.on_message,
                    on_error=self.on_error,
                    on_close=self.on_close,
                    on_open=self.on_open
                )
                self.ws.run_forever()
            except websocket.WebSocketException as exc:
                if (self.num_retries >= 0 and cnt > self.num_retries):
                    raise NumRetriesReached()

                sleeptime = (cnt - 1) * 2 if cnt < 10 else 10
                if sleeptime:
                    log.warning(
                        "Lost connection to node during wsconnect(): %s (%d/%d) "
                        % (self.url, cnt, self.num_retries) +
                        "Retrying in %d seconds" % sleeptime
                    )
                    time.sleep(sleeptime)

            except KeyboardInterrupt:
                self.ws.keep_running = False
                raise

            except Exception as e:
                log.critical("{}\n\n{}".format(str(e), traceback.format_exc()))


this snippet here is a major source of brittleness:

Code: [Select]
"Lost connection to node during wsconnect(): %s (%d/%d) "
                        % (self.url, cnt, self.num_retries) +
                        "Retrying in %d seconds" % sleeptime

A better behavior than just waiting and retrying on the same failed node is to switch nodes, THEN retry.


or simply raise the exception and let the user handle the failure: switching nodes; perhaps also blacklisting the old, or ringing a bell:

Code: [Select]
except websocket.WebSocketException:
    self.ws.keep_running = False
    raise

where the user could command:

Code: [Select]

attempt = 1
while attempt:

     try:

      # make api call
     attempt = 0

    except websocket.WebSocketException:

      # blacklist this node
      # run routine to find another white-listed node with low latency and non-stale blocktime
      attempt +=1
      if attempt > n:
          # run failsafe routine to generate new node list
      else:
          # switch node to known good node and loop
 


would it be possible to import the websocket.WebsocketException from the bitshares module?

something like

Code: [Select]
from bitshares import websocket.WebsocketException
but that doesn't work

I've also tried

Code: [Select]
from bitshares.websocket import WebsocketException
from bitshares import websocket
from bitshares import WebsocketException
and attempted to import the class function:

Quote
from bitshares import BitSharesWebsocket

but none of them work either, don't mind my ignorance here... just throwing things at the wall to see what sticks

I've also tried importing the websocket module and preempting the exception

Code: [Select]
import websocket

try:
    # connect to api
except websocket.WebsocketException:
    # print ('hello world')

does not catch

15
General Discussion / (Python) latency sorted Bitshares nodes
« on: March 11, 2018, 05:53:11 pm »
Update:  Developing here:
https://github.com/litepresence/extinction-event/blob/master/bitshares-node-latency.py







An "official" list of public nodes is here:

https://github.com/bitshares/bitshares-ui/blob/master/app/api/apiConfig.js

you can fetch it like this:
Code: [Select]
def nodes():  # Public Nodes List

    uri = 'https://raw.githubusercontent.com'
    url = uri+'/bitshares/bitshares-ui/master/app/api/apiConfig.js'
    raw = requests.get(url).text
    clean = ((raw.replace('"',"")).replace("'","")).replace(',','')
    parsed = [ t for t in clean.split() if t.startswith('wss') ]
    validated = [i for i in parsed if (('test' not in i) and ('fake' not in i))]

    return validated


result:
Code: [Select]
print (nodes())

>>>
['wss://bitshares.openledger.info/ws', 'wss://eu.openledger.info/ws', 'wss://bit.btsabc.org/ws', 'wss://bts.ai.la/ws', 'wss://bitshares.apasia.tech/ws', 'wss://japan.bitshares.apasia.tech/ws', 'wss://bitshares.dacplay.org/ws', 'wss://bitshares-api.wancloud.io/ws', 'wss://openledger.hk/ws', 'wss://bitshares.crypto.fans/ws', 'wss://ws.gdex.top', 'wss://dex.rnglab.org', 'wss://dexnode.net/ws', 'wss://kc-us-dex.xeldal.com/ws', 'wss://btsza.co.za:8091/ws', 'wss://api.bts.blckchnd.com', 'wss://eu.nodes.bitshares.ws', 'wss://us.nodes.bitshares.ws', 'wss://sg.nodes.bitshares.ws', 'wss://ws.winex.pro']



usage:
Code: [Select]
from bitshares.market import Market
from bitshares import BitShares

BitCURRENCY = 'OPEN.BTC'
BitASSET = 'BTS'
BitPAIR = BitASSET + ":" + BitCURRENCY
MARKET = Market(BitPAIR, bitshares_instance=BitShares(nodes()))

MARKET.buy()

Pages: [1] 2