Skip to content

Commit 5e47818

Browse files
twap/ annualized vol and documentation update
1 parent c2c30a7 commit 5e47818

17 files changed

+236
-46
lines changed

dashboard/dashboard.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ class Prices
4040
let expo = -pxa.price_exponent;
4141
let px = res.price * this.fact[expo];
4242
let conf = res.conf * this.fact[expo];
43+
let twap = res.twap * this.fact[expo];
44+
let avol = res.avol * this.fact[expo];
4345
let color = 'cornsilk';
4446
if ( res.status == 'unknown' ) {
4547
color = '#c0392b';
@@ -50,6 +52,8 @@ class Prices
5052
row.cells[col++].style.color = color;
5153
this.draw_cell( row.cells[col++], px.toFixed(expo), color );
5254
this.draw_cell( row.cells[col++], conf.toFixed(expo), color );
55+
this.draw_cell( row.cells[col++], twap.toFixed(expo), color );
56+
this.draw_cell( row.cells[col++], avol.toFixed(expo), color );
5357
this.draw_cell( row.cells[col++], res.status, color );
5458
this.draw_cell( row.cells[col++], res.valid_slot, color );
5559
this.draw_cell( row.cells[col++], res.pub_slot, color );
@@ -98,6 +102,8 @@ class Prices
98102
row.appendChild( document.createElement( 'TD' ) );
99103
row.appendChild( document.createElement( 'TD' ) );
100104
row.appendChild( document.createElement( 'TD' ) );
105+
row.appendChild( document.createElement( 'TD' ) );
106+
row.appendChild( document.createElement( 'TD' ) );
101107
row.appendChild( this.get_title( att, 'tenor') );
102108
row.appendChild( this.get_title( att, 'quote_currency') );
103109
row.appendChild( this.get_title( att, 'description') );

dashboard/index.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ <h2>pyth dashboard
1717
<th>ptype</th>
1818
<th width=100px>price</th>
1919
<th width=100px>conf</th>
20+
<th width=100px>twap</th>
21+
<th width=100px>avol</th>
2022
<th width=80>status</th>
2123
<th>valid_slot</th>
2224
<th>pub_slot</th>

doc/getting_started.md

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Getting started with publishing via pyth-client
22

3-
The pyth-client repo consists of a C++ library (libpc.a), a command-line administration tool (pyth) and a json/websocket-based server (pythd).
3+
The pyth-client repo consists of a C++ library (libpc.a), a command-line administration tool (pyth), a json/websocket-based server (pythd) and a gateway/proxy server for price publishing (pyth_tx).
44

55
You can integrate with libpc directly in your application. See `pctest/test_publish.cpp` for an example. Or, you can integrate with the pythd server via json/websockets. See `pctest/test_publish.py` for an example.
66

@@ -29,7 +29,7 @@ This will output the public key in base58 encoding and will look something like:
2929
5rYvdyWAunZgD2EC1aKo7hQbutUUnkt7bBFM6xNq2z7Z
3030
```
3131

32-
Once permissioned, you need two additional public keys in the key-store. The id of the mapping-account that contains the directory listing of the on-chain symbols and the id of the on-chain oracle program that you use to publish prices. Mapping and program accounts are maintained in three separate environments: pythnet, devnet and forthcoming mainnet-beta.
32+
Once permissioned, you need three additional public keys in the key-store. The id of the mapping-account that contains the directory listing of the on-chain symbols, the id of the on-chain oracle program that you use to publish prices and the id of the parameter-account that contains various math look-up tables used to compute the aggregate price. Mapping, program and parameter accounts are maintained in three separate environments: pythnet, devnet and forthcoming mainnet-beta.
3333

3434
Use the init_key_store.sh script to initialize these account keys:
3535

@@ -41,17 +41,19 @@ KENV=pythnet # or devnet or mainnet-beta
4141
4242
```
4343

44-
This creates two files: `$KDIR/program_key.json` and `$KDIR/mapping_key.json`.
44+
This creates three files: `$KDIR/mapping_key.json`, `$KDIR/program_key.json`, and `$KDIR/param_key.json`.
4545

4646
Once permissioned, you can test your setup by running the test_publish.cpp example program for publishing and subscribing to two test symbols. To test publishing on pythnet you need to run:
4747

4848

4949
```
50-
KHOST=44.232.27.44 # or api.devnet.solana.com
50+
KHOST=44.232.27.44
5151
./test_publish -k $KDIR -r $KHOST -t $KHOST
5252
```
5353

54-
The certification environment (pythnet) can be found at the IP address 44.232.27.44. Please also provide to the administrator the IP address you plan to publish to pythnet from so that it can be added to the pythnet firewall. Solana devnet can be found at: devnet.solana.com. No additional permissioning is required to publish to devnet.
54+
The -r and -t options correspond to the locations of required solana validator and pyth_tx server instances.
55+
56+
The certification environment (pythnet) can be found at the IP address 44.232.27.44 where the test validator and pyth_tx instances run. Please also provide to the administrator the IP address you plan to publish to pythnet from so that it can be added to the pythnet firewall.
5557

5658
You can also publish to solana using the pythd server. Start up the server using the same key-store directory and host specification:
5759

@@ -66,6 +68,25 @@ Run the test_publish.py example program on the same host to connect to the pythd
6668
6769
```
6870

71+
## Running the pyth_tx server
72+
73+
The pyth-client API connects to two separate services via TCP. These include the solana validator and pyth_tx servers. The pyth_tx server is included in the pyth-client repository.
74+
75+
The solana rpc interface is used for tracking slot and account updates. The pyth_tx server is used to submit price transactions directly to solana leader nodes via UDP.
76+
77+
pyth_tx runs as a separate server rather than being integrated directly into the client library to avoid a publisher from having to submit UDP datagrams to hundreds of different IP address from within an organization's firewall. Instead, a pyth_tx server can be deployed outside the firewall and a publisher clienti, running inside the firewall, can make a single TCP connection to it on a dedicated port.
78+
79+
You can run your own pyth_tx instance (recommended) or connect to provided server instances running against pythnet and mainnet-beta environments.
80+
81+
Start up the pyth_tx server as follows:
82+
83+
```
84+
./pyth_tx -r $KHOST
85+
```
86+
87+
The -r option points to the IP address of a solana validator node or rpc end-point. It can be the same or different IP address to that passed to test_publish or pythd as long as it corresponds to the same environment.
88+
89+
6990
## Running the dashboard
7091

7192
The pythd server also exports a dashboard web page for watching the ticking pyth prices. The public key you create above does not need publish-permission to watch the ticking pyth prices. To activate the dashboard page include an additional `-w` argument to pythd pointing at the html/javscript code directory:

doc/migrating_to_version_2.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Migrating to pyth version 2
2+
3+
Version 2 of the pyth on-chain program contains the full implementation of the aggregate price and confidence interval calculation. There have been changes to the price account data structure to make room for additional outputs including twap and volatility. A new account, known as the parameter account, has been introduced and contains math lookup tables that are required to compute the aggregate price.
4+
5+
A new set of mapping, product, price and program accounts has been deployed to devnet for version 2 and all publishers and subscribers should to migrate to these new accounts.
6+
7+
## Migrating publishers
8+
9+
Publishers should upgrade to the latest version of the pyth-client API (version 2). Two git branches, corresponding to versions 1 and 2, labelled v1 and v2, have been established to facilitate this.
10+
11+
Publishers need to migrate to new account keys. You should preserve your existing publishing key but update the mapping_key.json, program_key.json and param_key.json files in your key store directory. The simplest way to do this is to create a new directory, copy your publish_key_pair.json file to that directory and then run init_key_store.sh to generate the new account keys:
12+
13+
```
14+
KENV=pythnet # or devnet or mainnet-beta
15+
# KDIR= old key-store directory
16+
# NDIR= new key-store directory
17+
18+
# copy publish key over to new directory
19+
mkdir $NDIR
20+
cp $KDIR/publish_key_pair.json $NDIR
21+
22+
# initialize new directory
23+
../pctest/init_key_store.sh $KENV $NDIR
24+
```
25+
26+
The client API is also versioned and will fail to run against on-chain accounts that are set to a different version, so version 1 accounts must run against the v1 branch of the software and version 2 accounts must run against the v2 branch of the software.
27+
28+
## Migrating subscribers
29+
30+
On-chain subscribers should migrate to the new accounts defined above in the publishers section. New price accounts contain additional values derived from the aggregate price including twap and volatility as well as space for additional contributing publishers, now upgraded to 32 publishers from 16 in version 1:
31+
32+
```
33+
// from program/src/oracle/oracle.h:
34+
typedef struct pc_price
35+
{
36+
//...
37+
int64_t twap_; // time-weighted average price
38+
int64_t avol_; // annualized price volatility
39+
//....
40+
pc_price_comp_t comp_[PC_COMP_SIZE];// component prices
41+
} pc_price_t;
42+
43+
```
44+
45+
Please note that the version field in all version 2 account headers now read 2 instead of 1.

pc/request.cpp

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1995,6 +1995,8 @@ price::price( const pub_key& acc, product *prod )
19951995
pub_idx_( (unsigned)-1 ),
19961996
apx_( 0 ),
19971997
aconf_( 0 ),
1998+
twap_( 0 ),
1999+
avol_( 0 ),
19982000
valid_slot_( 0 ),
19992001
pub_slot_( 0 ),
20002002
lamports_( 0UL ),
@@ -2004,7 +2006,6 @@ price::price( const pub_key& acc, product *prod )
20042006
sched_( this )
20052007
{
20062008
__builtin_memset( &cpub_, 0, sizeof( cpub_ ) );
2007-
__builtin_memset( &dpx_, 0, sizeof( dpx_ ) );
20082009
areq_->set_account( &apub_ );
20092010
sreq_->set_account( &apub_ );
20102011
preq_->set_account( &apub_ );
@@ -2072,10 +2073,14 @@ int64_t price::get_price() const
20722073
return apx_;
20732074
}
20742075

2075-
int64_t price::get_deriv( deriv_type dtype ) const
2076+
int64_t price::get_twap() const
20762077
{
2077-
unsigned i = (unsigned)dtype - 1;
2078-
return i<PC_DERIV_SIZE?dpx_[i] : 0L;
2078+
return twap_;
2079+
}
2080+
2081+
uint64_t price::get_ann_volatility() const
2082+
{
2083+
return avol_;
20792084
}
20802085

20812086
uint64_t price::get_conf() const
@@ -2227,13 +2232,12 @@ void price::init_price( pc_price_t *pupd )
22272232
version_ = pupd->ver_;
22282233
apx_ = pupd->agg_.price_;
22292234
aconf_ = pupd->agg_.conf_;
2235+
twap_ = pupd->twap_;
2236+
avol_ = pupd->avol_;
22302237
sym_st_ = (symbol_status)pupd->agg_.status_;
22312238
pub_slot_ = pupd->agg_.pub_slot_;
22322239
valid_slot_ = pupd->valid_slot_;
22332240
cnum_ = pupd->num_;
2234-
for( unsigned i=0; i < (unsigned)deriv_type::e_last_deriv_type-1;++i ) {
2235-
dpx_[i] = pupd->drv_[i];
2236-
}
22372241
for( unsigned i=0; i != cnum_; ++i ) {
22382242
if ( !pc_pub_key_equal( &cpub_[i], &pupd->comp_[i].pub_ ) ) {
22392243
pc_pub_key_assign( &cpub_[i], &pupd->comp_[i].pub_ );
@@ -2337,12 +2341,11 @@ void price::update( T *res )
23372341
if ( valid_slot_ != pupd->valid_slot_ || valid_slot_ == 0UL ) {
23382342
apx_ = pupd->agg_.price_;
23392343
aconf_ = pupd->agg_.conf_;
2344+
twap_ = pupd->twap_;
2345+
avol_ = pupd->avol_;
23402346
sym_st_ = (symbol_status)pupd->agg_.status_;
23412347
pub_slot_ = pupd->agg_.pub_slot_;
23422348
valid_slot_ = pupd->valid_slot_;
2343-
for( unsigned i=0; i < (unsigned)deriv_type::e_last_deriv_type-1;++i ) {
2344-
dpx_[i] = pupd->drv_[i];
2345-
}
23462349

23472350
// capture aggregate price and components to disk
23482351
mgr->write( (pc_pub_key_t*)apub_.data(), (pc_acc_t*)pupd );
@@ -2444,3 +2447,4 @@ void price_sched::schedule()
24442447
{
24452448
on_response_sub( this );
24462449
}
2450+

pc/request.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -694,7 +694,8 @@ namespace pc
694694
uint64_t get_conf() const;
695695
symbol_status get_status() const;
696696
uint64_t get_lamports() const;
697-
int64_t get_deriv( deriv_type ) const;
697+
int64_t get_twap() const;
698+
uint64_t get_ann_volatility() const;
698699

699700
// get publishers
700701
unsigned get_num_publisher() const;
@@ -751,10 +752,11 @@ namespace pc
751752
uint32_t pub_idx_;
752753
int64_t apx_;
753754
uint64_t aconf_;
755+
int64_t twap_;
756+
uint64_t avol_;
754757
uint64_t valid_slot_;
755758
uint64_t pub_slot_;
756759
uint64_t lamports_;
757-
int64_t dpx_[PC_DERIV_SIZE];
758760
int32_t aexpo_;
759761
uint32_t cnum_;
760762
product *prod_;

pc/rpc_client.hpp

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,6 @@ namespace pc
3434
price_type str_to_price_type( str );
3535
str price_type_to_str( price_type );
3636

37-
// type of derived (from price) calculation
38-
enum class deriv_type
39-
{
40-
e_unknown = PC_DTYPE_UNKNOWN,
41-
e_twap = PC_DTYPE_TWAP,
42-
e_volatility = PC_DTYPE_VOLATILITY,
43-
44-
e_last_deriv_type
45-
};
46-
47-
deriv_type str_to_deriv_type( str );
48-
str deriv_type_to_str( deriv_type );
49-
5037
// current symbol trading status
5138
enum class symbol_status
5239
{

pc/user.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,8 @@ void user::on_response( price *rptr, uint64_t idx )
353353
jw_.add_key( "result", json_wtr::e_obj );
354354
jw_.add_key( "price", rptr->get_price() );
355355
jw_.add_key( "conf", rptr->get_conf() );
356+
jw_.add_key( "twap", rptr->get_twap() );
357+
jw_.add_key( "avol", rptr->get_ann_volatility() );
356358
jw_.add_key( "status", symbol_status_to_str( rptr->get_status() ) );
357359
jw_.add_key( "valid_slot", rptr->get_valid_slot() );
358360
jw_.add_key( "pub_slot", rptr->get_pub_slot() );

pcapps/pyth_csv.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ void csv_print::print_header()
7272
<< ",status"
7373
<< ",price"
7474
<< ",conf"
75+
<< ",twap"
76+
<< ",avol"
7577
<< ",valid_slot"
7678
<< ",pub_slot";
7779
for(unsigned i=0; i != PC_COMP_SIZE; ++i ) {
@@ -130,6 +132,8 @@ void csv_print::parse_price( replay& rep )
130132
std::cout.write( sstr.str_, sstr.len_ );
131133
std::cout << ',' << ptr->agg_.price_
132134
<< ',' << ptr->agg_.conf_
135+
<< ',' << ptr->twap_
136+
<< ',' << ptr->avol_
133137
<< ',' << ptr->valid_slot_
134138
<< ',' << ptr->agg_.pub_slot_;
135139
for( unsigned i=0; i != ptr->num_; ++i ) {

pctest/init_key_store.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,4 @@ echo $MAP_KEY > $KDIR/mapping_key.json
4545
check "chmod 0400 $KDIR/mapping_key.json"
4646
echo $PRM_KEY > $KDIR/param_key.json
4747
check "chmod 0400 $KDIR/param_key.json"
48+
check "chmod 0700 $KDIR"

0 commit comments

Comments
 (0)