电力竞价(广东规则)详解与代码

电力改革如火如荼,针对电力交易的广东规则,本文进行了详细地阐述并附上了代码与实例,供大家一起交流学习。

竞价规则

本竞价规则参考广东电力交易中心目前的竞价规则。

该内容及算例引用了售电市场研修院的内容,并感谢北京清软创新科技股份有限公司研究中心主任罗欣的讲解。

交易规模

交易牵涉两大角色,卖电方和买电方:

  • 卖电方:发电企业
  • 买电方:售电公司、电力大用户

交易牵涉一个变量:

  • 成交比例

也就是说,买卖双方的电量不会全部成交。

例如,如果发电企业意向申报交易规模100万千瓦时,售电公司意向申报规模80万千瓦时,电力大用户意向申报20万千瓦时。 若设置成交比例为80%,则竞争交易电力规模为100*0.8=80万千瓦时。

报价规则

报价规则牵涉的变量有:

  • 报价形式(双向报价,下面内容均特指该报价形式)
  • 发电企业申报与上网电价的价差
  • 发电企业申报与上网电价的价差范围
  • 售电公司、电力大用户申报与现行目录电价中的价差
  • 售电公司、电力大用户申报与现行目录电价中的价差范围

所报价差必须在指定的价差范围内。

例如: 发电企业申报价差范围:-50到-500厘/千瓦时。 售电公司及电力用户申报价差范围:0到-100厘/千瓦时。 发电企业上网电价为:500厘/千瓦时,申报价差:-100厘/千瓦时,表示期望卖出电价为400厘/千瓦时。 售电公司及电力用户目录电价为500厘/千瓦时,申报价差为-50千瓦时,表示期望买入电价为450厘/千瓦时。

撮合规则

这里,首先介绍下价差对的概念:

价差对=发电企业申报价差−售电公司或电力用户申报价差

价差对=发电企业申报价差-售电公司或电力用户申报价差

例如:发电企业申报价差为-100厘/千瓦时,电力大用户申报价差为-50厘/千瓦时,价差对为-100-(-50)= -50厘/千瓦时。

需要注意的是:

  • 价差对只有是负的才可以成交,表示卖方对买方让利(试想,如果卖方一直保持高价格不对买方让利,交易怎么可能成交呢)。
  • 卖方(发电企业)肯定希望价差的绝对值越小越好,这样表示他让利让的少啊。
  • 买方(售电企业与电力用户)肯定希望价差的绝对值越大越好,因为这意味着自己买电的价格更低,从卖方获利越大。
  • 价差对绝对值越大的越优先成交(相当于卖家让利最大)。
  • 当价差对相同的时候,按申报价差对应电量比例确定中标电量。

结算规则

结算规则主要涉及两点:

  • 价差电费返还:配对成交的买卖双方存在价差对,因此会产生价差电费,价差电费按照各自申报成交电费成比例返还给发电企业和大用户。
  • 价差返还系数:50%意味着价差电费在价差对双方之间平均分配。
  • 平均结算价格:(成交电量部分申报价差*成交电量+-返还电费)/总成交量

实例讲解

下面附上一个例子,并附上相应代码仅供交流学习。

交易双方

该交易涉及的发电企业与用电大用户数据如下:

交易情况概述

每轮的交易情况概述如下:

交易结算

发电企业的交易结算如下:

电力用户的交易结算如下:

代码

# coding: utf-8

# In[1]:

from __future__ import division
import pandas as pd


# # 基础类定义

# In[2]:

# 定义类
class Producer:
    def __init__(self,name,amount,price):
        self.name = name
        self.amount = amount
        self.price = price
        self.amount_left = amount
        self.accu_money = 0
        self.accu_money_diff = 0
    def __repr__(self):
        return "<Producer name:%2s  amount:%6s  price:%7s amount_left:%6s>" % (self.name, self.amount, self.price, self.amount_left)

class User:
    def __init__(self,name,amount,price):
        self.name = name
        self.amount = amount
        self.price = price
        self.amount_left = amount
        self.accu_money = 0
        self.accu_money_diff = 0
    def __repr__(self):
        return "<User name:%2s  amount:%6s  price:%7s amount_left:%6s>" % (self.name, self.amount, self.price, self.amount_left)


class Process:
    def __init__(self,amount,p_price,u_price):
        self.amount = amount
        self.p_price = p_price
        self.u_price = u_price
        self.diff_price = p_price-u_price
    def __repr__(self):
        return "<Process amount:%6s  p_price:%7s  u_price:%7s  diff_price:%7s>" % (self.amount, self.p_price, self.u_price, self.diff_price)


# # 参数设置

# In[3]:

# 设置买卖双方的参数
producers_name = ['A','B','C','D','E']
producers_amount = [14975,18099,59015,53707,87809]
producers_price = [-500,-334.3,-145.7,-105.8,-60.6]

users_name = ['1','2','3','4','5']
users_amount = [67983,39403,64478,38592,19799]
users_price = [-45,-35.8,-26.7,-14.3,-0.1]


# In[4]:

producers = []
for name,amount,price in zip(producers_name,producers_amount,producers_price):
    producers.append(Producer(name,amount,price))
users = []
for name,amount,price in zip(users_name,users_amount,users_price):
    users.append(User(name,amount,price))

# sort producers and users
import operator
producers_inline = sorted(producers, key=operator.attrgetter('price'), reverse=False)
users_inline = sorted(users, key=operator.attrgetter('price'), reverse=True)


# In[5]:

producers_inline


# In[6]:

users_inline


# # 交易撮合

# In[7]:

# 确定针对producers_inline和users_inline的指针
producer_pt = 0
user_pt = 0

# 指定参数
deal_ratio_proc = 0.8  #发电企业的成交比例
deal_amounts = 0      #成交数量累计
deal_amounts_max = sum(producers_amount)*deal_ratio_proc   #最大的成交数量
df = pd.DataFrame(columns=('发电企业', '申报电量', '申报价差','售电公司', '申报电量', '申报价差', '价差', '成交电量'))  #数据框初始化
df_i = 0   #数据框的行指针
processes = []     #累计每个交易流程
flag_stop = False  #判断是否到达成交比例的flag

# 交易流程
while user_pt < len(users_inline) and producer_pt < len(producers_inline):
    cur_producer = producers_inline[producer_pt]
    cur_user = users_inline[user_pt]
    diff_amount = cur_producer.amount_left - cur_user.amount_left
    diff_price = float(cur_producer.price) - float(cur_user.price)
    # 只有当价差对为负的时候才有可能成交
    if diff_price > 0:
        break
    deal_amount =  min(cur_producer.amount_left,cur_user.amount_left)
    deal_amounts += deal_amount
    # 只有当交易量在规定范围内才有可能成交,否则将flag_stop设置为True
    if deal_amounts > deal_amounts_max:
        curr_del_amount = deal_amounts_max - (deal_amounts-deal_amount)
        flag_stop = True
    else:
        curr_del_amount = deal_amount 
    # 针对每次交易过程的数据统计计算
    ##输出信息
    print "P:%s U:%s P_left_Amount:%6s U_left_Amount:%6s Deal_Amount:%6s Price_Differ:%s" % (cur_producer.name,     cur_user.name, cur_producer.amount_left, cur_user.amount_left, int(curr_del_amount),     cur_producer.price-cur_user.price) 
    ##进程信息统计
    processes.append(Process(int(curr_del_amount),cur_producer.price,cur_user.price))
    ##累计电费与累计价差电费
    cur_user.accu_money += cur_user.price*int(curr_del_amount)
    cur_user.accu_money_diff += (cur_producer.price-cur_user.price)*int(curr_del_amount)
    cur_producer.accu_money += cur_producer.price*int(curr_del_amount)
    cur_producer.accu_money_diff += (cur_producer.price-cur_user.price)*int(curr_del_amount)
    ##数据库信息统计
    df.loc[df_i] = [cur_producer.name,cur_producer.amount,cur_producer.price,            cur_user.name,cur_user.amount,cur_user.price,           cur_producer.price-cur_user.price,curr_del_amount]
    df_i += 1
    ##判断终止条件
    if flag_stop:
        cur_user.amount_left -= curr_del_amount
        cur_producer.amount_left -= curr_del_amount
        break
    ##判断交易方向,卖者还是买者退出市场
    if diff_amount == 0:
        user_pt += 1
        producer_pt += 1
        cur_user.amount_left = 0
        cur_producer.amount_left = 0
    elif diff_amount < 0:  #卖的少,买的多,卖者退出市场
        producer_pt += 1
        cur_user.amount_left -= curr_del_amount
        cur_producer.amount_left = 0
    else:                  #卖的多,买的少,买者退出市场
        user_pt += 1
        cur_user.amount_left = 0
        cur_producer.amount_left -= curr_del_amount


# # 交易整理

# In[8]:

df


# # 结算情况

# ## 发电公司

# In[9]:

producers_accounts = pd.DataFrame([(i.name,i.amount,i.amount_left,i.accu_money,i.accu_money_diff)for i in producers],columns=('name','amount','amount_left','accu_money','accu_money_diff'))


# In[10]:

producers_accounts['price'] = producers_price
producers_accounts['amount_deal'] = producers_accounts['amount'] - producers_accounts['amount_left']
producers_accounts['accu_money_ratio'] = producers_accounts['accu_money']/sum(producers_accounts['accu_money'])
producers_accounts['return_money'] = producers_accounts['accu_money_ratio']*sum(producers_accounts['accu_money_diff'])*0.5
producers_accounts['real_monty'] = producers_accounts['accu_money'] -  producers_accounts['return_money']
producers_accounts['real_price'] = producers_accounts['real_monty']/producers_accounts['amount_deal']


# In[11]:

columns_ordered = ['name', 'price','amount', 'amount_left','amount_deal', 'accu_money','accu_money_ratio', 'accu_money_diff',                   'return_money','real_monty', 'real_price']
producers_accounts = producers_accounts[columns_ordered]
producers_accounts.columns = ['名称','申报价差','申报电量','剩余电量','中标电量','累计电费(不含返还)','累计电费占比','累计价差电费',                             '返还电费','中标电费(含返还)','中标价差']
producers_accounts


# ## 售电公司与电力用户

# In[12]:

users_accounts = pd.DataFrame([(i.name,i.amount,i.amount_left,i.accu_money,i.accu_money_diff)for i in users],columns=('name','amount','amount_left','accu_money','accu_money_diff'))


# In[13]:

users_accounts['price'] = users_price
users_accounts['amount_deal'] = users_accounts['amount'] - users_accounts['amount_left']
users_accounts['accu_money_ratio'] = users_accounts['accu_money']/sum(users_accounts['accu_money'])
users_accounts['return_money'] = users_accounts['accu_money_ratio']*sum(users_accounts['accu_money_diff'])*0.5
users_accounts['real_monty'] = users_accounts['accu_money'] +  users_accounts['return_money']
users_accounts['real_price'] = users_accounts['real_monty']/users_accounts['amount_deal']


# In[14]:

columns_ordered = ['name', 'price','amount', 'amount_left','amount_deal', 'accu_money','accu_money_ratio', 'accu_money_diff',                   'return_money','real_monty', 'real_price']
users_accounts = users_accounts[columns_ordered]
users_accounts.columns = ['名称','申报价差','申报电量','剩余电量','中标电量','累计电费(不含返还)','累计电费占比','累计价差电费',                             '返还电费','中标电费(含返还)','中标价差']
users_accounts

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏区块链大本营

如何向弱智程序员解释区块链

3334
来自专栏一名叫大蕉的程序员

区块链?黑人问号?NO.1

# 区块链的大白话 我是小蕉。 从前的从前啊,有一个桃花屯,屯里住着一群跟小布小青这样的种田青年。屯里出现了这么一件事,每年的收成都是几千斤几千斤这样,每次出去...

18210
来自专栏企鹅号快讯

POW和POS机制究竟是什么?二

POS:拥有的币越多,有记账权的概率就越大? POS(Proof of Stake),权益证明,试图解决POW机制中大量资源被浪费的情况。这种机制通过计算你持有...

2065
来自专栏企鹅号快讯

区块链搬砖的坑及有效鉴别方法

经过上篇文章“区块链搬砖要避免哪些坑”的了解,相信大家对搬砖已经有一个基本的了解。本节课我想在上篇的基础上继续和大家分享下我在搬砖过程中遇到的坑及常用鉴别方法,...

3287
来自专栏区块链领域

美女BTC月赚24.6%,用免费交易所多赚7800

第一,不要24小时看盘,只要没有突破区间,就不要管,不要想买在谷底,抛在峰顶,心态非常非常重要,再重复一遍,心态非常非常重要。

832
来自专栏钱塘大数据

如何向菜鸟解释区块链?

? 导读:区块链技术的文章泛滥成灾,但大多读起来晦涩难懂。这篇在知乎上点赞量达到1万+的文章,就有点意思了。作者写这篇文章初衷正是苦恼于不知该如何跟弱智室友解...

3826
来自专栏区块链资讯

比特币分叉案判决,丢失的BCH终于又回来了

去年8月1日,UTC时间(零时区)12:37,比特币在区块高度478558开始硬分叉,比特币现金就此诞生了。

593
来自专栏一名叫大蕉的程序员

用区块链解决桃花屯的粮食问题No.49

我是小蕉。 从前的从前啊,有一个桃花屯,屯里住着一群跟小布小青这样的种田青年。屯里出现了这么一件事,每年的收成都是几千斤几千斤这样,每次出去卖一趟粮食,我了个乖...

19710
来自专栏企鹅号快讯

用两性关系解释区块链:你和前任干的那些事,现任都知道

【腾讯科技打开脑洞整理报道】区块链的概念依旧在不停升温,上周,为了让更多的网友搞清楚什么是区块链,我们特意做了一组图看懂系列。 虽然很多网友表示“恍然大悟”,但...

1708
来自专栏汇智网教程

2018最新区块链白皮书大全

3816

扫码关注云+社区