深创投李守宇-创投之道在于双赢-企业喜欢有智慧的VC_PE

2017年7月29日,由投资家网和中国科技金融促进会风险投资专业委员会联合主办的“投资家网·2017中国股权投资峰会”在深圳福田香格里拉酒店隆重举行。

本次峰会以“股权投资大时代”为主题,深度剖析“股权投资大时代”的全新业态,并将邀请国内一线私募股权投资机构及一线FOFs、政府引导基金、上市公司、国内外高净值个人、优秀创业企业、各地政府领导等优质LP聚集一堂,共同探讨2017退出之路、新环境下的投资探索、智能制造,新经济的突破口等热点话题。

值得一提的是,投资家网联合中国科技金融促进会风险投资专业委员会发布的“2016-2017中国股权投资行业系列榜单”以及由投资家网研究院出品、投资家网WFin数据库支持的“中国股权投资市场十年回顾暨2017半年度研究统计报告”,于7月29日隆重揭晓和重磅发布。

深圳市创新投资集团有限公司副总裁李守宇出席了峰会,并在主题为“2017,创投的投资策略及方向-创业投资的价值发现”的演讲中表示,投资机构不能光会做Pre-IPO项目,对早期天使项目,也要时刻关注。不仅仅要关注一些有专利、有技术的早期项目,还要关注初期能够创造较大价值、对企业退出有较大引领性质的早期项目。李守宇还表示创投之道是一门技术,更是一门艺术,可谓“道可道,非常道”。但我们要讲的是天之道,利而无害,投资一定要对LP、所投企业持双赢的趋势。

以下为李守宇在“投资家网2017中国股权投资峰会(深圳)”上的演讲实录,根据速记整理:

01 投资回归理性,早期项目受到青睐

感谢投资家网在深圳召开的这次峰会。这次峰会的主题——“股权投资大时代”起得非常好,我们VC/PE就是股权投资大时代的引领者。

这些年来资本市场发展的非常迅速,尽管全球经济下行的压力不断增加,但中国的经济形势整体进了L型趋势,增速继续保持着稳步的增长。

近日,习近平主席指出“稳中求进不是无所作为,不是强力维稳、机械求稳……”。从资本市场来说,供给侧改革、投资消费以及供给侧需求等,这些都需要投资拉动。同时我们也看到无论是美国还是1998年的韩国,这些国家从泥潭中走出来均是依靠改革,尤其是供给侧改革。改革需要货币增发,货币增发容易引起通货膨胀,因此在此阶段投资是一个很大的孤岛。投资对抵抗货币的增发、货币贬值,有很大的促进作用。

从这些年的发展来看,创业、投资更加回归理性。从创业、PE投资来说,经过了2016年的蓬勃发展,投资案例数和投资金额都有很大的提高,投资任务不减。虽然早期项目、案例数有所下降,但金额持续上升,并购持续活跃,同比上升76.6%。

2016年全球范围内有291家中企完成上市,2017年沪深股市IPO数量不断增加,让投资和退出形成了较好的良性循环。

从创投市场的竞争环境来看,大家对投资的热度不减。现在企业家们都在持续不断地创业,但总体来说,目前能够创造更多利润、有更好成长性的优质项目比较难寻了,但相对而言投资机构对好项目的追求却在不断增加。这使得机构也在逐渐加强对早期项目的投资,因为投资机构不能光会做Pre-IPO项目,对早期天使项目,也要时刻关注。不仅仅要关注一些有专利、有技术的早期项目,还要关注初期能够创造较大价值、对企业退出有较大引领性质的早期项目。在并购方面,要求投资机构对企业资源、整体价值进行有效地整合,这也要求投资机构有更高的技术水平。

02 深创投的投资方向

从创业投资的产业选择上来看,未来创投市场对全球技术的转移非常看重。

未来创投关注的方向主要在技术创新驱动,以及消费升级带来的产业投资机会上。从美国到以色列、欧洲、日本、中国,这几年技术创新驱动更加注重产能以及创新的驱动。今后有创新驱动、产业整合、消费升级带来的产业升级项目是我们投资的方向。

另外,自主创新的高新技术企业处于国民经济的核心地位,是民族栋梁产业。过去中国是世界上最大的能源消费国,传统型、高能耗、易污染企业占中国经济的主导地位。而现在中国对新经济有很大的需求,包括节能环保等方面。对创业投资来说,引领产业升级,引领新的经济、更好的科技发展、更加潮流的企业,是创投人的责任和方向。深创投也正是本着这样的精神,为了改变中国经济状况而不断努力着。

新一代信息技术,是“信息时代”的基石,因此我们深创投有几个投资方向,即物联网、大数据、人工智能、汽车电子等。

这些年生物健康是很多企业和投资机构推崇的方向,生物医药、生物技术、医疗服务、医疗器械,也是很多机构投入的方向。虽然生物健康行业投资周期长,对技术有很高的需求和判断,也需要耐心,但从深创投现在投资的效果上来看,各方面也表现出较好的预期。目前我们投资多年的华大基因已经挂牌上市,包括原来在新三板挂牌的微点生物,也给深创投带来了很大的投资回报。

此外,节能环保产业对我国经济以及人民生活的幸福、稳定有很多好处,这方面也是深创投非常看重的投资方向。

这些年高端装备也是中国非常热门的投资方向,包括工业机器人、无人机、服务机器人、3D打印等。最近我们在美国、中国分别投了一个3D打印企业,在美国投资的这家3D公司被评为全球最聪明的公司之一。

在新能源投资方面,中国的新能源汽车在世界上发展的速度非常快,某种程度上来说,在全球起着引领的作用。国家科技部、发改委给予新能源汽车非常多的政策。包括比亚迪等一系列企业对新能源汽车的发展方向有较大的提高。在我看来,新能源汽车会像高铁一样,将来一定处于世界上非常领先的地位。

在深创投投资的案例中,潍柴动力是我们投资的明星企业,在汽车零部件、汽车发动机方面是发展较好的公司。除此之外最近上市的华大基因、今年刚上市的正海生物,包括汽车零部件轴承方面的领先电子企业五洲新春等都是我们投资的一些案例。

中国目前正在从第一生产大国向第一消费大国迈进。人均收入翻倍,对消费升级、投资和经济发展有较好的驱动。目前消费人群最旺盛的是35-64岁年龄阶段人口,2030年将持续提高。

随着互联网、物流、城镇化率的不断提高,以及消费升级的到来,包括实物消费升级和精神消费升级在内的物品、影视、娱乐、电视节目等,都会对投资和经济有很大的带动。一些与健康、美丽、快乐、休闲放松、追求个性化等词汇相关的产业,都将来是新经济引领的方向。

03 创投之道,一定要对LP、所投企业持双赢态势

这次投资家网峰会所提出的“股权投资大时代”的主题非常好。从企业、国家、经济等方面的发展来看,目前投资已经从银行的间接融资向直接融资方向发展了。投资将是未来个人资产、公司资产、整体资产保值增值非常好的手段。

创投之道是一门技术,更是一门艺术,可谓“道可道,非常道”。但我们要讲的是天之道,利而无害,投资一定要对LP、所投企业持双赢的趋势。

中国股权投资为什么能引起大家的推崇,为什么今天的主题是股权投资大时代?因为在这中间有着资本市场、中国企业家的聪明、才智和勤劳,才让我们的财富在不断增值,使我们能形成投资各方共赢的态势。

当然投资也是价值变现,挖掘市场价格差,要靠寻觅、分析、感觉。创业投资是什么?是金融和科技、资金和管理相结合的专业性投资。这种权益投资大都是注重现金流、利润、分红,更加注重企业长期发展和长期股权投资的增值。现在做投资的人很多,这就需要投资的感觉、经验、机制。

创业投资喜欢什么样的企业?从人本主义来说,我们喜欢企业家诚信,没有诚信的企业家是难有作为的。同时企业家也要有志向,将来要将企业做大做强,有远见,能预见行业的发展,要整体态势敏锐,果敢、豁达,对小事不斤斤计较,以及要有合作团队精神。当然健康也是企业家要非常重要的一方面。从现在投资成功的企业来说,身体健康、体力充沛,35-55岁之间的企业带头人,上市企业的比例比较高。

反过来,企业需要什么样的VC/PE?需要有“智慧”的VC/PE,这些人能够帮助企业打造核心竞争力,和企业一起持续提高盈利能力,提高企业的品牌影响力,改善企业经营环境,优化企业股东结构。

另外也需要能够提供“增值服务”的VC/PE,能成为企业的股东,帮助企业规范运作,帮助企业制定和实施战略,帮助企业进行资源整合,开拓市场渠道,为企业进行诊断,帮助它们解决疑难杂症等。

目前深创投成立了并购部、企业服务中心,我们投后的很多企业,投完之后还持续定增,帮助资本运作。从1999年深创投成立,当时是7亿注册资本,而现在深创投母公司发展的总资产已达235亿,净资产近130亿。

这些年随着深创投资产的增加,从2011年以来,深创投每年保持着10亿以上的利润。除了自己母公司的230亿左右的总资产,目前我们管理的资金规模已经达到2100亿,其中包括深圳市政府引导基金1000亿。并且我们还在全国参与了政府引导子基金,达到83支,很多地方都有我们的企业。

举例来说,在东北,深创投有三支基金,并投入了十几个项目,目前已经上市了几家。主要形式是和当地政府进行合作,由当地政府出一部分资金,深创投出一部分资金共同投资项目。投资团队一般都在当地,东北这边有10个人左右,也以当地人员为主,只有在当地的人员才更了解当地的情况。深创投还会对当地企业家进行培训,随时提供增值服务,能做到跟企业家零距离接触,这样的效果就更好。

深创投还管理了首支国家中小企业发展的基金的首支实体基金,规模大概60亿。另外佛山市政府母基金、山东财金红土基金、前海母基金、东莞母基金,包括中外合资基金5支,还有红土创新基金。

深创投已经投资的企业大约700多家,已经在全球资本市场上市了126家,仅今年就已经上市了14家。从投资项目上来看,主要为新兴的高科技行业,初创项目占到80%。

这么多年以来,深创投和LP、投资企业,都保持了很好的关系。感谢社会各界、LP、包括各级政府引导基金对我们的支持,谢谢大家!

Metaclass_in_Python

I pick this post from stackoverflow, it’s really awesome, thanks for e-satis .

Here is the original link : http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python

Classes as objects

Before understanding metaclasses, you need to master classes in Python. And Python has a very peculiar idea of what classes are, borrowed from the Smalltalk language.

In most languages, classes are just pieces of code that describe how to produce an object. That’s kinda true in Python too:

1
2
3
4
5
6
7
>>> class ObjectCreator(object):
... pass
...

>>> my_object = ObjectCreator()
>>> print my_object
<__main__.ObjectCreator object at 0x8974f2c>

But classes are more than that in Python. Classes are objects too.

Yes, objects.

As soon as you use the keyword class, Python executes it and creates an OBJECT. The instruction

1
2
3
>>> class ObjectCreator(object):
... pass
...

creates in memory an object with the name ObjectCreator.

This object (the class) is itself capable of creating objects (the instances), and this is why it’s a class.

But still, it’s an object, and therefore:

you can assign it to a variable
you can copy it
you can add attributes to it
you can pass it as a function parameter
e.g.:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
>>> print ObjectCreator # you can print a class because it's an object
<class '__main__.ObjectCreator'>
>>> def echo(o):
... print o
...
>>> echo(ObjectCreator) # you can pass a class as a parameter
<class '__main__.ObjectCreator'>
>>> print hasattr(ObjectCreator, 'new_attribute')
False
>>> ObjectCreator.new_attribute = 'foo' # you can add attributes to a class
>>> print hasattr(ObjectCreator, 'new_attribute')
True
>>> print ObjectCreator.new_attribute
foo
>>> ObjectCreatorMirror = ObjectCreator # you can assign a class to a variable
>>> print ObjectCreatorMirror.new_attribute
foo
>>> print ObjectCreatorMirror()
<__main__.ObjectCreator object at 0x8997b4c>

Creating classes dynamically

Since classes are objects, you can create them on the fly, like any object.

First, you can create a class in a function using class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
>>> def choose_class(name):
... if name == 'foo':
... class Foo(object):
... pass
... return Foo # return the class, not an instance
... else:
... class Bar(object):
... pass
... return Bar
...
>>> MyClass = choose_class('foo')
>>> print MyClass # the function returns a class, not an instance
<class '__main__.Foo'>
>>> print MyClass() # you can create an object from this class
<__main__.Foo object at 0x89c6d4c>

But it’s not so dynamic, since you still have to write the whole class yourself.

Since classes are objects, they must be generated by something.

When you use the class keyword, Python creates this object automatically. But as with most things in Python, it gives you a way to do it manually.

Remember the function type? The good old function that lets you know what type an object is:

1
2
3
4
5
6
7
8
>>> print type(1)
<type 'int'>
>>> print type("1")
<type 'str'>
>>> print type(ObjectCreator)
<type 'type'>
>>> print type(ObjectCreator())
<class '__main__.ObjectCreator'>

Well, type has a completely different ability, it can also create classes on the fly. type can take the description of a class as parameters, and return a class.

(I know, it’s silly that the same function can have two completely different uses according to the parameters you pass to it. It’s an issue due to backwards compatibility in Python)

type works this way:

type(name of the class,
tuple of the parent class (for inheritance, can be empty),
dictionary containing attributes names and values)
e.g.:

1
2
>>> class MyShinyClass(object):
... pass

can be created manually this way:

1
2
3
4
5
>>> MyShinyClass = type('MyShinyClass', (), {}) # returns a class object
>>> print MyShinyClass
<class '__main__.MyShinyClass'>
>>> print MyShinyClass() # create an instance with the class
<__main__.MyShinyClass object at 0x8997cec>

You’ll notice that we use “MyShinyClass” as the name of the class and as the variable to hold the class reference. They can be different, but there is no reason to complicate things.

type accepts a dictionary to define the attributes of the class. So:

1
2
>>> class Foo(object):
... bar = True

Can be translated to:

1
>>> Foo = type('Foo', (), {'bar':True})

And used as a normal class:

1
2
3
4
5
6
7
8
9
>>> print Foo
<class '__main__.Foo'>
>>> print Foo.bar
True
>>> f = Foo()
>>> print f
<__main__.Foo object at 0x8a9b84c>
>>> print f.bar
True

And of course, you can inherit from it, so:

1
2
>>>   class FooChild(Foo):
... pass

would be:

1
2
3
4
5
>>> FooChild = type('FooChild', (Foo,), {})
>>> print FooChild
<class '__main__.FooChild'>
>>> print FooChild.bar # bar is inherited from Foo
True

Eventually you’ll want to add methods to your class. Just define a function with the proper signature and assign it as an attribute.

1
2
3
4
5
6
7
8
9
10
11
>>> def echo_bar(self):
... print self.bar
...
>>> FooChild = type('FooChild', (Foo,), {'echo_bar': echo_bar})
>>> hasattr(Foo, 'echo_bar')
False
>>> hasattr(FooChild, 'echo_bar')
True
>>> my_foo = FooChild()
>>> my_foo.echo_bar()
True

You see where we are going: in Python, classes are objects, and you can create a class on the fly, dynamically.

This is what Python does when you use the keyword class, and it does so by using a metaclass.

What are metaclasses (finally)

Metaclasses are the ‘stuff’ that creates classes.

You define classes in order to create objects, right?

But we learned that Python classes are objects.

Well, metaclasses are what create these objects. They are the classes’ classes, you can picture them this way:

1
2
MyClass = MetaClass()
MyObject = MyClass()

You’ve seen that type lets you do something like this:

1
MyClass = type('MyClass', (), {})

It’s because the function type is in fact a metaclass. type is the metaclass Python uses to create all classes behind the scenes.

Now you wonder why the heck is it written in lowercase, and not Type?

Well, I guess it’s a matter of consistency with str, the class that creates strings objects, and int the class that creates integer objects. type is just the class that creates class objects.

You see that by checking the class attribute.

Everything, and I mean everything, is an object in Python. That includes ints, strings, functions and classes. All of them are objects. And all of them have been created from a class:

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> age = 35
>>> age.__class__
<type 'int'>
>>> name = 'bob'
>>> name.__class__
<type 'str'>
>>> def foo(): pass
>>> foo.__class__
<type 'function'>
>>> class Bar(object): pass
>>> b = Bar()
>>> b.__class__
<class '__main__.Bar'>

Now, what is the class of any class ?

1
2
3
4
5
6
7
8
>>> age.__class__.__class__
<type 'type'>
>>> name.__class__.__class__
<type 'type'>
>>> foo.__class__.__class__
<type 'type'>
>>> b.__class__.__class__
<type 'type'>

So, a metaclass is just the stuff that creates class objects.

You can call it a ‘class factory’ if you wish.

type is the built-in metaclass Python uses, but of course, you can create your own metaclass.

The metaclass attribute

You can add a metaclass attribute when you write a class:

1
2
3
class Foo(object):
__metaclass__ = something...
[...]

If you do so, Python will use the metaclass to create the class Foo.

Careful, it’s tricky.

You write class Foo(object) first, but the class object Foo is not created in memory yet.

Python will look for metaclass in the class definition. If it finds it, it will use it to create the object class Foo. If it doesn’t, it will use type to create the class.

Read that several times.

When you do:

1
2
class Foo(Bar):
pass

Python does the following:

Is there a metaclass attribute in Foo?

If yes, create in memory a class object (I said a class object, stay with me here), with the name Foo by using what is in metaclass.

If Python can’t find metaclass, it will look for a metaclass in Bar (the parent class), and try to do the same.

If Python can’t find metaclass in any parent, it will look for a metaclass at the MODULE level, and try to do the same.

Then if it can’t find any metaclass at all, it will use type to create the class object.

Now the big question is, what can you put in metaclass ?

The answer is: something that can create a class.

And what can create a class? type, or anything that subclasses or uses it.

Custom metaclasses

The main purpose of a metaclass is to change the class automatically, when it’s created.

You usually do this for APIs, where you want to create classes matching the current context.

Imagine a stupid example, where you decide that all classes in your module should have their attributes written in uppercase. There are several ways to do this, but one way is to set metaclass at the module level.

This way, all classes of this module will be created using this metaclass, and we just have to tell the metaclass to turn all attributes to uppercase.

Luckily, metaclass can actually be any callable, it doesn’t need to be a formal class (I know, something with ‘class’ in its name doesn’t need to be a class, go figure… but it’s helpful).

So we will start with a simple example, by using a function.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# the metaclass will automatically get passed the same argument
# that you usually pass to `type`
def upper_attr(future_class_name, future_class_parents, future_class_attr):
"""
Return a class object, with the list of its attribute turned
into uppercase.
"""

# pick up any attribute that doesn't start with '__' and uppercase it
uppercase_attr = {}
for name, val in future_class_attr.items():
if not name.startswith('__'):
uppercase_attr[name.upper()] = val
else:
uppercase_attr[name] = val

# let `type` do the class creation
return type(future_class_name, future_class_parents, uppercase_attr)

__metaclass__ = upper_attr # this will affect all classes in the module

class Foo(): # global __metaclass__ won't work with "object" though
# but we can define __metaclass__ here instead to affect only this class
# and this will work with "object" children
bar = 'bip'

print hasattr(Foo, 'bar')
# Out: False
print hasattr(Foo, 'BAR')
# Out: True

f = Foo()
print f.BAR
# Out: 'bip'

Now, let’s do exactly the same, but using a real class for a metaclass:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# remember that `type` is actually a class like `str` and `int`
# so you can inherit from it
class UpperAttrMetaclass(type):
# __new__ is the method called before __init__
# it's the method that creates the object and returns it
# while __init__ just initializes the object passed as parameter
# you rarely use __new__, except when you want to control how the object
# is created.
# here the created object is the class, and we want to customize it
# so we override __new__
# you can do some stuff in __init__ too if you wish
# some advanced use involves overriding __call__ as well, but we won't
# see this
def __new__(upperattr_metaclass, future_class_name,
future_class_parents, future_class_attr):

uppercase_attr = {}
for name, val in future_class_attr.items():
if not name.startswith('__'):
uppercase_attr[name.upper()] = val
else:
uppercase_attr[name] = val

return type(future_class_name, future_class_parents, uppercase_attr)

But this is not really OOP. We call type directly and we don’t override call the parent new. Let’s do it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class UpperAttrMetaclass(type):

def __new__(upperattr_metaclass, future_class_name,
future_class_parents, future_class_attr):

uppercase_attr = {}
for name, val in future_class_attr.items():
if not name.startswith('__'):
uppercase_attr[name.upper()] = val
else:
uppercase_attr[name] = val

# reuse the type.__new__ method
# this is basic OOP, nothing magic in there
return type.__new__(upperattr_metaclass, future_class_name,
future_class_parents, uppercase_attr)

You may have noticed the extra argument upperattr_metaclass. There is nothing special about it: a method always receives the current instance as first parameter. Just like you have self for ordinary methods.

Of course, the names I used here are long for the sake of clarity, but like for self, all the arguments have conventional names. So a real production metaclass would look like this:

1
2
3
4
5
6
7
8
9
10
11
12
class UpperAttrMetaclass(type):

def __new__(cls, clsname, bases, dct):

uppercase_attr = {}
for name, val in dct.items():
if not name.startswith('__'):
uppercase_attr[name.upper()] = val
else:
uppercase_attr[name] = val

return type.__new__(cls, clsname, bases, uppercase_attr)

We can make it even cleaner by using super, which will ease inheritance (because yes, you can have metaclasses, inheriting from metaclasses, inheriting from type):

1
2
3
4
5
6
7
8
9
10
11
12
class UpperAttrMetaclass(type):

def __new__(cls, clsname, bases, dct):

uppercase_attr = {}
for name, val in dct.items():
if not name.startswith('__'):
uppercase_attr[name.upper()] = val
else:
uppercase_attr[name] = val

return super(UpperAttrMetaclass, cls).__new__(cls, clsname, bases, uppercase_attr)

That’s it. There is really nothing more about metaclasses.

The reason behind the complexity of the code using metaclasses is not because of metaclasses, it’s because you usually use metaclasses to do twisted stuff relying on introspection, manipulating inheritance, vars such as dict, etc.

Indeed, metaclasses are especially useful to do black magic, and therefore complicated stuff. But by themselves, they are simple:

intercept a class creation
modify the class
return the modified class

Why would you use metaclasses classes instead of functions?

Since metaclass can accept any callable, why would you use a class since it’s obviously more complicated?

There are several reasons to do so:

The intention is clear. When you read UpperAttrMetaclass(type), you know what’s going to follow
You can use OOP. Metaclass can inherit from metaclass, override parent methods. Metaclasses can even use metaclasses.
You can structure your code better. You never use metaclasses for something as trivial as the above example. It’s usually for something complicated. Having the ability to make several methods and group them in one class is very useful to make the code easier to read.
You can hook on new, init and call. Which will allow you to do different stuff. Even if usually you can do it all in new, some people are just more comfortable usinginit.
These are called metaclasses, damn it! It must mean something!

Why the hell would you use metaclasses?

Now the big question. Why would you use some obscure error prone feature?

Well, usually you don’t:

Metaclasses are deeper magic than 99% of users should ever worry about. If you wonder whether you need them, you don’t (the people who actually need them know with certainty that they need them, and don’t need an explanation about why).

Python Guru Tim Peters

The main use case for a metaclass is creating an API. A typical example of this is the Django ORM.

It allows you to define something like this:

1
2
3
class Person(models.Model):
name = models.CharField(max_length=30)
age = models.IntegerField()

But if you do this:

1
2
guy = Person(name='bob', age='35')
print guy.age

It won’t return an IntegerField object. It will return an int, and can even take it directly from the database.

This is possible because models.Model defines metaclass and it uses some magic that will turn the Person you just defined with simple statements into a complex hook to a database field.

Django makes something complex look simple by exposing a simple API and using metaclasses, recreating code from this API to do the real job behind the scenes.

The last word

First, you know that classes are objects that can create instances.

Well in fact, classes are themselves instances. Of metaclasses.

1
2
3
4
 >>> class Foo(object): pass
>>> id(Foo)
142630324
Everything is an object in Python, and they are all either instances of classes or instances of metaclasses.

Except for type.

type is actually its own metaclass. This is not something you could reproduce in pure Python, and is done by cheating a little bit at the implementation level.

Secondly, metaclasses are complicated. You may not want to use them for very simple class alterations. You can change classes by using two different techniques:

  • monkey patching
  • class decorators
    99% of the time you need class alteration, you are better off using these.

But 99% of the time, you don’t need class alteration at all :-)

靳海涛:一级市场估值的拐点即将到来,建议行业集体放缓投资

2018 年 7 月 11-12 日,清科创业、投资界联合主办的第十二届中国基金合伙人峰会于上海外滩茂悦大酒店隆重举行,集结中国顶尖的

  LP 与 GP 同赴盛宴,前瞻中国股权投资市场发展大势。

  在第一场主题演讲中,前海股权投资基金(有限合伙)首席执行合伙人、前海方舟资产管理有限公司董事长靳海涛深刻地指出了当前

  VC/PE 行业亟待解决的“五个关键问题”,涉及到“募资难”、一级市场投资估值攀升过快,以及创投行业反应强烈的公平税制等问题。

  以下为演讲内容精华,经投资界( ID

  : pedaily2012

  )整理 :

  各位同仁,各位来宾早上好。非常高兴清科提供这个机会,和大家交流行业的问题。首先,分享我对当前行业状况的总体判断,我认为,当前

  VC/PE 行业进入了一个相对比较困难的时期,我们正处于较大幅度调整的前夜。

  其实很多问题是在你比较顺利的时候无法解决的,但是碰到困难以后,这些问题就容易被解决了,所以这也是解决问题的一个好时机。我们应该通过上下的协同,通过群策群力来解决发展中的问题,问题解决以后,这个行业就变好了。

  今天我主要谈五个方面的问题。第一是“募资难”的问题;第二是投资估值过高的问题;第三是投资过程中需要严格执行保证条款的问题;第四是外资准入监管过于“一刀切”的问题;第五是现行税收制度对行业特性考虑不足的问题。这些问题大家都很熟悉,我想讲一讲我的观点和看法。

  “募资难”的原因

  第一个问题,我们需要解决越来越难的募资问题。数据显示,今年第一季度募资额较去年下降,下降幅度很大,而且仍会继续下降,为什么呢?原因有四个:

  第一个原因是行业整体投资回报有所下降。 这个行业的收益跟我开始在 90 年代末期 2000 年初期做创投的时候不一样,那时候生意特好,懂创投的人特别少,我们喝了“头啖汤”。伴随着项目的退出,相当一部分投资者获得了大利,但是那个时代已经过去了。现在这样的情况也可能偶尔会发生,但难度增大了很多概率也下降了很多。

  第二个原因是

  LP

  结构不太合理 。在美国,养老金、保险资金,主权财富基金、家族财富基金等成熟的长线机构投资者占比超过 40% ,而在中国最多占到 2% 到 3% 。在中国,我们主流的出资人是谁?民营企业、国有企业,相对富裕的个人,再加上各级政府引导基金。但这两种结构背后所代表的资金属性和资金实力完全不同,成熟度不同,对收益性、安全性和流动性的要求都完全不一样。比如像政府引导基金,很多对行业和地域都有限制性要求。

  第三个原因是资管新规的影响 。资管新规对行业影响的是什么?我想了想有五条:

  1、 资管新规前银行理财资金是通过资金池进行错配后投资进入了 PE 基金。资管新规后在不得开展资金池业务和期限匹配原则的约束下,该等模式受到重大影响,未来银行理财资金投资私募基金的规模将会严重萎缩。

  2、 资管新规前银行理财资金通过向投资人结构化配资方式间接成为了私募股权投资基金的重要资金来源之一,新规后该等模式很难延续,该等资本供给量将相应大幅减少。

  3 、随着金融去杠杆的深入推进和地方政府债务的规范清理,政府引导基金的规模正回归常态,未来私募基金从有银行配资的政府引导基金募资存在较大不确定性。

  4 、资管新规对股票定增类结构配资和未上市项目并购退出通道也造成了重大影响。其实我们很多并购的项目,在并购过程中也会采取类似于欧美的杠杆式收购,这部分资金很多来自银行的配资,但后续由于杠杆比例约束等原因将受到重大影响。

  5、 资管新规对个人

  LP 门槛明显提高了,这将直接减少个人合格投资者数量及投资规模。

  而“募资难”的第四个原因,是本来应成为

  VC/PE

  基金主力军的保险资金进度还比较缓慢 。我们都知道创投行业流动性不好,由于受到内部考核机制的影响,前人栽树后人乘凉的事情大家都不愿意干,一般的创投基金难以满足保险资金对当期收益考核的要求。我们必须针对这些问题找到解决办法,届时保险资金的大门就可以敞开了。

  破解“募资难”:建议从母基金下手

  “募资难”已是众所周知的事情,我们应该如何解决?这里,我提几条建议:

  第一,建议政策制定部门高度重视当前面临的问题,

  “募资难”只是行业的表象,对创新型经济实体的冲击才是问题的关键。如果情况持续下去,创投行业规模的总体受限将会很大程度制约实体经济融资需求,影响实体经济发展。政策制定部门有必要高度重视当前行业面临的困难,为行业募资创造良好的环境和条件,而不是处处设卡。

  第二,

  建议资管新规配套实施细则审慎出台,出台前应高度重视创投行业的意见 。创投这个行业太重要了,你不尊重它的发展将会带来很多负面影响。遗憾的是,很多人对创投的商业本质不太熟悉,把它的风险看得过重。。

  第三,

  建议大力支持市场化母基金的设立,并出台有针对性的扶持政策,积极鼓励和支持保险资金、养老金等投资市场化母基金 。培养合格投资人队伍应该从哪下手呢?我觉得应该从风险最低的母基金下手。如果说

  VC/PE

  这些直投基金属于低风险中高收益,我给母基金的一个商业本质的定位是, 母基金具有两层风险分散属性,属于极低风险中高回报的投资品种,从资产配置理念和风险收益特征都与保险资金、社保资金以及政府引导基金高度匹配。

  欧美的数据显示,母基金的收益跑赢大多数直投基金,至今未出现过亏损案例。刚才我提到保险资金关于内部考核和流动性的问题怎么解决,这里有一个建议:

  我在行业带头,前海母基金每年都做估值报告,这个估值报告标准写进法律合约,聘请专业的会计师事务所来做。如果保险公司投你了,对方就可以依据估值报告对内部进行考核,那么这个流动性的问题就可以解决掉。目前中国母基金刚刚起步,虽然看起来发展很快,但是还是挺艰难,母基金的募资也是非常难。但我还是提倡大力发展母基金,如果中国母基金能像美国那样占到 40% 甚至 50% ,那么意味着中国合格的投资人建立起来了,我们不用开会再讲募资难的问题了。同时,有大量的母基金存在,也可以减少监管的风险和难度。

  一级市场估值拐点即将到来!建议:集体放缓投资

  第二个关键问题,需要遏制一级市场投资估值攀升过快的现象。

  一级市场投资价格的攀升由来已久, 2013 年以后尤为突出。清科的数据显示, 2014 年到 2017 年项目平均估值增长了 3.65 倍,其中

  VC/PE 最具代表的成长性的平均估值,从 2014 年的 5.3 亿,增长到 2017 年的 16.3 亿,增长了 3.2 倍,可见我们的估值是“脱实向虚”。

  背后原因是什么呢?我总结了一下,在看待创新型企业时,年轻人容易乐观,所以对项目的估值风险估计不足,容易开高价或者接受高价,这是要跌跟头的。所以,一个好的 Gp 结构中,应当有老中青不同年龄段的人相结合,彼此碰撞,彼此切磋,兼听则明。

  一级市场估值升了,二级市场估值又是什么情况?大家听听数据就很可怕,现在的股市已经低于 2016 年底熔断时市盈率、市净率水平。过去 A 股都是挣钱的,现在一二级市场价格倒挂的现象已经出来了,至少是在发行价的倒挂。很多一批有名的企业都倒挂了,以前这个现象没有。

  美股与港股近期也不好,小米作为指标性的公司,按最低估值定的价,首日破发,好在第二天又上去了,所以雷军说像做梦一样,如果第二天再撑不住就真惨了。不光他惨,后面要上的企业也好不到哪去。

  一级市场估值高能持续吗?大家知道,

  VC/PE 的价值,最终需要在二级市场体现。随着今年资金不断的紧缩,一级市场估值的拐点到来不可避免。如果还有人挺着,那也是时间的问题。对于问题的形成,肯定不是一朝一夕的,是一个积累的过程,如果 GP 现在在估值问题上还缺乏清楚的认识,战略理念以及果断应对,不能及时避免风险,在不远的将来必然造成极大的困难。

  面临这样的局面应该怎么办?也许这个话说得不对,但是一定要说,要对行业负责,我的建议是:

  第一,集体放缓投资;第二,慎碰高估值项目。如果我们多数人做到了,一级市场的估值就会很快下来,那我们也就安全了,这是我的建议。

  坚守保障条款应该是

  VC/PE 长期坚持的原则

  第三个问题,是需要解决 GP 对投资保障条款不断放松的现状。

  保障条款,这原来是作为

  VC/PE 的一个标配。投资机构和企业之间信息不对称,真正的情况即便你作为董事也未必知道。我们过去的经验和教训是大部分投资标的实现不了它的预测,而我们往往是根据预测溢价估值的,所以我们坚持必须要有保障条款,过去保障条款是必须的,但现在呢?根据我们了解的情况,现在的投资标的含有保障条款的有一半就不错了。

  企业当然不愿意签订保障条款,但是我认为 GP 应该坚持。

  现在有的投资人开始放弃了,别人没办法只能跟着放弃了,这相当于放弃了对风险的事前防范,不坚持的结果就是投资风险加大了,问题的项目就会越来越多。不坚持,就会对不起出资的

  LP

  ,这对我们行业来说非常不利 。

  因此我认为,保障条款应该是

  VC/PE

  长期坚持的原则。从母基金的角度看,判断优秀的 GP ,不但要看其能否捕捉到成功项目,也要看其对不可避免要出现问题的项目事先是如何安排风险解决方案的。

  VC/PE 无奈:外资准入监管“一刀切”

  第四个问题,是关于外资准入监管过于“一刀切”的问题。国家对有些行业进行外资限制的政策是对的,初衷是好的,但在实际监管过程中,由于采用过于“一刀切”的监管方式,导致外资准入政策有些走了形、偏了道,这将对创投行业的长期健康发展带来一定的消极影响。

  我们这个行业碰到的问题是什么呢?但凡有一点外资成分的企业,均无法突破限制,最典型的是涉及到互联网和军工行业。正如之前提到,保险资金是未来创投行业的主力军,但是几乎所有中国保险公司都有外资,作为

  VC/PE ,如果你要保险公司的钱,那就意味着很多行业你都投不了。

  “一刀切”背后充斥着许多不合理:

  第一, 从基金产品和投资人的关系来说,投资人投资基金相当于是购买一个产品,他并不对你投资基金所投资的领域产生控制和影响。

  第二, 从所有权和管理权的角度上, GP 管

  LP 的钱,

  LP 不管 GP 的事,连投资的事都不管,投资企业背后的事能管吗?根本不涉及,你有任何机密实际上都不会涉及到。

  第三,中国还在继续开放,金融机构中银行、保险都有外资,这是国家鼓励的,而且必须要开放,不开放 WTO 不干,欧美也不干。所以,穿透来看完全规避外资很难。

  第四,对保险公司的钱,是两部分,一部分是自有资金,它可能会有外资股东的钱,另一部分是保费,但用于投资的钱主要是保费,是中国老百姓(603883,股吧)的钱。但是投资主体又是保险资产的管理公司,保险资产的管理公司是保险公司的全资或者是控股的子公司,一穿透审查有外资,也在监管准入之外了,这明显是不合理的。

  因此,我建议,第一,从国家顶层设计的角度出发,由各部门联合出台进一步完善外资准入的相关政策,关键是对我们这种特殊性的私募基金进行分类管理,本着支持创投和实事求是的原则来制定政策。

  第二, 我觉得对以下几类有限合伙人的投资豁免外资,这都可能是将来很重要的

  LP ,如境内央企集团在境外设置全资的公司,或者境外的央企在境内设置全资的公司;在红筹上市或者发行 H 股的企业;基于国家开放经营战略引进的外国投资者的银行和保险;保险公司通过保费进行投资的股权主体等等。

  第三, 按照实质重于形式的原则,即便有外资,应明确外资的计算规则,穿透起来外资成分限制在一定的比例范围内,不能按照过去一穿透审查发现外资成分就全都切了。

  税制争议:创投行业应该交多少税?

  最后,需要结合私募的特点,解决行业反应强烈的公平税制。

  首先我讲两点认识,第一个,没有创投就没有新兴产业的迅猛发展和传统产业的转型升级,就没有中国经济的未来,所有人都应该清楚。第二点,创投在某些人眼里是自身赚大钱的,给国家贡献过税收不够,这是错误看法,但是很多人是这么想的。

  创投对税收的贡献大不大?其实还是挺大的,我拿到一组数据,深圳 2017 年创投行业对税收的增长是 31% 。我觉得其他行业很难达到这个数。记得大概十年前左右,深圳福田区纳税的前三名有一个股权投资基金,挣了大钱,也交了大税,所以它是纳税大户。

  第二点,其实很多人往往忽略了,创投机构所投企业的纳税。创投机构投了企业,企业规范了,成长了,上市了,形成了持续增长的税源。我建议对创投投资企业投资前后的税收状况做个比较统计,数字一定惊人的、震撼的。这也是创投对国家税收的重大贡献,不可忽略。

  创投行业和财税部门争议在哪?

  三个方面,

  第一是所得税。 VC 认为,创新型企业的资金来源主要是靠创投机构,这个创新型企业、高科技企业,按国家规定享受 15% 的所得税,而创投机构自身的税率却是 25% 。所以, VC 认为应该把税率降下来。

  第二是关于增值税 。 VC 认为创投赚的是资本进出的差价,在经营过程中,不产生营业收入、不产生工商企业通常存在采购和卖出之间的差价,没有增值税,不退出就没有增值,所以它应该交的是资本利得税,而不应该交增值税。现在很多创投为了流动性问题也做定增,但同样干定增的公募基金不用交增值税也不交所得税,而我们创投机构既要交增值税也交所得税,严重不公平。

  第三个是 作为工商企业盈亏相抵完交税,这是一个常识,所以创投机构认为收回本金以后再交税,而不应该按单纳税,现在退出一单,就按那一单纳税,大家意见很大。

  面对这样的局面,应该怎么办呢?我建议,在权威部门的组织下,我们这个行业的协会,包括官方和民间组成的协会,与财税部门进行郑重其事、深入具体的对话。这个对话有一个前提,那就是大家先统一思想,

  把私募基金看成是属于投资人开展对外投资所依赖的投资载体和投资管道,并非受益主体。第二,把创投机构看成一个特殊的工商企业,并非一般意义的工商企业。

  在这个前提下,我的看法,第一所得税考虑到创投的多重目的,而且又是新生事物,它很幼小,要扶持,

  应该适当降低所得税率;针对增值税,我仔细考虑了这个问题,建议

  免征增值税。第三,我认为通过这样的对话,合伙企业

  应该至少改变现在按单纳税的现状,即投资人已经收回本金了,再开始纳税,虽然还有点不公正,但是要考虑双方的承受能力。

  这就是我今天想跟大家分享的五个问题,很关键,也很重要,可能有些地方讲得比较大胆,有些人听了也许不开心。但是我想我还是应该对行业呐喊,说出大家想说的话,提出建议,上下协同群策群力去解决这些问题,最终的目的是为了促进这个行业的发展。须知道,创投行业的发展对中国至关重要。

缠中说禅公司分析

  • 靠研究公司基本面买股票,那种积累速度太慢,只适合大资金。其实,一切关于基本面的研究,最终都归于行业或总体经济的发展。

  • 本ID 买股票从来都不是乱买的,8 元让各位买 000777 时,各位当然不可能知道该股基本面将会怎样,但本ID 就知道,这就是对基本面的把控能力,光技术面,只是一方面。
    例如,600649,大概到现在,没人知道这股票里卖的什么药,但如果你去研究一下该股是现在管理层的资本运用的辉煌历史,还有上海市对国企重组的计划,那么,当然就明白,本ID当时让各位在6元买入,不是瞎说的。

  • 本 ID 从来不乱买股票,如果乱买,那么整个股市中最和 VC 与 PE 相关的两只股票 600635、000938,为什么都在本ID的组合里?本 ID那 10几只股票中,业绩暴增百分之几百、甚至一千的,难道还少?当然,这只是冰山一角,就像000938,谁告诉你就是PE、VC 这点事情?

  • 600635 是本 ID 那十几只股里的 VC 股,说的时候,当然也是本 ID 大举介入的时候,是 5 元多点。为什么本 ID 要当时要大力买入并让这里的人都去买?因为他是中国最大的 VC 企业 20%的股东。
    知道全流通最大的投资机会是什么?就是 VC,更准确说,是私人股权投资这一块。
    知道 635 的那 VC 企业对潍柴动力2000 万的投资,几年时间,现在已经快 100 倍的收益了吗?
    知道本 ID 为什么要为潍柴动力写了一首诗?看看当时该股多少钱,现在多少,有受大盘影响吗?知道潍柴动力占有中国 5000 亿重汽市场的多少分额吗?当然,本 ID 不是让你现在去买,当时写诗的时候,潍柴动力 60 不到,不过,就算现在去买,站在中线的角度,绝对一点问题都没有,但就怕你没有这个耐心。
    就像本ID4 月前后让各位注意002100 后的 6000万总盘,2000 万以下流通的中小板,看看后来都走成什么?如果两年后再看看,你会更 H,本ID 就奇怪了,怎么总是有人说本ID 的理论是短线的,有些股票,本ID 绝对可以拿10 年以上,关键是他值得本ID拿吗?
    本 ID 可以419,当然也可以 4N9,关键是你的N 是多少。谁告诉你本ID 只看技术面买股票的?只看技术面买股票就等于只看上半身找面首一样,只有上半身没有下半身的能是好面首吗?

  • 个股方面,本ID的股票都是中长线介入的,都有足够的基本面和战略面的理由才介入的。
    当然,对于本 ID 这种资金来说,有时候介入的股票,不一定是基本面很明确的,但本 ID 可能是先介入,再改造其基本面。
    例如,最近在年线附近介入的一只股票,现在才 7、8 元,但他将生产的产品,比三一重工的最大利润的拳头产品成本低30%以上,马上就开始生产,三一这次可麻烦大了。
    本来这样的股票是很好的,但该股票在基本面上有些很不明朗的因数,所以本来这股票,应该现在就应该在30元以上位置的,就因为这基本面上的某个因数,所以不能太用力玩弄这面首。
    而这个因数能否解决,本ID也没把握,也只能看一步走一步,所以这种股票,也就只能让本ID自己独自去偷欢了。

  • 个股方面,说句梦话,千万别信:可以开始关注两只股票600319、000822,这都是基本面上有可能出现重大变化的。

  • 2007-01-10 16:27:06 缠姑娘好!到穷山僻壤出差几天没能上网分享你的智慧了,今天倍感亲切。
    我今天发现中信海直000099在周线上有第二类买点,所以在4.39进入,到今天收盘已有所收获。不知判断对否?
    缠中说禅 2007-01-10 16:32:08
    买的高了点,4元随便买。任何买点,都应该在回跌的时候介入,而不是追上去。只是回跌的级别不同而已。

  • 各位没必要知道那么多股票,本ID的第二只股票是5个0中间一数字的能源股,题材是整体上市,都涨那么多,本ID也不好让各位买了。前几天是一个标准的第三类买点。当然,本ID资金量大,不可能在一个精确的点上买。注:000600
    第三个是前面三个0,后面三个相同的另外数字的江浙的股。注:000777
    第四和第三后5个数字都相同,就前面一个不同。注:600077
    第5个和第三个最后一个数字不同的300样本股。注:000778
    算了 ,最快一个已经第一时间告诉了,都拿不住,这四个可没第一个牛,知道了也没意思。
    注意,本ID现在可不当什么庄家,只是喜欢抽庄家血。
    还有,这笔后来的钱只占本ID的一小部分,本ID的大部队可不在这里,大部队早就进去了,现在都没影子地高了,更没必要知道了。

  • 数女,任何看待A股与H股的严重分化呢?
    缠中说禅 2007-01-10 20:42:54
    香港是中国的一部分而不是相反。

对话华生——6000点论与制度改革带来的新牛市_2012-03-17

沈竹:欢迎进入今天的《名嘴侃财经》,我们说从上周开始,我们推出了聚焦了A股制度红利的大讨论,今天是周五,是压轴好戏,我们要做一个总结陈词,首先介绍一下两位重量级的嘉宾燕京华侨大学的校长、著名经济学家华生教授,另外一位是我们的老朋友东兴证券副总经理银国宏先生。

像往常一样,昨天晚上财经频道的3·15晚会再次引发了全社会的关注打假维权,保护消费者利益,是3·15的宗旨,巧的是也在3·15这一天,证监会的投资者保护局,针对市场一系列热点的问题,做了一个全面的回应,可以说保护投资者的利益也成为今年3·15一个主题,我们首先回顾一下证监会投资者保护局昨天的谈话说到了一个什么样的声音。

小片:积极协调降低公司与分红相关的操作成本,提高对股东的回报,证监会投资者保护局的回应,仅仅围绕投资者权益展开,并对相关的制度改革安排做出详细说明。在分红方面,负责人再次强调将督促上市公司充分披露不分红的原因,对不按承诺比例分红,长期不分红的公司加强监管约束,对于改革焦点,新股发审制度,负责人表示,注册制、审核制实质性差别不大,改革主要以信息披露为中心,强化资本约束、市场约束和诚信约束。谈到退市问题时,负责人谈到目前正集中力量研究改进和完善主板退市制度,一是完善上市公司退市标准,二是进行制度改革,避免停而不退,三是要健全责任追求机制。

沈竹:今天既然华生教授来到我们的现场,我要隆重的介绍一下他,他在2001年、2005年准确的预测了市场的大逆转,今天我们看到了他的一个表态,是A股未来十年可以站上6000点,也是文字上的传达,今天既然华生老师来到了我们的现场,我们就向他求证一下,他的原话到底是怎么说的,6000点的看法,怎么得来?华教授能不能做一个解释。

华升:我确实没有说过未来十年就是到6000点,因为我从来不预测股市的点位。

沈竹:就是媒体误传您的话。

华升:我确实说了今后十年,中国的股市应该有一个比较好的回报,因为我们现在整体的市盈率都比较低,在中国经济高速增长的大的背景下面,未来十年股市有很好的回报应该没有问题的。如果一定要说什么点位的话,可能是6000点,也可能是7000点呢,我觉得都是可能的。

沈竹:你有这么强烈信心的原因是什么?

华生:我觉得最主要还是中国的股市,有中国经济作为一个坚实的基础,过去几年,当时泡沫比较严重,2001年的时候,市盈率过高,我们看到实际上中国的每股盈利从当时增长四倍,从当时60倍的市盈率,现在基本上到了10多倍,如果中国经济还保持这种速度的话,上市公司盈利不用多,每年能够增长百分之十几,今后十年,我们的市场就会上升三倍、四倍的潜力。

沈竹:您同意我们的导播把这个标题打上吗?就是未来十年的中国股市会报会非常好,您有这个信心,这样准确吗?

华生:对,我觉得可以这么说,未来十年中国股市回报是值得期待。

沈竹:银总坐在旁边,我不知道您对华教授的看法自己是什么样的意见?未来的十年如何能够达到这样一个增长?股市的增长是不是跟中国经济的增长是完全契合的?

银国宏:我觉得是,其实未来十年的汇报究竟能达到什么样的水准,实际上是取决于两个因素。第一个因素来讲,中国经济的转型,要能够比较成功的完成,至少进入到一个转型以后,一个增长的正确的轨道上。现在来讲,其实我们还在转型的过程当中,究竟是用三年完成,还是五年完成,我们需要等待,观察一下。第二个是关于制度的约束问题,我们知道中国经济在2002年到2007年的时候,经济的增长速度还是很快的,但是由于股权分置,这样一个非常大的制度约束来讲,在2002-2005年,整个股票市场是没有反映中国经济增长的现实情况的,股票市场回报并不是非常理想,但是一旦股权分置的枷锁被打破或解除以后,市场释放出了惊人的能量,把2002-2005年的没有反映那部分,加上2006、2007年中国经济增长一并反映出来,以至于冲到了6000点,实际上大家将那个就叫泡沫。这个来讲,我觉得当制度跟整个经济的增长形成共振的时候,回报才是最良好的。未来来讲,其实我个人倒觉得,对于整个制度的改善还是比较有信心的,中国股票市场从建立到现在制度是不断完善的,而且现在随着国际化的进程不断加强,实际上制度完善的步伐比以前更快一点,我相信有十年的时间,中国的制度完善会有很大的进步,但是整个经济的转型还要观察一下。

沈竹:华教授,您知道您这6000点论一出来,媒体误读一出来,大家的反应非常的热闹。昨天我在网上看到了一些网友的回应,比如说网友名叫嘀咕的人就说了,你指的6000点是指沪市还是深市,大家很没有信心。还有网友天使下凡就说了,以现在A股的体量,好像有点难吧。还有网友IT民工刺客说道指都到一万三了,A股还到不了6000点,我们相信大家对6000点还是有期待的。大家的心态,您能理解不?

华生:我可以理解,因为过去的十年,应该说投资回报是让人比较失望的,这个时候大家对将来有预期,中国经济又有这么好的背景,未来十年会给一个比较好的回报。

沈竹:你说的回报我们想想看有没有一些前提条件,比如有的人担心,说郭主席这一段时间内,如果很难理顺现在市场一系列制度变革,这么复杂的系统,前面留下了这么多难解决的问题,如果这些不解决的话,我们重圈钱重融资的市场,是不是能改观,是不是有投资价值,我们打一个问号。还有网友说,你先给我们一个小散户一个何时取得公平交易机会的时间表吧,如果没有这个时间表,这6000点的时间表,我们似乎也很难在有生之年看到,您说这个时间表重要吗?制度改革的时间表,您心里有答案吗?

华生:我觉得大家的担心是有道理的,我们是说未来十年是有回报,十年是很长的时间。对于中国证券市场目前来说,这个挑战是非常严峻的,所以我一再强调,目前市场的走势跟我们的制度变革有非常大的关系,中国证券市场就像刚才说到的,过去由于股权分置改革我们迎来了大发展,中国证券市场的潜力真正要释放出来,还需要一次更加深刻的制度变革,这就是发行审批制度的根本改革,如果没有这样一个变革,应该说市场在中短期内还面临着相当多的坎坷和挑战。

沈竹:我们看到美国曾经的制度改革,引发了他们的大牛市,所以我们之所以关注此次的制度红利,也是期待着这样的制度红利能促进我们A股的大牛市。刚才根据华教授和银总的判断,如果制度改革非常的顺利的话,这个大牛市是非常可以期待的。下面我就要问了,华教授曾经写过几篇文章,2001年的时候写过一个漫漫熊市的转折信号,2005年写过市场的转折信号,2007年最后写了一个市场过热信号,现在有没有在写一个关于什么什么样的信号?能告诉我们现在的市场在什么局面里头?

华生:这一次大家可能是要等待市场变革的信号、制度变革的信号,如果基本制度向股权分置制度改革,推出一个根本性变革的制度,能够释放我们资本市场的潜力的话,我们就可以预期,市场会迎来波澜壮阔的发展。

沈竹:波澜壮阔,听着挺让人振奋的,银总同意吗?

银国宏:我觉得是,我觉得目前来讲,制度的因素肯定是非常重要的约束力,但是当前我个人觉得真正影响中国资本市场或者股市市场走势来讲,不是制度因素,其实经济也是非常重要的制约因素,很多人探讨经济软着陆、硬着陆,其实根本的原因还是对未来的转型需要有一个答案,或者更清楚的措施。关于制度层面来讲,现在确实遇到了一些焦点,或者已经到了不改不行的地步,如果不改的话,即使转型成功了,市场也不会给我们提供更好的回报。

沈竹:在两位的言论中,我听到了制度改革的关键性和紧迫性。刚刚“3·15期间证件者投资者保护局给我们一系列的反馈,说我们的主板退市制度,不能够说停而不退,包括我们在红利税上动刀子,能够让大家分红的成本更低,这样一步一步的步骤,按你们的想象是不是在按着你们的理解发展,他们的动作是不是抓住了整个制度建设核心的问题?

华生:说老实话,我觉得还没有。因为现在做的还是基本上的技术的修补,从根本上要改变的是审批制度,整个改革的核心,发行审批的核心是审批制度,证券市场基本是天罗地网的审批制度下面形成的,所有的事情,从融资再融资、发债到重组,包括买方的基金,卖方的券商,甚至保荐人的推荐通报,所有的事情都是经过审批的。我觉得做根本性的制度变革,是要对审批制度做一个根本性的改变,我现在注意到,监管部门有个说法,说注册制和审批制没有什么本质的区别,说实话我是不赞成的,一开始的时候说是不是可以不审批,我觉得那个过分过极了,但是现在说两个制度没有区别,我觉得这个区别太大了。如果我们真想使得证券市场的潜力能够释放出来,提高证券市场的投资回报价值,我觉得就是不能回避发行审批制度根本性的改革。你刚才说的红利税,我想说的是,现在上市公司红利税已经是减半征收,这个地方没有空间,而且我认为进一步降低也是不对的,因为红利税对于我们广大的未上市企业,中小型企业,他们在分红利税的时候是全额征收,上市公司已经是减半征收了,如果再取消,对于其他的企业就不公平,是不是所有的公司的红利税都取消呢?这跟我们税制改革的方向又不一样了,因为我们税制改革的方向就是要大大的降低我们现在间接税的比重,增加直接税,包括红利税这样的税种。证券市场的发展有潜力,不需要靠吃偏饭,靠吃偏饭,实际上并不能够真正发挥资本市场的作用。

沈竹:您曾经在注册制还是审批制上有这样一个言论,对比美国和香港的市场,其实他们也不是注册制,他们审的比我们还要严,您曾经对比过国内外的状况,您认为什么样的审才是对我们市场有力的审。

华生:前一阵子我为什么讲到这个问题呢,因为有很多人讲到注册制就说企业随便,就像到工商登记注册一下就上市,我特别要说清楚,美国也好,香港也好,西方国家不存在自由上市的注册制,都是有审查,都是有聆讯,都是有盘问的。但是从另外一个角度来说,注册制应该说和我们现在中国资本市场这二十年内有本质的区别,如果简单的比方就说注册制是说给了一个明确的标准,给了一个门槛,如果我够了,只有在特殊情况下,你才能拒绝我的上市申请。而审批制是说我的标准也许很低,但是呢,判断掌握在我手上,不管你做得多好,你能不能够上市,取决于我最后同意不同意你,所以审批制和注册制是有本质的区别。

沈竹:我看到银在旁边频频点头,您对华教授的这番自己的思考,和市场上发生的一系列的事情,有没有过对比,有没有过想法?

银国宏:是,其实来讲,现在大家比较集中的焦点,就是关于注册制、审批制的问题,我也比较同意华教授的观点,就是说从审批制到注册制的过度,实际上不可能是一蹴而就的,如果这样一蹴而就的话,可能也会带来一些冲击。我个人觉得整个新股发行,整个改革环节来讲,目前当务之急是解决定价和销售的环节,因为定价和销售的环节,其实使得整个一二级市场利益分配格局是被扭曲的,实际上整个过去大概从2007年以后,从股权分置改革以后,一级市场的利益占了大头,二级市场的利益被一级市场极大的侵蚀,这本身在内部来讲是被侵蚀的。我们放大一点,实际上整个资本市场,或者股票市场的利益,因为你制度上的不稳定,你的一些缺陷,实际上是被其他金融市场也在进行利益的侵蚀,这样的话,整个股票市场,现在整个股票市场现在整个中国的金融产业链,或者整个金融生态环境当中,处于一个非常低端的,是一个高风险低收益的环节,这样就造成了过去几年回报非常不佳的状态,所以我觉得首先要改变的就是调整利益分配的结构,只有把它拧过来以后,整个股票市场才能够唤起投资者的信心。

沈竹:股票投资价值,说得非常好,我们前一阶段听到郭树清主席说我们的蓝筹股出现了罕见的投资价值,但是华生先生自己的判断是蓝筹股还没有任何的投资价值,现在我们大家对蓝筹股的价值出现了针锋相对的两种声音。我要请教华教授了,您认为我们蓝筹股到底有没有投资价值?

华生:我首先纠正一下,我没有说没有任何投资价值,我是说我们的蓝筹股还缺乏投资价值。我理解证监会的领导说,主要是从市盈率的角度看的,确实中国证券市场经过这十年的发展,过去的泡沫基本上挤压掉了,所以现在市盈率水平跟国际上规范的市场、成熟的市场基本上比较靠近。从这个意义说,我们可以说蓝筹股已经开始具备一定的投资价值,但是我觉得应该说这里面还有很大的距离,还不是很具有吸引力,是不是很有吸引力的投资价值,不取决于我们主观的判断,是有客观的标准的。客观的标准是什么呢?比如说一年期的存款利率,一年期的存款利率现在我们知道是3.5%,我们这个市场上,最优秀的股,比如说沪深300,已经是我们最优秀股的代表,他们现在的分红,股息利水平对社会公众股分配的来说不到2%,靠近2%,他还在一年定期存款的60%左右,在这样的水平下,显然像保险基金,以及其他的长线基金就很缺乏吸引力,因为这个钱我拿去储蓄的话,一年还可以分3.5%,我投到你这儿来,一年分红只有接近2%。今年经过证监会做这些工作,我们觉得分红水平会提高,增加吸引力,但是增加到什么程度?我们看到银行最有能力分红的,他说他资本不足,还要降低分红比例,另外对于证券市场来说,重要的不是一年的分红比例,而是说蓝筹股需要,什么叫蓝筹股,是有长期的,稳定的丰厚的补息、派息能力,基于所有考虑,跟国际上比较,所以我们说蓝筹股还缺乏投资价值。蓝筹股的分红派息,能够长期稳定的比一年期存款利息还高,不要我们呼吁,也不要我们劝说,所有这些长线资金自然就会挤到市场上来。

沈竹:所以市场的状况确实真实的反映了到底没有价值的状况,我不知道银总是不是同意这个观点?

银国宏:我觉得这里头有两个问题,我想解释一下。第一个问题从股票市场的判断,判断一个股票有没有价值,蓝筹股作为一个大的板块来讲,说蓝筹股是有价值的,这话大体上不会太错,如果再一个便宜的蓝筹股具有价值,我觉得这句话基本上可以说放在任何时间点上,基本上都是不会错的。但是这里头主要是什么样的股票叫蓝筹股,刚才华教授提出了一个分红率的问题。其实首先来讲蓝筹股除了规模在行业中的地位,整个行业的属性和商业模式要吻合一个经济发展的特殊的时代和背景,其实美国股票市场发展这么多年,不同阶段的蓝筹股的构成还是不一样的。这一点是要有变化的,比如说当前阶段,你说价格很便宜的钢铁,我们未见得它是一个比较好的蓝筹股。

第二个想澄清的问题就是关于分红的看法,其实我跟市场大多数人的看法不是特别一样,我不是特别的强调股票或者蓝筹股也好,要给予多高的分红率,如果蓝筹股也好,一般的股票也好,如果我们把价值分开来看,就像可转债的价格一样,首先有票面的利率,加上未来的期权,这是它的一个价值,我们回过头来看蓝筹股定价来讲,也是这样,首先有一个分红率,分红率就像一个可转债的票面利率一样,其次有一个期权,就是基本利得的波动,这两个部分构成在股票上真正投资的价值,从这个角度上来讲,蓝筹股的分红率,或者说可转债债券的票面利率,一定是低于没有期权的债券的票面利率的,两只股的分红率,我个人不一定超过一年的期的存款,但是要有一个比较稳定的业绩的增长,这个是对蓝筹股更为重要的衡量的标准。从这个角度来讲,我觉得蓝筹股强调分红是没有错的,这种分红只是为长线资金提供了一个投资价值的底线,如果有了这个分红,不管你是比一年的存款利率低于0.5个点,还是0.25个点,实际上可以倒算出一个底线价值,当有了底线价值以后,就跟没有分红的蓝筹股相比是什么概念呢?如果没有分红的蓝筹股,就不知道会跌到什么位置会有底线价值,所以这个分红应该体现一个底线价值,同时加上期权,构成一个完整的蓝筹股的定价。

沈竹:两个人对蓝筹股表达了自己的看法,华教授著名的双轨制曾经让我们印象深刻,比如说像我们现在提到的股市的市场建设,进入了深水区,我们经常说到,公司治理是非常重要的,这直接决定了了蓝筹股到底有没有投资价值,这就说到了国企和民企的双重标准的问题,我们看到专家学者说国资委一股独大,经常在法律面前,在经济判断面前是网开一面的,这样我们在判断公司的价值时候,是非常模糊的,所谓公司的边界,我下面就想追问了,这是不是蓝筹股投资价格的深水区。

华生:我先补充一句刚才银总说的我可能有些不赞成的地方,对于个别企业来说,是不是蓝筹并不取决于分红水平,我们知道世界上很优秀的企业,比如说像苹果,多年来不分红,并不影响他作为蓝筹的优势企业。但是作为整体市场来看,因为它的行业都在变化,比如我们300指数当中的企业、行业都在不断的调整,看整个市场的时候,股息率的水平,能不能够高过,或者一年定期储蓄应该是有稳定的关系,我们从国际上看,普遍是高于一年定期储蓄的,而我们显著的低于一年定期储蓄的。

沈竹:您是从概率的角度来分析。

华生:我们判断一个市场的时候,只能从整体上来看,整体上把很多个案都给你忽略了,看总体上说这个市场是有投资价值,还比较缺乏吸引力。所以这个意义上来,强化分红的概念是对的,当然不能去强制。

沈竹:另外刚才我的问题是不是能够有一个补充?

华生:我觉得实际上我不是太赞成把国企和民企分裂开来说,重要的问题是我们证券市场,在证券市场发展过程当中,有的阶段强调要为国企服务,为国企脱困,为他们服务。有的阶段强调为民企的中小企业创新型企业服务,最近甚至提出来要为小微企业服务,甚至为某一个产业,跟宏观政策或者政府要求的产业服务,我个人认为,如果我们不能摆脱这样一个怪圈的话,中国证券市场的发展会受到严重的制约。证券市场的发展,扶持企业的标准,应该不受所有制,不受产业,也不受政府临时政策需要的支配,这样才有真正的生命力。

沈竹:具体到双重标准问题也不是特别严重的问题?

华生:我们的问题是,在一个阶段说的是对的,比如90年代后期,本世纪初期,有相当一个阶段基本上上市的是国企,国企甚至是带病上市,但是这几年政策又大大的倾向了中小型的民企,上市了一些企业,比如说最典型的云南上市的企业绿大地,就是另外一个极端。我个人的观点如果我们的证券市场跟着风跑,不管你扶持谁跑都会出问题。

沈竹:不跟风,咬定青山不放松的定力从哪儿来,我们刚刚跟两位一起交流了,对制度改革的意义做了探讨,下面的问题就是怎么改,从哪里入手会切中要害,稍事休息,我们继续我们的的评论。

(小片)

沈竹:欢迎回来。今天是我们聚焦A股红利大讨论的总结陈词,在过去的九期节目当中,我们分别讨论了分红、新股发行、退市制度、养老金入市、国际板、交易规则、以及打击内幕交易多项的话题,改革真是千头万绪,从哪儿入手,如何下手,才能把改革顺利的推进,并实现我们想象中的制度红利。现在就请两位嘉宾做一个小游戏,两位手里有一个小纸板,你们觉得从哪里入手对改革最有有力,最节省成本,请表达你们的看法,我们给两位一点点时间。

我们刚刚聊天的过程当中,两位都提到了新股发审的重要性,但是也有很多人说,审批这个东西是各个环节的,如果动了一个不让审批了,或者审批少了,会引起整个系统的大乱,所以方方面面的审批,到底应该从哪儿开始动起,我们看到两位都写好了。先看华教授的,发行审批制度。银总的新股发行加制度。两个人是大同小异,都切中了发行的关键环节。原因是什么?华教授。

华生:因为我们现在的制度,现在证券市场的基本制度,在股权分置改革以后,在形式上和国际上接轨了,但是精神实质上还有大的差距,最重要的就是发行审批制度,这个审批制度应该说是阻碍,甚至在很多方面扼杀了资本市场本身应该具有的活力和潜力。所以我觉得如果对这个制度不从根本上下决心动刀的话,我们很难再向前走,特别是我们发行定价的改革遇到了很多困难,进退两难,这就说明了一个问题,就是刚才你提到的,如果发行审批制度是一个整体,如果仅仅在某一点上动的话,结果反而还会造成新的扭曲,像我们的定价,市场化了,大家说你造成了三高,这叫伪市场化,现在仅仅在发行方面,在新股的发行上面做文章,包括在退市上是需要的,但是仅仅在个别环节上做文章问题,还不能解决问题,甚至造成新的问题。

沈竹:第一步要从新股发行入手,银总简练的表达一下您的观点。

银国宏:我写新股发行来讲,我其实更关注的是定价和销售这两个环节。目前来讲,刚才华教授提到了三高,定价高实际上引来的坏处是非常大的,第一个就是一级市场的投资者,严重侵蚀了二级市场的投资的利益,这是第一个。第二个就是发行价过高的话会削弱中国企业家的精神,资本市场是鼓励一些企业家来去创新,把他们的创新精神转化为高额的财富,如果财富的膨胀速度过快的话,企业家的精神会消失的,这不利于中国长期的发展。所以我觉得这是定价环节,销售环节来讲,目前也存在一个问题,实际上来讲的话,大体上来讲的话,你的发行人是证券公司的客户,最后把股票销出去,去买股票其实不一定是你的客户,这个时候来讲,利益就会有不平衡,在销售环节也应该使得你的客户,无论是发行人还是卖股票的人还是卖股票的人,都是你客户的时候,这个时候利益就会均衡,就会平等,所以这个来讲也是比较关键的问题。

沈竹:我们下面追问一下今天我们新股上市,深交所又开始抑制炒新来封停炒新账户,这样的做法不知道两位怎么评价的?包括2009年的时候华教授也写了一篇文章,新股发行改革的几个核心问题,当时就预测到了,有可能我们市盈率的问题会出现结构性的偏差,比如小盘的股市盈率奇高无比,而大盘股再低的市盈率也出现了发售很困难的情况,这样的问题为什么叫伪市场化,真正的改,像这样抑制炒新的方法能够长久吗?

华生:说实话我个人觉得是不行的,这一点我跟银总的看法又不太一样,我觉得重要的不是定价和销售。实际上我们想控制发行价是很容易的,过去都是控制发行价,所以没有三高,你给个窗口指导,行政性的控制,这个并不困难。如果你控制了发行价的结果,那就是新股上市首日爆涨和炒新,就是按下葫芦浮起瓢。所以我觉得我们监管部门过多的介入市场本身的交易,违法的违规的要打击,这个我是赞成,但是我们过多的介入市场本身的交易,而且不断的出台一些主观的、人为的制度去干涉市场本身的运行,我个人认为不可取的,因为我们的方向是市场化,如果我们要出台制度的话,最好也是规范的。比如说首日,我们现在每一天的交易都是由10%的涨跌,出一个制度既然是市场化发行了,首日跟其他的日有什么区别呢?也就是10%的涨停板控制,这样统一的制度规范,而且给投资者一个稳定的指引,一样能够达到抑制炒新的目的,所以我个人是不太赞成,我们频繁的用行政手段出台措施。

沈竹:这种结构性失调,怎么处理比较符合市场化的规律呢?

华生:你要看到这些新股,比如说把定价,最后为什么炒新又厉害了呢?是因为前一阵控制了发行价,从各个方面吹风、打招呼,使得定价掉下来了。下来了以后跟二级市场上同类企业,同类小规模的企业价格就有很大的落差,这种情况下,你首日挡住了,最后三分钟又涨上去了,或者第二天继续炒上去了,所以我们看到你把发行价按住了,上市了以后又给你翻了一倍,这样做实际上对长期的发展更不利,这些钱奖励了认购者,上市公司没有拿到,上市公司没有拿到以后,过不了多久,创业板又再融资,进一步增加对市场的压力,我们还是要考虑根本性的制度变革,不光是技术性的手段上做一些调整。

沈竹:银总又开始频频点头,今天你要跟华教授不一样的思考,对待现在的抑制炒新的方式,您是什么态度?

银国宏:抑制炒新,大多是从交易环节抑制,这是比较难的。这几天来讲,上市的新股基本上每天会停牌,这就充分说明了这个制度抑制会有一些难度。我现在还是这样讲,其实我讲的所谓发行和销售环节的改革,并不是行政性的干预,而是说在定价的流程和发行的流程有很多还没有达到市场化的程度,如果真的达到市场化程度来讲,就会消除伪市场化状态。

沈竹:能达到吗?

银国宏:完全可以。其实现在整个定价的程序、流程,都有很多改革的环节,包括定价是招标荷兰式,或者是美国式,我觉得都有改革的空间,包括销售是不定项的销售还是批股制度,其实我觉得这些东西都可以改革,这些东西改革以后,本身如果在发行环节,就能通过市场化反映出市场交易的价格,这个交易价格只不过不是二级市场交易的反映,这个时候来讲,跟二级市场的价格会比较接轨,这样来讲,无论首日上涨还是暴跌,实际上里讲都已经交给市场了,这个既不是我要奖励给谁,也不是去惩罚谁,完全是由市场交易的行为,交易出的价格,这个是最合理的。

沈竹:您总有自己独特的观点。华教授也思考新股建设该从哪儿入手,这个步骤该怎么样,酝酿写一篇比较系统性的问题,针对我们提出的问题,您认为您的思考的问题是怎么样的?怎么样抑制三高,怎么样让市盈率结构性不平衡得到改善,市场化的手段该是如何的?

华生:这个可能我们在今天在这儿把事情说清楚了,不太允许我们。我总的想法是我们把整体发行审批制度作为整个来看,因为每个环节都是审批的,如果您仅在某一点上动肯定会出问题。回到刚才说的新股,我们新股为什么出问题,比如去年第四季度,实际上某种意义上,这种炒新的问题已经基本解决了,就像刚才银总说的,你基本交给市场了,大家都不去认购了,这是市场发挥作用了。发挥作用的结果大家并不满意,大家说你看三高,上市都破发了,造成很多严重的问题,说明仅仅在这个环节上兜圈子,我们兜不出来,我们控制住了,今年导致破发都没有了,上市以后涨80%、90%的股票多的是,但是这样的结果必然是造成下一步大量的资金涌向新股认购的环节,大量的资金来进行新股炒作。我个人的观点是要做总体的规划,不是强调顶层设计吗,我觉得要像股权分置改革一样,对整个发行审批制度要有大的目标,是不是要从审批制向一个有门槛,有标准,有一定审核的注册制过度,这个目标你要不要,如果有目标,应该做哪几件事情,应该从什么地方突破,这个是哪个环节上做总攻,这个我觉得要有一个全盘的计划。如果这样来做,我们做改革的时候就不会动了一个环节,结果出现另外一个问题,就像我们动了定价的市场化,带来了三高的问题,结果我们现在实际上三高往后退,退的过程当中,又出现了新股首日的暴涨和炒作的问题,我的中心意思是想说,我们要有一个大的规划,要做一个大的制度变革的准备,这一点,恐怕管理层和政府都要考虑。

沈竹:我们也期待着你整体的思路给我们和盘托出的日子。最后一个问题,因为时间的关系,我们大家没有办法分享更多的细节性的操作过程。我们谈了将近十天的制度红利,我们真的想知道到底什么样是我们期待的制度红利,我们知道美国的制度红利带来大牛市,我们也期待我们的制度红利能给我们带来大牛市,这样的期待,您觉得我们能够看到吗?

华生:我个人是非常有信心的,一个方面呢,确实像证监会领导说的,我们现在再一个好的起点上,现在不是2001年也不是2007年,市场的泡沫已经基本上散去,中国经济固然面临着很多挑战,包括银总说的制度转型的挑战。但是呢,我对中国经济中长期发展是有信心的,我们还处在城市化的前中期,中国工业化中期,中国经济长期发展是可以预期,有了强大的基础,如果证券市场本身再把自己的制度瓶颈给解决了,要把未来十年有一个很好的回报,我认为是完全可以预期的。

1
2012.03。17 上证指数大约在2300~2500之间, 华生认为泡沫基本散去

沈竹:最后交给银总,什么是真正的制度红利,我们能不能看到制度红利带来的大牛市?

银国宏:首先我觉得我们一定会看到一个制度红利带来一个市场的上涨,但是这个牛市有多大,不太好判断,取决于制度红利的释放程度。什么是制度红利呢?最近我觉得大家都听了很多郭主席关于制度变革的讲话,一个框架性的东西,总体性的东西已经出来了,这个里面覆盖的东西是非常全面和完整的,这里头按照改革的顺利,一个轻重缓急和难易程度来讲的话,要有一个推进的过程,要让整个A股市场和资本市场看到改革是在往前走,而不是仅仅停留在讨论的层面,这样的制度红利一定会带来整个A股市场的恢复。

沈竹:好的,再次感谢两位嘉宾的精彩观点,我们说聚焦A股制度红利,到今天暂时告一段落了。不过,我相信这不是一个结束,而只是一个开始,我们期待着跟股改相提并论的二次股改,能够为A股带来新的气象,郭树清主席最近再次表示对资本市场的发展充满信心,当前推进的发行改革,退市改革和投资者保护等一系列的举措,都是提振股市信心的做法,在改革的深水区,我相信决心比信心重要,信心比黄金重要,我们希望监管层和制度的改革者,不负我们亿万投资者的期待,让真正的制度红利,催生真正的新牛市。

重温股市大辩论的是是非非

中国股市的问题主要不是出在投资者一边,而是出在融资者和裁判员身上。裁判员吹偏哨,向着融资者一边倒,是投资者一损再损,股市价值中心不断下移的根源。裁判员如果一再误判,损害了球赛,他自己也要受到制裁。

2000年底至2001年初这段时间,经济学界出现了一种影响力很大的观点,持这个观点的一位著名经济学家集中抨击中国证券市场的投机炒作和股市泡沫,声援证券监管部门从2000年初开始的规范市场、打击坐庄炒作、推行市场化改革的措施,认为“中国股市从一开始就很不规范”,“不规范的股市对我国证券市场发展和整个市场经济制度的危害极大”。“从深层次看,股市上盛行的违规、违法活动,使投资者得不到回报,变成了一个投机的天堂”,“坐庄、炒作、操纵股价这种活动可以说是登峰造极”,像一个可以偷看别人牌的不规范的赌场。他认为,做短线即投机与做长线即投资不同,投机炒作是一种零和博弈,只是钱从一个人口袋流向另一个口袋,并不创造财富。“想要依靠投机使一个国家或全体参与者富起来,那纯粹是一种幻想。”后来,他的观点被人形象地但也并不全面地概括为“赌场论”、“泡沫论”和“全民炒股论”。

董辅礽先生治学几十年,虽有改革开放伊始就喊出经济改革的实质就是要改革国家所有制形式的石破天惊之举,却从来没有对某一个经济学同仁的观点进行针锋相对批驳的先例。例如,尽管先生是以所有制改革振聋发聩于经济学界,但在20世纪80年代厉以宁教授“所有制改革优先”与这位经济学家“价格改革优先”的论战中,先生竟稳坐一旁,并未帮腔。80年代中后期,先生的弟子以“双轨制增量渐进改革论”与以这位经济学家为代表的“综合配套改革论”之间的唇枪舌剑,也未撼动先生的修身定力,他依旧隔岸观火,旁若无人。先生生前说起他与这位经济学家从无宿怨,改革前的困难年代相互还帮过一点小忙。尽管在证券市场问题上,先生一贯对股市呵护有加,而这位经济学家一直警告股市泡沫,认为在股市遇到困难时的政策救市,是不当的政府托市行为,不过双方从未正面接触更不用说直接交锋。但是,这次先生如此珍爱和寄予厚望的中国证券市场,不仅像是遭了一大桶污水,而且在他看来简直是处在要被全盘否定的危急关头,年逾古稀的先生竟像年轻人一样跳将出来,对他认为是完全错误和不能接受的“三论”迎头痛击,这恐怕是先生自己也不曾想到的事。

接下来的事情更是出乎先生的意料,当董辅礽先生有理有据地对股市的“赌场论”、“投机泡沫论”、“全民炒股论”逐一批驳之后,对方指出,他从不否认证券市场的功能和作用,只是反对过度投机炒作,反对庄家黑市,反对股市狂热和股灾,因为其结果只会使小投资者受损,对广大中小投资者,他从来都是“我爱你们,但你们要警惕啊!”因此,先生及他的同道人对证券市场的捍卫和反击,成了以偏概全、找错了对象地与风车作战,而秉性耿直的先生则老来当了回堂·吉诃德。更糟糕的是,股市争论从一开始就预设的经济学良心与黑心、改革与既得利益的反抗格局,使得先生一干反击的人一上来就大有“既得利益代表”、“庄家代言人”的嫌疑。董辅礽先生有生以来第一次从理论上和道德上被打上了一个不大不小的问号。以至不久后在“两会”上记者采访时,先生如孩子般赌气和无忌地说,“我不懂股市,没有什么可说。”这就是毫无心计和童心未泯的先生!

换个角度看,董辅礽先生实际上是在以沉默作无声的抗议,抗议在中国经济学界争论的过程中,第一次把道德、良心,把利益影射和大众情绪带进独立的学术研讨和争论,从而使独立的学术研究和讨论无法正常进行下去。我们后来看到,国有股市价减持的错误政策正是在此之后推出不久又被废止的,给国家、市场和投资者带来无端的损失,而恰好在此之前发生的经济学界股市大争论却没有能发挥它本应有的理论先导作用。这是非常令人惋惜的,也是理论界应当吸取的经济研究中的一个深刻教训。

客观地说,股市的批评者抓住了投机泡沫和坐庄炒作这个颇能拨动大众心弦的现象,因而一时引起了广泛的共鸣,而如董辅礽先生这样的股市捍卫者,呵护心切,又由于不是自己的专门领域,没有抓住中国股市在股权分置基础上溢价圈钱这个本质,这样对股市投资价值的认定,就缺乏可靠的基础,留下了被人批评的口实。因此,当股市在规范化的口号下打击了炒作,放开了圈钱,市场失衡,熊途漫漫时,争论的双方都受到相当多股民的责疑,就不难理解了。

庙堂经济学家的权力江湖

作为中国最顶级的经济学家,躬逢思想解放的上个世纪八十年代,在历史机遇与个人的奋斗的合力下,他们成为朝野器重的改革英雄。学术权力与现实影响力,让他们成为时代的明星。这些经济学家当仁不让地构成了中国学术圈中的“豪门”。

  文|李军奇

  家庭联产承包、国有企业股份制改造、价格双轨制、整体改革,这些牵动整个中国上个世纪八十年代时代神经的词汇,其背后都挺立着一个个赤心热血的经济学家。中国没有哪个时代,经济学家会被如此器重,他们以其卓越的学术勇气与学术良知,影响决策,改写历史,赢得朝野尊重,成为时代耀眼的英雄与明星。2008年开创的中国经济理论创新奖,总结经济历史,并将幕后的经济学家推至前台,以公开公正的旗帜,推动学术民主,以期催发中国经济学的繁荣。

  大争鸣,“中青年”啸聚莫干山

  2011年11月26日下午,北大经济学院泰康人寿报告厅,群贤毕至。13点20分,北京大学校长助理张维迎稳步而至,招牌式的华发一如往昔挺拔。甫一入门,起身祝贺与寒暄的学者络绎不绝;半小时后,燕京华侨大学校长华生悄然前来。原定13点30分启幕的会议已经开始。华生想从侧门绕进,不巧,他的座牌靠近正门。而侧门第一排,张维迎默然端坐,偶然低头写上几笔。华生退步—也许正门落座才不会太引人注目。20分钟后,记者求证组委会,确知当天另一主角田源因故不会到场。这是中国经济学家年度论坛暨中国经济理论创新奖(2011)颁奖典礼现场。经202位经济学家、著名大学经济院校和国内研究机构负责人、主要经济和学术媒体负责人以记名投票方式评选,以华生研究组、田源、张维迎为主要贡献人的“价格双轨理论”,高票当选第四届中国经济理论创新奖。

  纷争一时的关于谁是“价格双规理论”第一发明人的喧嚣,以华生研究组、张维迎的到场,田源的缺席暂划一个句号。华生在领奖时回顾“价格双规理论”的诞生地—浙江莫干山,不胜唏嘘:“27年了,(人生)能有几个27年。当时在那儿争论,能够到今天在领奖台上,我很希望你(编者注:当年会议的重要参与者王岐山)来参加。”

  正是莫干山会议,促成中青年经济学家的全面崛起,他们开始深度介入中国的改革时代。这是已被载入史册的辉煌时刻!

  1984年4月,25岁的西北大学研究生张维迎以《以价格改革为中心带动整个经济体制的改革》一文惊险过关,成为莫干山会议的150人成员之一。这是一群忧心于城市改革的青年经济学者,他们被“不讲关系、不讲学历、不讲职称、不讲职业、不讲名气,凭论文水平确认代表资格”的“铁血原则”吸引,啸聚浙江莫干山。会议的策划者之一、时任国务院技术经济中心助理研究员黄江南回忆:“一位民族学院的女士,在山下哭了好长时间,非要上来。阻挡她的人说,你又不是发起单位的,又没有论文被选上,凭什么让你上。结果她说:‘我也是搞改革的啊!’挨不过她的执拗,就说让她上来待一天就离开。第二天就要她走。”这是一个民间组织的学术活动,因时任中央书记处农村政策研究室外联部副主任王岐山等官员的到会,一时成为朝野瞩目的焦点。

  会务颇具创新,上山不许带论文,第一天不开会,先聊天交友;会议分成七组,每组有主持人,有中心发言和会员讨论,会员到哪个组听都可以。与会者热烈讨论,时而火药味十足。从白天到黑夜,人人精神亢奋。会议结束时,居然大半人累得生病。经过几番激辩,双轨制成为莫干山会议价格组的主流观点。会议最终形成一个总报告和附有一份专题报告《价格改革的两种思路》以及由华生执笔的会议纪要—《用自觉的双轨制平稳地实现价格改革》。

  莫干山会效应像发射波,一波一波向外扩展。很多青年因此声名远播。会后,很多与会者迈入政府体改部门,比如田源成为国家体改委委员;年纪最小的张维迎在这年12月去体改委报到上班。吸纳青年学者的意见,鼓励年轻人冒头,一时成为各地政府的开明之举。河南省政府曾组织河南省经济咨询团,由省长刘杰任团长,于1985年4月邀请莫干山会议中的一些骨干人员作为政府的咨询顾问。近百位青年经济学家群情振奋,欣然受聘,开了省一级领导和青年经济学家直接沟通对话、直接形成地区发展战略的先河。莫干山会议之后,“中青年”成了被社会广泛承认的改革时代新名词。

  事隔多年,在谁首先提出价格双轨制问题上,张维迎、罗小朋等人卷入争论风暴,不过罗小朋亦承认同一讨论组的华生对价格双轨制的贡献在于他的口才,“他把这个思路变成会议的主流思路,并且对于说服决策者起了其他人不可替代的作用。”从这个角度来讲,“在当时的青年一代中,他的功劳确实是最大的,他应该是‘双轨制’当之无愧的代表人物”。

  大勇气,三个老人的故事

  如果说第四届中国经济理论创新奖记忆了上个世纪八十年代中青年的风发意气,那么2008年第一届中国经济理论创新奖则颂扬了历经劫难的老一辈经济学家的政治勇气与学术良知。

  “每天上午八点半,杜润生都要到位于北京砖塔胡同的办公室上班。在这个陈旧昏暗朝北的房间里,扭开一个上世纪80年代样式的台灯,他要静静坐上那么一会儿。”没有人知道他在想些什么。这是2007年媒体笔下94岁老人杜润生的生活片段。一年后,95岁高龄的杜润生作为“农村家庭联产承包责任制理论”的主要贡献人,首获中国经济理论创新奖。

  1955年,因为对农村合作化心存疑虑,杜润生曾被毛泽东批评为“小脚女人”,解除了他中央农村工作部秘书长的职务。1980年秋,在中央长期规划会议上,时任中央农村政策研究室主任的杜润生提出先在贫困地区试行包产到户。这个建言得到时任副总理姚依林的支持,随后邓小平终于发话表示赞同。1981年,杜润生在国务院会议上再次放言:集体经济已难以维持,最大的弊端就是把人捆死;社会主义的目标是实现共同富裕,不是共同贫困。这一年的春夏之交,杜润生亲率调查组,坐在颠簸的吉普车里,挺进农村做田野调查。杜润生主持起草了1982年到1986年的五个重要的“一号文件”,正式肯定了农村家庭承包经营制度,终结包产到户长达30年的争论。

  近百岁的杜润生已倦于回顾自己对“包产到户”的作为,对于2008年的那次时隔二十多年的褒奖,他坚持说那是农民自己的发明。双耳失聪的他听不到颁奖现场雷鸣般的掌声。他喜欢待在安静的个人世界里,多年思考,悟出一句:中国的改革要过两关,一个市场关,一个民主关。晚年有记者问他:中国的改革最需要警惕的是什么?这个有着“中国农村改革之父”的老人不假思索,大声说:权贵资本主义!

  师从杜润生的一些青年如今已成思考和解决中国问题的中坚,他们中有国务院副总理王岐山、中央农村工作领导小组办公室主任陈锡文和著名经济学家周其仁。这三位都曾直接参与了上世纪80年代连续五个中央“一号文件”的起草。

  与心系农村和农业的杜润生相比,文革结束后已是北大经济系副教授的厉以宁的职业兴趣在于城市与工业。1980年4月到5月,中央书记处研究室和国家劳动总局联合召开的劳动就业座谈会上,厉以宁提出以股份制模式,以及企业可以通过发行股票扩大经营,来解决当时城市日益窘迫的就业问题。可惜,在计划经济一手遮天的时代,他的提议未能得到认可。厉以宁有感而发:“隋代不循秦汉律,明人不着宋人装。陈规当变终须变,留与儿孙评短长。”

  偃旗息鼓终非厉以宁的性格。1986年9月,他在《人民日报》上发表《我国所有制改革的设想》一文,从理论上详细地讨论了我国改革以后的所有制体系以及股份公司的构造。1986年,《纽约时报》就以“厉股份”的称谓来报道厉以宁在中国股份制改造问题中的作为。不过,相比“厉股份”,厉以宁不排斥有人喊他 “厉非均衡”。因为在他看来,股份制是一种具体的方法,“最集中代表我观点的书就是那本《非均衡的中国经济》。”因对所有制改革起到了重要的推动作用,作为“国有企业股份制改革理论”的主要贡献人,厉以宁获得第二届中国经济理论创新奖。

  在2011年11月26日中国经济理论创新奖现场,厉以宁稳居第一排中间位置,华生、张维迎分居其左右。他当天发表了关于缩小城乡制度差距的演讲。语气铿锵,学术的目光返至农村,强调“必须给农民以产权,农民没产权是没有道路的”。

  1985年前,中央经济改革基本上是局部的、零敲碎打的和自发式的。1985年前后,以吴敬琏为代表的部分经济学家对是否应该继续沿着“放权让利”方向前景持有怀疑态度,提出救治之策在于推进配套改革。他们主张政府进行价税财联动的改革,并参加了1986年国务院领导提出的“价、税、财配套改革”的方案设计工作,成为与“企业改革主线论”主张不同的“整体改革论”的主要代表。这种改革理论自成一体,并对中国经济改革的实践产生了较大影响。2010年,第三届中国经济理论创新奖颁给“整体改革理论”主要贡献人吴敬琏、周小川等人。

  被誉为中国经济学界“良心”的吴敬琏先生,年逾八旬依旧为中国改革而“常怀千岁忧”。从2001年怒斥中国股市“连规范的赌场都不如”,到2010年警告中国股市正处于“强盗贵族时代”,再到近年来成为呼吁转变经济增长方式的旗手,从“吴市场”到“吴法治”,他总是点中中国经济的痛处。

  大智慧,四代经济学人

  2011年11月23日14点,发展经济学之父张培刚走完了99岁的人生。他是在1949年前已经功成名就的那一代人中最后离世的经济学大师。生前,张培刚担任中国经济理论创新奖组委会主席。11月26日下午,中国经济学家年会会议正式开始前,中国经济理论创新奖组委会执行主席毛振华(微博)提议全体起立,向张培刚默哀。三百多经济学界人士纷纷站起,老中青三代学人沉浸在巨大的悲伤中。

  拿毛振华的话讲,1949年到改革开放前的三十多年时间,中国的经济学存在一个断层,而像张培刚这样的哈佛博士,基本中断了最黄金的学术生涯。庆幸的是他们捱过了学术最黑暗的时代,以余热培养出了自己的学生。

  经济学家赵晓在一篇名为《他们为中国播撒市场经济火种》的文章中写道:中国经济学家分为四代,第一代包括卓炯、顾准、孙冶方和薛暮桥;第二代有吴敬琏、马洪、刘国光和厉以宁;第三代有樊纲、周其仁、林毅夫、张维迎等人,而他自己这一批上个世纪末开始活跃的经济学者属于第四代。

  其实,遗憾的是,像解放前留洋的经济学教授,基本在计划经济的年代中靠边站,没有成为第一代经济学人的中坚。譬如建国初期“海归”杨敬年教授,中国最优秀的发展经济学家之一;譬如伦敦经济学院博士钱荣坤教授,中国一度最优秀的金融学家。他们莫不在连续不断的政治运动中屡屡遭受或轻或重的冲击,根本不敢奢望能有正常研究的一天。

  当然,根据其学术活跃时间和自身年龄,第一代经济学家还应包括于光远、杜润生等;第二代应有董辅、成思危和茅于轼等;第三代应有华生、田源、何家成、邹恒甫等;第四代则更多,譬如谢国忠、李稻葵(微博)等。

  赵晓说,第一代称得上凤毛麟角,已经退出历史舞台;第二代现在寥若晨星;第三代群星灿烂,如日中天;第四代则是批量生产,正在崛起。这四代经济学家一脉相承的是对于市场经济如何发展的研究,都是在完成经济学的启蒙工作。

  董门显赫,力撑最豪华经济学奖

  在第四届中国经济理论创新奖颁奖现场的嘉宾签到台上,记者看到,“董门”的台签赫然独列。鱼贯而入的各路经济学界人士一到门口,先前的并肩寒暄,到此各找签名簿。这委实是已故经济学家董辅的门生盛事。

  中国经济学理论创新奖,发源于董辅经济科学发展基金会。“中国经济学理论创新奖,是董辅基金会联合北大、人大、武大、上海交大和清华的经济学院而发起的一项旨在鼓励、褒扬经济学创新的奖项。”毛振华是董辅的博士生,也是董辅经济发展科学基金会的理事长。毛振华创办了中国诚信信用管理有限公司全程赞助中国经济理论创新奖;而董辅的另一个任泰康人寿的董事长的博士生陈东升为本届创新奖提供了总额100万的奖金,而提供评奖经费的武汉当代科技产业集团负责人,亦是董辅的门生。

  董辅师承发展经济学之父张培刚。早在上个世纪五十年代和六十年代,他便提出了关于再生产数量关系的数字模型,被誉为“中国经济成长论的代表”。在改革开放初期,他破天荒地就提出了企业改革的方向应该是“政企分离”、“政社分开”的政策性建议。他最早提出并一直坚持所有制改革成为中国经济改革的关键。1984年董辅获得了当时经济学最高奖—首届孙冶方经济学奖。

  2004年7月30日董辅病逝。8月12日,经济学界召开董辅追思会。“会上,有经济学家提出设立董辅基金会,董门弟子积极响应。讨论最后,确立基金会的发展方向是弘扬、鼓励经济学家的创新精神。”回忆起基金会创办情况,毛振华依然不减对恩师的感念之情。“2005年基金会终于注册成功。之所以没有用经济学家的名字命名这个奖项,是因为我们不是弘扬董先生的经济思想。”

  董辅从1985年后开始在北大、武大开设博士点。据董辅的学生、中国银行业协会常务副会长杨再平(微博)介绍,董辅生前带出的博士生有五十多个,目前担任司局级领导的约有二十多个,省部级的也有几个,还有许多在经商。董辅的第一个博士生是1985年进入中国社会科学院经济研究所工作的华生。同获第四届经济理论创新奖的田源亦是董辅的博士生。

  董辅面相严峻,但内心柔软,极为爱护学生。生前对于学生的要求,几近有求必应。在一个名为“怀念董辅”的网页上,近二十多弟子书写悼念文章,情真意切,感人肺腑。

  在第二代经济学家中,还没有在经济学“普道”上能超越董辅的。他的众多门生,每年以中国经济学年会暨中国经济理论创新奖的名义相聚,把手叙情,颌首论道。

  基本上,这些经济学家的学术荣耀系于改革开放,尤其是上个世纪八九十年代。这是理论总结实践、理论被纳入国家决策的非常时期。

  前三代经济学家,其学术生命与改革开放的进程紧密相连,问题意识始终推动着他们的学术思考。他们因关注时代大命题,而为决策者所注意,在体制内爆发出巨大的能力,进而影响社会,推动时代的发展。那是问题丛生的八十年代,生而有幸的八十年代。毛振华讲,这样的时代际遇基本不会再次出现。“衡量他们的成就,不是计算他们在国际一流学术刊物上发表多少篇论文,毕竟中国经济学本身要植根于中国的改革开放的实践。”

  2004年8月12日,在董辅追思会上,赵晓如此感叹,“每一代经济学家都有他们的问题意识,有他们时代的使命,他们为这个使命付出一切,我们都要为此感到庆幸。”前三代经济学家们以巨大的学术勇气与大无畏的探索精神,无愧于时代的召唤。而在日益浮躁的当下,新锐的经济学家们该承担什么使命?

  中国经济理论创新奖

  中国经济理论创新奖是我国第一个由经济学界以学术民主投票并公开计票的方式进行评选的经济学大奖,其宗旨是推动经济理论的创新和发展,每年评选出一个10年前的原创性经济理论,获奖理论将得到100万元奖金,这是目前国内奖励金额最高的经济学奖项。2008年,“农村经济改革之父”杜润生及中国农村发展问题研究组获得首届中国经济理论创新奖。

  影响经济决策的智囊机构

  上个世纪80年代初,杜润生以及他领导的中央农村政策研究室和国务院农村研究中心是党中央和国务院的重要智库。从1982年到1986年,连续五年,中央每年都要颁发一个关于农业问题的“一号文件”,其中中央农村政策研究室发挥了重大作用,王岐山、周其仁参与执笔。

  1982年5月,国家经济体制改革委员会成立,这是一个后来发挥了巨大影响的机构,其职能中就有“改革理论创新、设计总体方案”等,因此被形容为改革的“参谋机构”,而其下属的体制改革研究所亦成为著名官方智囊机构。每年国务院召开改革座谈会以及各种专题讨论会,体改所承担着输送年轻学者的任务,对中国改革的宏观决策提供意见。周小川时任体改所副所长,当时体改所的年轻人还有张维迎。体改所被认为是1980年代最有影响的“思想库”。

  1985年,原国务院经济研究中心、技术经济研究中心和价格研究中心合并成了一个新的机构—国务院发展研究中心,这个直属国务院的机构被描述为“国务院的咨询研究机构”,在此后的二十多年里,这个机构也发挥独特的作用。吴敬琏长期在此任职。林毅夫曾任国务院发展研究中心农村部副部长。

  1994年,直属国务院的国家行政学院成立,“提供政府管理政策咨询”的定位使它迅速和国务院发展研究中心成为“一政一经”两大国务院智囊机构,而老牌的中国社科院则开始从理论研究更多地转向现实问题。

  混战江湖

  第一代与第二代经济学家,因关注改革热点问题,身处体制内,影响决策,往往被大众定格为“庙堂”经济学家。那些经常在媒体发声的,则被学院派经济学家讥讽为“媒体经济学家”;无视学术辈分与争鸣规则,四处挑战,常惹江湖硝烟的,则被媒体冠以“明星经济学家”。这三类经济学人并非界限分明,彼此有交集。他们的学术论证,在日益市场化、利益集团化的上个世纪九十年代,勾兑着门派之见、名利之争、学术话语权之抢夺。学术界日益江湖化、学术权力场日益碎片化,成为一个不可逆的潮流。

  文|牧野

  经济学从来是仁者见仁、智者见智的事情。观点纷争,应是学术争鸣的应有之义。这些论争,如果卷入风云莫测的政治斗争或人事诬陷中,加上旁观者的误读甚至搅和,正常的学术争鸣,亦会变色,蜕变为名利场的角斗。

  温和之战:门户之见与学术争鸣

  在第一代经济学人,因为时逢百废俱兴,个人的学术发展与单位的地位挂钩,服从组织,服务大局,基本抑制了经济学家内争的可能。真有价值的经济学家,都有属于自己的一片学术开阔地,即使争论,多是改革的声音与保守的声音之间的交锋。私人名利与恩怨,在其间基本不太突出。

  在第二代经济学家,因学术的争论而导致彼此感情的疏离现象,开始出现。大经济学家成为改革的英雄,他们亦成为日益发达的媒体宠儿。大众舆论的加入,使得这种学术辩论容易走火伤人。

  吴敬琏与厉以宁的学术纷争是经济界人尽皆知的事情。两人在学术观点上的分歧,最早发生于上个世纪八十年代中后期,当时厉以宁认为企业改制势在必行,吴敬琏则认为应优先考虑价格改革。2001年2月,由于对股票市场的状况和发展看法不同,两人的矛盾白热化,引发了一场为国人所瞩目的争论。自此,两人争论不断,甚至鲜少同时出现在一个场合。

  尽管事后,吴敬琏表示,为了维护思想自由,学术独立,大家都有责任维护一种不用意见争论的氛围。厉以宁亦公开表示:“我和吴敬琏有过几次争论,其实我们俩关系挺好的。我们俩是高中同学,我们俩在改革大方向上始终是一致的。”但至为惋惜的是,这种不能成为朋友的学术论争,还是被外界解读为两人不和的原因。

  孙冶方是我国老资格的经济学人,他执掌中国科学院经济研究所时,先后将吴敬琏、董辅招至麾下。“先生生前说他与这位经济学家从无宿怨,改革前的困难年代相互还帮过一点小忙。”董辅的得意弟子华生在回忆恩师的文章中,将他与师傅的共同“论敌”—吴敬琏,称为“这位经济学家”。华生曾因双规制度增量渐进改革论与吴敬琏为代表的综合配套改革派发生过唇枪舌剑。

  在华生看来,恩师最为看重的中国证券市场,在2000底、2001年初遭遇了吴敬琏的痛击。董辅的“婴儿论”与吴敬琏的“赌场论”针锋相对。华生在回忆恩师的文章中认为这次争论,“第一次把道德、良心、利益映射和大众情绪带进独立的学术研讨和争论,从而使得独立的学术研究和讨论没办法正常进行下去。”董辅与吴敬琏的学术分歧,因参与者的情感因素,旁观者的误读,最终伤害了论争双方的私人关系。

  董辅与厉以宁、萧灼基向来交好。他们经常出门结伴调研,厉以宁、萧灼基亦是董辅的弟子博士论文答辩委员会的常客。董辅去世后,两人均写文悼念。厉以宁也是董辅追思会积极的召集人。

  在第三代经济学家中,关于价格双轨制理论的第一发明者,出现了过多个版本,当年莫干山会议的参与者华生、张维迎、罗小朋均卷入纷争。在2011年11月26日的颁奖致辞中,华生反复强调这是一个“集体智慧的结晶”,“这些想法完全是在会议上通宵达旦碰撞出来的。”张维迎则如此追述:“大概在莫干山会议之前的4个多月,在莫干山会议之前,我有了(价格双轨制)第二稿,第二稿发表在内蒙古经济研究1984年第四期,那是公开的刊物。”

  其实,排除学术上的纷争,张维迎和华生,在师承上还有源渊。张维迎在西北大学的硕士导师何炼成是武汉大学张培刚的高足,而华生的恩师董辅亦是张培刚的门生。张培刚在武汉大学先后培养出董辅、曾启贤、何炼成等。董辅门生成名者众,而曾启贤又培养出邹恒甫、杨再平等一流学者;何炼成领导下的偏居一方的西北大学经济管理学院,居然为中国经济学贡献了数位重量级人物,包括张曙光(微博)、邹东涛、魏杰等人,享有“青年经济学家的摇篮”美誉。当时经济学界许多重量级人物都与武汉大学有着或显或隐的关系,一时圈内有“武大学派”之称。

  尽管是师承有关系,但抵挡不住利益与声名的利剑。与张维迎同是张培刚弟子的弟子,邹恒甫就曾因被北大光华管理学院(微博)辞退,在博客上破口大骂时任院长的张维迎。

  致命之战:学术评价体系之异见

  经历了大破大立、英雄辈出的1980年代,经济学家的论争基本被纳入更学术的轨道,他们开始走下“神殿”,被动或主动地还原为更纯粹的知识分子。尽管这一历程伴随着时代阵痛,但昔日的“英雄”随时有被枪挑下马的“惊吓”。关于经济学人的评价体系,遭遇前所惟有的险情。

  在武汉大学教授邹恒甫眼里,这些上个世纪八十年代成名的中国经济学大家,“有些人根本没有任何学术成就”,他把中国一批著名的经济学家编成“三纲五常”、“林海张杨”,多次在公开场合毫不客气地点评他们。在他的学术评价体系里,国际一流学术期刊才是展示实力的舞台。

  2005年11月,香港科技大学教授丁学良,在北京某媒体上发表“中国合格经济学家不超过五个”的观点后,引起媒体强烈关注。面对批评,经济学家集体沉默。

  论及对经济学家之间的直言批评,《经济学消息报》创办人高小勇提及这样一件事。上个世纪九十年代中期,曾与吴敬琏在一个市场化改革方案设计组的才子刘吉瑞,从英国普茨茅斯给高小勇传真来一篇稿子。刘在文章中感慨“在中国当个经济学家,比当木匠容易”。当时高小勇很喜欢这篇文章,打电话给樊纲。樊纲的回答却是:谨慎些,中国经济学进步需要一个过程。

  第一代与第二代经济学家,因关注改革热点问题,身处体制内,影响决策,往往被大众定格为“庙堂”经济学家。而新成长起来的第四代经济学家们,往往以学术的深度、在一流国际期刊上的论文数量,来与第二代、第三代经济学家论衡。这些很早吮吸西方经济学理论的后来者往往“不服”或“轻视”前辈经济学家。

  这种对于经济学家的重估浪潮,开始挑战一个传统定论:经济学家的价值,在于现实的参与度,学说的“经世致用”性。但无论如何,在新的评价体系面前,有的经济学家开始了默默自省,更多地关注自我的学术创新。

  艰难之战:为“道德”与“良心”交锋

  上个世纪九十年代,是市场经济起步与高速发展的时代,公平与效率成为经济学家争论的焦点。“国退民进”、产权改革等论战中,道德与良心、公正与良知,成为批评者娴熟使用的词汇。这一阶段中,郎咸平(微博)持续处于旋涡之中,这个郎旋风,先后与中国经济学界大腕吴敬琏、张维迎、周其仁交过手。

  如果说这些发生在顶级经济学家之间的裂隙,大致诱因是学术观点的差异与名利的纷争,那么在媒体发达时代,大众对顶级经济学家的围观与批判,则发酵了经济学界最为复杂的唾沫狂欢。一时间,追求学术独立与营造健康的学术氛围,亦被知识界一再呼吁。清华大学经济管理学院金融系主任李稻葵一度生气地说,经济学界不算健康的争论风气让他开始怀念多年前关于改革细节的争辩,和“不争论”、“多实践”的日子。

  樊纲的宽厚和理性一直给予高小勇很深的印象。“说樊纲理性、懂科学,是因为他是最早提出把事实研究和价值研究分开的经济学家。”樊纲早在上世纪90年代,就曾在《经济学消息报》的一篇文章里,提出了直到如今都争议不休的观点:经济学和道德无关。高小勇认为这一观点,有助于在一个有着感情用事传统的国度里,充分理解经济学的科学实质。

  在财经作家苏小和看来,当代中国经济学家中,唯有周其仁挨骂最少。“当茅于轼、张维迎,甚至还有吴敬琏被各路人马破口大骂之时,周其仁却在各种场合赢得一阵阵热烈的掌声”;林毅夫被人们讥笑为“政府御用经济学家”,而当周其仁接替林的中国经济研究中心掌门人之位时,却被人们评价为,“周将会为这所高级别的经济研究机

  构带去真正独立的学术之风”。

  “周其仁之所以能不陷入大众的谩骂声中,是因为他一方面将自己的言论场域仅仅锁定在学院经济学之内,他的文章之专业、学问之严谨,一般不围绕大众关心的经济热点问题作惊人之语。另一方面,听过周先生演讲的人都感受到了他的控制力,他的演讲从不大声呼喊,句子在某种有意克制的节奏和氛围中娓娓说出,目光凝聚,脸面生动,在有形无形之间感染受众”。这涉及到书斋学术与庙堂学术的问题,同时又牵扯个人的做学术的姿态、传播学问的方式。

  媒体的发达,让经济学家群体出现明显分野。一类更加专业性,走向书斋,看重与国际学术界对话。这类经济学家强调学术独立与学术的国际性,譬如邹恒甫。他们基本财务独立,不迷恋各种论坛与商界活动,沉潜于学术教育与研究;一类是明星式学者。他们善于针对社会热点问题,接受媒体访问;频繁穿梭于各种活动,曝光率奇高,亦被评价为“媒体经济学家”,譬如郎咸平;最为大众诟病的则是任职于各类商业机构的经济学家,他们常被讥讽为利益集团的“帮凶”。

  恒久议题:庙堂之争与学术独立

  至于学术独立,在毛振华看来,其实,身处“庙堂”,如果违背自己的理论良知,追风、骑墙,肯定不会有杰出成就。四届中国经济理论创新奖项的颁布,正是证明了三代经济学家关注现实、坚持真理的学术勇气和人格操守。

  中国最顶级的经济学家,从董辅、吴敬琏、厉以宁、张维迎、华生、邹恒甫,或因学术或因人事改革或因个人性情、修养,沉人际关系泥沼。学术是非,可以时间来检验,而名利是非,恐怕终生无解。为政策背书,为利益集团代言,在权力与商业轮番侵蚀的时代,经济学家继续走向分化,似乎不可避免。学术自由与思想独立,仍是中国经济学家常读常新的必修课。

  “老一辈经济学家,人和人之间很熟,一起共事过,各有各的观点,个人之间,经过那么长的社会矛盾,有各种交集,也有分歧,但最终都参与进来,也不容易。”毛振华说,开始吴敬琏和刘国光老师对他们的邀请,基本保持沉默,“现在他们都是中国经济理论创新奖评委会的名誉主席,这也反映出他们学术大家的胸怀。”

  在毛振华等董门弟子看来,董辅经济学发展基金会联合高校学术机构,创设中国经济理论创新奖,“就是要弘扬学术民主,不论你对谁的学术观点有意见,对不起,你只有一票;你对谁有成见,在两百多票中,永远只是少数。经济学这么大的学科,观点纷争是正常的,落实到评奖上,关键是要公平公正。”

  高尚全 中国经济体制改革研究会名誉会长,中国经济理论创新奖(2011)颁奖典礼演讲嘉宾。他多次参加党中央、国务院重要政策和体制文件的起草工作。

  中国经济学界在改革发展中发挥了重要的作用。中国经济学奖既肯定经济界专家学者的贡献,也是为了总结改革和发展所走过的道路,为我国经济未来更好的发展奠定牢固的理论和政策基础。

  厉以宁 是我国最早提出股份制改革理论的学者之一,他的学术研究贯穿中国改革开放30多年历程。他是中国经济理论创新奖(2011)评审专家、第二届中国经理理论创新奖获得者。

  你几时看见厉以宁和谁论战了?我就谈我的观点。任何经济学家都不可能是先知先觉者,必须跟着实践走。我最初提出在中国实行股份制也只是一个假设,只有经过实践检验后才慢慢成为真正的理论。

  张维迎 北京大学校长助理, 2011年,因对双轨制价格改革的理论贡献荣获第四届“中国经济理论创新奖”。1983年他发表《为钱正名》之后,就一直深陷争论的漩涡之中。

  任何一种思想,无论是哲学的还是宗教的,无论创始人多么伟大,无论在创造时多么正确,一旦变成垄断的思想,就会助长无知和无耻,给人类带来灾难。所以我们的希望在于我们的未来。

  孙祁祥 北京大学经济学院院长,中国经济理论创新奖(2011)颁奖典礼演讲嘉宾。业界评论她是“中国保险学界第一人”、“保险学界的铿锵玫瑰”、“亚洲保险业的女强人”。

  真正能够对经济学的发展起到推动作用,对实践的发展起到推动作用的,我们大家都耳熟能详许多经典的理论和非常重要的实证研究都具有深刻而简明的特点,我认为好的理论应当是深刻而简明的。

  陈继勇 武汉大学经济与管理学院院长,中国经济理论创新奖(2011)颁奖典礼演讲嘉宾。国家级重点学科——武汉大学世界经济学科点学科带头人及湖北省跨世纪学科带头人。

  一个学者获得知识的目的,就在于“借助于这些知识,保障人类的全部天资得到同等的、持续而又进步的发展。由此,就产生了学者的真正使命:高度注视人类一般的实际发展进程,并经常促进这种发展进程”。

  顶级经济学家权力榜

  这些经济学家处于改革开放的潮头浪尖。他们基本掌握着中国经济理论的话语权。以其学术活跃的年代和媒体影响力,大致可以将其划分为四类。

  1949-1980年代初

  学术奠基人

  顾准 中国最早提出社会主义市场经济理论的第一人。顾准在中国社会科学院经济研究所从事研究工作,其卓尔不群、独立思考的精神影响了吴敬琏等经济学家。是中国经济学家思想“教父”级大师。

  张培刚 发展经济学奠基人,经济学“武大学派”的灵魂人物,董辅、曾启贤、何炼成是其高足。

  孙冶方 执掌中国科学院经济研究所所长时,先后将吴敬琏、董辅招至麾下。孙冶方经济科学奖是中国经济学界上世纪八十年代最高奖项。

  薛暮桥 新中国第一代社会主义经济学家和高级经济官员之一,被誉为“市场经济拓荒者”。与孙冶方一向交好。

  于光远 许多经济建设和经济体制改革中的重大理论问题都是由他率先或较早提出的,并参与了许多重要的决策。与董辅交好。

  杜润生 家庭联产承包责任制理论的主要贡献者。王岐山、陈锡文和著名经济学家周其仁都师承杜润生,直接参与了上世纪80年代连续五个中央一号文件的起草。

  卓炯 曾任广东省社会科学院副院长,所著的《论社会主义商品经济》,成为新中国经济理论发展的十面旗帜之一。提出两个不等式,即“商品经济不等于资本主义,计划经济不等于社会主义”。

  1980年代初至今

  学术掌权人

  董辅礽 长期执掌中国社科院经济研究所,最早提出并一直坚持所有制改革成为中国经济改革的关键,门生众多,华生、田源是其高足。

  吴敬琏 整体改革理论主要贡献人,主张维护市场规则,保护草根阶层生计,被誉为“中国经济学界良心”,是媒体和公众眼中的学术明星。

  厉以宁 国有企业股份制改革理论主要贡献人,主持了《证券法》和《证券投资基金法》的起草工作。

  刘国光 在上世纪八十年代提出“稳中求进”的改革思路,他的开创性贡献主要集中于社会主义再生产理论、宏观经济管理、中国经济发展、中国经济体制改革等方面。

  茅于轼 中国民间经济学者的重要代表。他参与创办的天则经济研究所,聚集了张曙光、盛洪、樊纲、汪丁丁等一批实力派经济学家,“已经走出了一条民间开展学术研究的道路”。

  成思危 为我国新兴的风险投资业做出了奠基性贡献,业内人称“中国风险投资之父”。

  杨小凯 最突出的贡献是提出新兴古典经济学与超边际分析方法和理论,获得了世界级的成就和同行的推崇。杨小凯曾经被两次提名诺贝尔经济学奖(2002年和2003年)。

  张五常 国际知名经济学家,新制度经济学和现代产权经济学的创始人之一。他以《佃农理论》和《蜜蜂的神话》两篇文章享誉学界。

  1980年代中至今

  学术明星

  周小川 中国人民银行行长。上个世纪八十年代,从事经济体制改革的政策分析及许多经济课题的研究工作。1986年出任国务院体改方案领导小组成员,并兼任中国经济体制改革研究所副所长,为国务院高层担任智囊。

  张维迎 价格双轨制理论主要贡献人。在他还是何炼成硕士研究生的时候,在《中国青年报》发表了《为钱正名》一文,开始他备受批评的学术之旅。但他备受茅于轼赏识。

  周其仁 1980年代初,曾跟随杜润生进行学术调研与中央文件的起草。他被称为中国经济学家中最出色的演讲家,“当代中国经济学家中,周其仁挨骂最少”。

  林毅夫 2008年2月4日,林毅夫担任世行首席经济学家兼负责发展经济学的高级副行长,也是国际经济学期刊中发表论文最多的中国大陆经济学家之一。

  京城四少 中国经济学四小龙,指钟朋荣、樊纲、魏杰、刘伟四个人。

  华生 价格双轨制理论主要贡献人,被称为中国最有财的经济学家。董辅的高足。

  温铁军 中国人民大学农业与农村发展学院院长。早在1985年左右他提出“三农”问题的研究思路。自述对自己学术影响最大的两位经济学家:一位是自己的博士导师杜润生;一位是吴敬琏。

  1990年代初至今

  学术名家

  张曙光 北京天则所学术委员会主席,典型的改革一代经济学家。在改革的主题被调控的声音取代之后,他仍然坚持市场化改革的呼声。他不求献策成功,只求能够发出不同声音。

  陈志武(微博) 2006年2月,美国《华尔街电讯》公布了一份十大华人经济学家的榜单,陈志武名列其中。

  许小年(微博) 目前商业论坛最受欢迎的发言人、演讲家。他的一篇关于中国证券市场研究的论文被吴敬琏推荐,获得了当年的中国经济学最高奖—“孙冶方经济学奖”。

  巴曙松(微博) 国务院发展研究中心金融研究所副所长,主要研究领域为金融机构风险管理与金融市场监管。

  汪丁丁 北大教授,主要研究与教学领域:发展经济学、制度经济学、宏观经济学、数理经济学、经济学哲学。长期以来倡导“个体生命的自由”。

  邹恒甫 张培刚的学生曾启贤的弟子,热心经济学教育,与董辅、杨小凯交往密切。曾因被北大光华管理学院下课,与张维迎交恶,但被郎咸平盛赞为“浮躁喧嚣的经济学和教育界的一个传奇”。

  赵晓 《有教堂的市场经济与无教堂的市场经济》一文,开创了中国大陆改革开放以来市场伦理研究的先河。

  胡鞍钢 中国科学院和清华大学教授、国情研究中心主任,是一流的政策智库成员。他同时任供政府高级官员阅读的参考刊物《中国国情研究报告》主编。

  胡祖六 哈佛几大经济学家的弟子身份,博士毕业的胡祖六已很自然地进入世界经济管理的核心圈子。1996年,胡祖六已经是瑞士达沃斯世界经济论坛(微博)首席经济学家。他成为中国经济学人走向世界的象征之一。

  易宪容(微博) 中国社科院金融研究所研究员。作为一位以“敢言”著称的学者,易宪容的辞职在网络上引起了较大反响,被称为“房地产平民代言人”。

  郎咸平 作为公司治理和金融专家,2004年,郎咸平用最为传统的财务分析方法,痛陈国企改革中的国有资产流失弊病,引起巨大的影响,被称为“郎旋风”。

  李稻葵 清华大学经济管理学院金融系主任。因长期评论股市和房地产而被大众熟悉。

  谢国忠 1997年加入摩根士丹利,任亚太区经济学家。2007年离开摩根士丹利。对房地产的集中评论,让他成为大众熟悉的经济学家。谢国忠赢得学界的广泛认可源自他在1997年亚洲金融危机爆发之前就预见到了陷阱。

  华生

  经济学家不需要神话

  在华生看来,到目前为止,他很少看到真正的讨论和争议。正常的学术争鸣应该是严肃、理性和深入展开的碰撞。

  华生 燕京华侨大学校长,第四届中国经济理论创新奖获得者。

  33岁时华生被评为首批“国家级有突出贡献的专家”。

  文|王与菡

  记者:作为“价格双轨制”的主要贡献人之一,你获得了第四届中国经济理论创新奖。你怎么评价这个奖项?

  华生:虽然过去也领过很多奖,但这个奖很特别。它是经济学界第一个用民主投票的形式来决定获奖者的奖项,是一种民主的体现,不在个人掌控范围内的奖项。中国经济理论创新奖的酝酿产生,脱离了小圈子的限制。先是包括来自全国各大院校的学者、媒体人和项目研究领头人的二百多名专家自由提名,然后经过两轮投票,最后才产生了获奖者。从另一个方面讲,这个奖项脱离了常规体制,尤其在中国民主制度艰难前行的现在,把这个奖项的形态从经济学领域推广到整个社会,也非常具有启示性。

  记者:改革开放三十多年来,经济学家在其中起到什么作用?

  华生:以经济建设为中心的经济体制改革让经济学家在中国如鱼得水,如日中天。这其中,对于中国经济学界来说,是破旧逐新的过程。这个行业里的人边学边用,再到后来上个世纪九十年代一批批经济学专业留学生的归国,更加壮大了这个行业的体量。在现今中国经济的转型中,社会发展对这门学科的要求越来越高,虽然中国经济学的发展是一个向西方学习和借鉴的过程,但这个国家跟西方不同,即使是现今的西方社会也远远没有做到。能用理论模型解决现实经济问题,所以才有金融海啸和欧债危机。我国经济学领域内的人自然更无法用西方现成的学术模型来做中国社会转型期的研究。

  记者:你从一度的学术中心离开经商,有过心理落差吗?

  华生:落差当然有。从身处经济改革前沿,因为环境被迫成为个体户,这么大的改变肯定需要根本调整。我从商之初,跟很多知识分子下海一样有不适应。凭直觉办过餐厅,这种体验和做经济学研究完全不一样。做学术研究是在前人理论基础上,再搭一块砖,是钻牛角尖的专门家、学问家;而做企业要有综合素质、能带队伍,还懂得市场判断,能够承担风险。不过我现在不能算企业家,要算也只能算是最懒的企业家,我一年也难得去下属公司转一圈。不过,在实践中摸索出来的企业管理机制帮助了我。

  记者:对于中国的经济学发展,这几年你思考最多的问题是什么?

  华生:经济学家圈子,其实可以分作两个不同的领域。虽然都叫经济学,但里面包括了投行、券商等等。另外是在学术单位、研究所和大学,纯粹一点做理论研究的学者。但今天的这种形势与上世纪八十年代已经不同,二者差异正在越变越小。因为利益上的导向正在变强。以前捧着铁饭碗,做理论研究,基本是纯学术,今天这些人经受着各种利益诱惑,出现在各个会场,成为学术明星。他们参加不同团体或利益集团举办的峰会、论坛,自然会有发言或方向上的偏向。而且这样一来,还会有多少时间研究呢。当然现在社会对这个群体也有一个误解,对于经济学家,更多地应该从专业性上来判断,而不是想像着他们在各方面,从学术、道德至人品都尽善尽美。经济学家不需要神话。

  记者:对国内经济学上的学术争鸣,你怎么看?

  华生:国内经济学界的争鸣并不多。到目前为止,我很少看到真正的讨论和争议。正常的学术争鸣应该是严肃、理性和深入展开的碰撞。现在更多的是对某一件事情的争论,就事论事,而且是各说各话,达不到学术争鸣的程度。比如收入分配是社会转型的大问题,这样的争论对政府决策和对社会的影响是有意义的。但是并没有真正的讨论和交锋。这跟国内学术本峰的组织、跟时代和外界的诱惑无不有关。做吸引外界眼球的人,本身不是不好,但偏离了研究的专业性和中立性,就是问题所在。

  记者:谈谈你近年来的学术研究方向。

  华生:我的研究重点在机制设计领域。2007年诺贝尔经济学奖颁发的就是这个领域。机制设计在中国的应用还处于刚开始。在这个转型期,要想改变,除了要有目标,过渡的方式就是要用设计机制来完成。其实,八十年代的价格双轨制也是机制设计的一种,作为一种过渡性机制,从1985年到1993年,为期7年,在计划经济到市场经济的转变中,没有出现大的动荡,说明这个机制设计是成功的。后来的国企、 国有资产管理的体制同样如此,从1986年开始讨论到2003年成立国资委,也是一种机制设计。

  毛振华

  公开公正,不搞圈子

  令毛振华欣慰的是,组委会的行动释放了最大的诚意和善意,做到评奖公开公正,不是搞学术门户。

  毛振华 董辅礽经济科学发展基金会理事长、中国经济理论创新奖组委会执行主席。

  曾在政府部门从事经济研究工作,1992年创办中国诚信信用管理有限公司。

  文|李军奇

  记者:既然是在追思怀念董辅的大会倡议的奖项,为什么没有以董辅的名字命名“中国经济理论创新奖”?

  毛振华:这个奖项,确实是以董辅经济科学发展基金会发起的,但同时我们联合了北大、人大、武大、上海交大等学术结构,动员了全国的经济学家,要对一个时代的一批经济学家颁发是“中国经济理论”的创新奖。如果以一个经济学家的名字命名奖项,容易出问题,譬如代表性不够广泛。董辅是中国经济学大家,学术成就独树一帜,他有自己的学术观点和学术轨迹。每个经济学家有自己学术上的特点,大家并非都是一致的。再说基金会也不是弘扬董辅他个人的学术思想,基金会是个公益事业,要推动整个中国经济学的繁荣。

  记者:赞助这个奖项的基本上是董辅的学生,你的师兄弟,你不怕别人有意见?

  毛振华:组委会成员有很多经济学大家,二百多经济学界人士参与投票,参加赞助的,只是服务组委会。即使组委会,包括我,也是有一票的权利。这是一个公平公开的公益平台,评上谁就是谁,相信中国经济学家的共识。

  记者:这个奖项2008年颁发了第一届,刚开始,学界支持吗?经过四届评选,有什么变化?

  毛振华:一开始就得到很多老师的支持与鼓励,如厉以宁、江平、萧灼基他们。一些和董辅有不同学术观点的经济学家,还在观察。观察我们这个奖,是不是真正做到公开公正,是不是真正的“中国经济理论”的创新奖,会不会是某个小圈子搞的评奖。我们的行动释放了最大的诚意和善意,做到评奖公平公正,不是搞学术门户,给出了积极的正面答案,确实在推动学术发展,赢得了广泛的信任和支持。越来越多的经济学家后来都参与进来了。现在于光远、厉以宁、刘国光、吴敬琏老师都是我们评委会的名誉主席。中国经济理论创新奖,基本成了年度经济学界的盛事。

  记者:怎么保障投票的民主与公平?

  毛振华:中国经济理论创新奖评选采取专家推荐、广泛参与、公开评选的方式进行。奖项第一阶段,是候选理论的征集与候选理论的网上公示。可以是他荐,也可以是自荐。第二阶段,二百多位专家投票,选三项重要经济理论。第三阶段,投票计票。公开计票,现场有公证员监督。每个投票人,都只有一票,包括我。投票人可以备查。

  记者:四届评选,投票结果有争议吗?

  毛振华:有啊。有的奖颁出来了,大家还争议:这是个学问吗?这不是外国经济学的翻版嘛。这不是一个经济政策嘛。譬如农村联产承包责任制,看似政策,但那肯定是有理论基础的。对我们来说,经济学从来是有争议的。还有一个很有名的经济学家,他只投一个人,第一轮他要投的人被拿下,第二轮他继续投这个人。

  记者:评审专家的学术成果也可以参与评奖?

  毛振华:可以,例如获得第二届创新奖的厉以宁老师的国有企业股份制改革理论,厉老师可以参加第一轮投票;但他的理论进入第二轮评选,当事人就要回避,没有投票权。

  记者:为什么想要做这个奖项?

  毛振华:中国经济学家是为中国的改革和发展做出了贡献,这是他们应该得到的,我们必须要进行弘扬。不过有些评奖,只是圈子里的行为,评奖专家搞莫名其妙的审查。我们就想搞一个更有公信力的奖项,推动经济学界的交流与繁荣,推动学术民主。

  我们的奖项是颁给十年前的经济理论创新者。从我们得到的推荐和成果来看,也反映出了得到奖励的一定是给中国的经济发展和中国改革推动起到了实际的推进作用的人,这项工作很有挑战性,我也能感觉到自豪与骄傲!

  记者:你最大的愿望是什么?

  毛振华:做一个好老师,培养出对中国比较了解,有很好的理论功底,对国家和社会有影响有抱负的综合型人才。

  燕京华侨大学校长 华生

  武汉大学经济与管理学院院长 陈继勇

  董辅礽经济科学发展基金会理事长 毛振华

  泰康人寿股份有限公司董事长 陈东升

  北京大学光华管理学院名誉院长 厉以宁

  中国人民大学经济学院院长 杨瑞龙(微博)

  北京大学经济学院院长 孙祁祥

  北京大学校长助理 张维迎

how_to_install_virtualenv

https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001432712108300322c61f256c74803b43bfd65c6f8d0d0000

which python
which python3
1 #创建python2.7虚拟环境
2 virtualenv -p /usr/bin/python2.7 ENV2.7
3
4 #创建python3.4虚拟环境
5 virtualenv -p /usr/local/bin/python3.4 ENV3.4

在开发Python应用程序的时候,系统安装的Python3只有一个版本:3.4。所有第三方的包都会被pip安装到Python3的site-packages目录下。

如果我们要同时开发多个应用程序,那这些应用程序都会共用一个Python,就是安装在系统的Python 3。如果应用A需要jinja 2.7,而应用B需要jinja 2.6怎么办?

这种情况下,每个应用可能需要各自拥有一套“独立”的Python运行环境。virtualenv就是用来为一个应用创建一套“隔离”的Python运行环境。

首先,我们用pip安装virtualenv:

$ pip3 install virtualenv
然后,假定我们要开发一个新的项目,需要一套独立的Python运行环境,可以这么做:

第一步,创建目录:

Mac:~ michael$ mkdir myproject
Mac:~ michael$ cd myproject/
Mac:myproject michael$
第二步,创建一个独立的Python运行环境,命名为venv:

Mac:myproject michael$ virtualenv –no-site-packages venv
Using base prefix ‘/usr/local/…/Python.framework/Versions/3.4’
New python executable in venv/bin/python3.4
Also creating executable in venv/bin/python
Installing setuptools, pip, wheel…done.
命令virtualenv就可以创建一个独立的Python运行环境,我们还加上了参数–no-site-packages,这样,已经安装到系统Python环境中的所有第三方包都不会复制过来,这样,我们就得到了一个不带任何第三方包的“干净”的Python运行环境。

新建的Python环境被放到当前目录下的venv目录。有了venv这个Python环境,可以用source进入该环境:

Mac:myproject michael$ source venv/bin/activate
(venv)Mac:myproject michael$
注意到命令提示符变了,有个(venv)前缀,表示当前环境是一个名为venv的Python环境。

下面正常安装各种第三方包,并运行python命令:

(venv)Mac:myproject michael$ pip install jinja2

Successfully installed jinja2-2.7.3 markupsafe-0.23
(venv)Mac:myproject michael$ python myapp.py

在venv环境下,用pip安装的包都被安装到venv这个环境下,系统Python环境不受任何影响。也就是说,venv环境是专门针对myproject这个应用创建的。

退出当前的venv环境,使用deactivate命令:

(venv)Mac:myproject michael$ deactivate
Mac:myproject michael$
此时就回到了正常的环境,现在pip或python均是在系统Python环境下执行。

完全可以针对每个应用创建独立的Python运行环境,这样就可以对每个应用的Python环境进行隔离。

virtualenv是如何创建“独立”的Python运行环境的呢?原理很简单,就是把系统Python复制一份到virtualenv的环境,用命令source venv/bin/activate进入一个virtualenv环境时,virtualenv会修改相关环境变量,让命令python和pip均指向当前的virtualenv环境。

小结
virtualenv为应用提供了隔离的Python运行环境,解决了不同应用间多版本的冲突问题。

Bullet Proofing Django Models

https://medium.com/@hakibenita/bullet-proofing-django-models-c080739be4e

We recently added a bank account like functionality into one of our products. During the development we encountered some textbook problems and I thought it can be a good opportunity to go over some of the patterns we use in our Django models.

This article was written in the order in which we usually address new problems:

  1. Define the business requirements.
  2. Write down a naive implementation and model definition.
  3. Challenge the solution.
  4. Refine and repeat.

A Bank Account
Business Requirements

  • Each user can have only one account but not every user must have one.
  • The user can deposit and withdraw from the account up to a certain amount.
  • The account balance cannot be negative.
  • There is a max limit to the user’s account balance.
  • The total amount of all balances in the app cannot exceed a certain amount.
  • There must be a record for every action on the account.
  • Actions on the account can be executed by the user from either the mobile app or the web interface and by support personnel from the admin interface.

Now that we have the business requirements we can start with a model definition.
Account Model

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# models.py

import uuid

from django.conf import settings
from django.db import models

class Account(models.Model):
class Meta:
verbose_name = 'Account'
verbose_name_plural = 'Accounts'

MAX_TOTAL_BALANCES = 10000000

MAX_BALANCE = 10000
MIN_BALANCE = 0

MAX_DEPOSIT = 1000
MIN_DEPOSIT = 1

MAX_WITHDRAW = 1000
MIN_WITHDRAW = 1

id = models.AutoField(
primary_key=True,
)
uid = models.UUIDField(
unique=True,
editable=False,
default=uuid.uuid4,
verbose_name='Public identifier',
)
user = models.OneToOneField(
settings.AUTH_USER_MODEL,
on_delete=models.PROTECT,
)
created = models.DateTimeField(
blank=True,
)
modified = models.DateTimeField(
blank=True,
)
balance = models.PositiveIntegerField(
verbose_name='Current balance',
)

Let’s break it down:

  • We use two unique identifiers — A private identifier which is an auto generated number (id) and a public id which is a uuid (uid). It’s a good idea to keep enumerators private — they expose important information about our data such as how many accounts we have and we don’t want that.
  • We use OneToOneField for the user. It’s like a ForeignKey but with a unique constraint. This ensures a user cannot have more than one account.
  • We set on_delete=models.PROTECT. Starting with Django 2.0 this argument will be mandatory. The default is CASCADE — when the user is deleted the related account is deleted as well. In our case this doesn’t make sense — imagine the bank “deleting your money” when you close an account. Setting on_delete=models.PROTECT will raise an IntegrityError when attempting to delete a user with an account.
  • You probably noticed that the code is very… “vertical”. This is not just because Medium has such poor support for source code — we write like that because it makes git diffs look nicer.

Account Action Model

Now that we have an account model we can create a model to log actions made to the account:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# models.py

class Action(models.Model):
class Meta:
verbose_name = 'Account Action'
verbose_name_plural = 'Account Actions'

ACTION_TYPE_CREATED = 'CREATED'
ACTION_TYPE_DEPOSITED = 'DEPOSITED'
ACTION_TYPE_WITHDRAWN = 'WITHDRAWN'
ACTION_TYPE_CHOICES = (
(ACTION_TYPE_CREATED, 'Created'),
(ACTION_TYPE_DEPOSITED, 'Deposited'),
(ACTION_TYPE_WITHDRAWN, 'Withdrawn'),
)

REFERENCE_TYPE_BANK_TRANSFER = 'BANK_TRANSFER'
REFERENCE_TYPE_CHECK = 'CHECK'
REFERENCE_TYPE_CASH = 'CASH'
REFERENCE_TYPE_NONE = 'NONE'
REFERENCE_TYPE_CHOICES = (
(REFERENCE_TYPE_BANK_TRANSFER, 'Bank Transfer'),
(REFERENCE_TYPE_CHECK, 'Check'),
(REFERENCE_TYPE_CASH, 'Cash'),
(REFERENCE_TYPE_NONE, 'None'),
)

id = models.AutoField(
primary_key=True,
)
user_friendly_id = models.CharField(
unique=True,
editable=False,
max_length=30,
)
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.PROTECT,
help_text=’User who performed the action.’,
)
created = models.DateTimeField(
blank=True,
)
account = models.ForeignKey(
Account,
)
type = models.CharField(
max_length=30,
choices=ACTION_TYPE_CHOICES,
)
delta = models.IntegerField(
help_text=‘Balance delta.',
)
reference = models.TextField(
blank=True,
)
reference_type = models.CharField(
max_length=30,
choices=REFERENCE_TYPE_CHOICES,
default=REFERENCE_TYPE_NONE,
)
comment = models.TextField(
blank=True,
)

# Fields used solely for debugging purposes.

debug_balance = models.IntegerField(
help_text='Balance after the action.',
)

What do we have here?

  • Each record will hold a reference to the associated balance and the delta amount. A deposit of 100$ will have a delta of 100$, and a withdrawal of 50$ will have a delta of -50$. This way we can sum the deltas of all actions made to an account and get the current balance. This is important for validating our calculated balance.
  • We follow the same pattern of adding two identifiers — a private and a public one. The difference here is that reference numbers for actions are often used by users and support personnel to identify a specific action over the phone or in emails. A uuid is not user friendly — it’s very long and it’s not something users are used to see. I found a nice implementation of user-friendly ID’s in django-invoice.
  • Two of the fields are only relevant for one type of action, deposit — reference and reference type. There are a lot of ways to tackle this issue — table inheritance and down casting, JSON fields, table polymorphism and the list of overly complicated solutions goes on. In our case we are going to use a sparse table.

Note about the design: Maintaining calculated fields in the model is usually bad design. Calculated fields such as the account’s balance should be avoided whenever possible.

However, in our “real life“ implementation there are additional action types and thousands of actions on each account — we treat calculated attribute as an optimization. Maintaining state poses some interesting challenges and we thought it can serve the purpose of this post so we decided to present it as well.
Challenges
Multiple Platforms

We have three client applications we need to support:

  • Mobile app — use an API interface to manage the account.
  • Web client — can use either an API interface (if we have some sort of SPA) or good old server side rendering with Django forms.
  • Admin interface — uses Django’s admin module with Django forms.

Our motivation is to keep things DRY and self contained as possible.
Validation

We have two types of validations hiding in the business requirements:

Input validation such as “amount must be between X and Y”, “balance cannot exceed Z”, etc — these types of validation are well supported by Django and can usually be expressed as database constraints or django validations.

The second validation is a bit more complicated. We need to ensure the total amount of all balances in the entire system does not exceed a certain amount. This forces us to validate an instance against all other instances of the model.
Atomicity

Race conditions are a very common issue in distributed systems and ever more so in models that maintain state such as bank account (you can read more about race conditions in Wikipedia).

To illustrate the problem consider an account with a balance of 100$. The user connects from two different devices at the exact same time and issue a withdraw of 100$. Since the two actions were executed at the exact same time it is possible that both of them get a current balance of 100$. Given that both session see sufficient balance they will both get approved and update the new balance to 0$. The user withdrawn a total of 200$ and the current balance is now 0$ — we have a race condition and we are down 100$.
Logging / History

The log serves two purposes:

  • Log and Audit — Information about historical actions — dates, amounts, users etc.
  • Check Consistency — We maintain state in the model so we want to be able to validate the calculated balance by aggregating the action deltas.

The history records must be 100% immutable.
The Naive Implementation

Let’s start with a naive implementation of deposit (this is not a good implementation):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Account(models.Model):

...

def deposit(self, amount, deposited_by, asof):
assert amount > 0

if not self.MIN_DEPOSIT <= amount <= self.MAX_DEPOSIT:
raise InvalidAmount(amount)

if self.balance + amount > self.MAX_BALANCE:
raise ExceedsLimit()

total = Account.objects.aggregate(
total=Sum('balance')
)['total']
if total + amount > self.MAX_TOTAL_BALANCES:
raise ExceedsLimit()

action = self.actions.create(
user=deposited_by,
type=Action.ACTION_TYPE_DEPOSITED,
delta=amount,
asof=asof,
)

self.balance += amount
self.modified = asof

self.save()

And let’s add a simple endpoint for it using DRF @api_view:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# api.py


from django.db.models import transaction


@api_view('POST')
def deposit(request):
try:
amount = int(request.data['amount'])
except (KeyError, ValueError):
return Response(status=status.HTTP_400_BAD_REQUEST)

with transaction.atomic():
try:
account = (
Account.objects
.select_for_update()
.get(user=request.user)
)
except Account.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)

try:
account.deposit(
amount=amount,
deposited_by=request.user,
asof=timezone.now(),
)
except (ExceedsLimit, InvalidAmount):
return Response(status=status.HTTP_400_BAD_REQUEST)

return Response(status=status.HTTP_200_OK)

So what is the problem?

  • Locking the account — An instance cannot lock itself because it had already been fetched. We gave up control over the locking and fetching so we have to trust the caller to properly obtain a lock — this is very bad design. Don’t take my word for it, let’s take a glimpse at Django’s design philosophy:

  • Loose coupling
    A fundamental goal of Django’s stack is loose coupling and tight cohesion. The various layers of the framework shouldn’t “know” about each other unless absolutely necessary.

So is it really the business of our API, forms and django admin to fetch the account for us and obtain a proper lock? I think not.

  1. Validation — The account has to validate itself against all other accounts — this just feels awkward.
    A Better Approach

We need to hook into the process before the account is fetched (to obtain a lock) and in a place where it makes sense to validate and process more than one account.

Let’s start with a function to create an Action instance and write it as a classmethod:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# models.py

from django.core.exceptions import ValidationError

class Action(models.Model):

@classmethod
def create(
cls,
user,
account,
type,
delta,
asof,
reference=None,
reference_type=None,
comment=None,
):
"""Create Action.

user (User):
User who executed the action.
account (Account):
Account the action executed on.
type (str, one of Action.ACTION_TYPE_*):
Type of action.
delta (int):
Change in balance.
asof (datetime.datetime):
When was the action executed.
reference (str or None):
Reference number when appropriate.
reference_type(str or None):
Type of reference.
Defaults to "NONE".
comment (str or None):
Optional comment on the action.

Raises:
ValidationError

Returns (Action)
"""
assert asof is not None

if (type == cls.ACTION_TYPE_DEPOSITED and
reference_type is None):
raise errors.ValidationError({
'reference_type’: ‘required for deposit.',
})

if reference_type is None:
reference_type = cls.REFERENCE_TYPE_NONE

# Don't store null in text field.

if reference is None:
reference = ''

if comment is None:
comment = ''

user_friendly_id = generate_user_friendly_id()

return cls.objects.create(
user_friendly_id=user_friendly_id,
created=asof,
user=user,
account=account,
type=type,
delta=delta,
reference=reference,
reference_type=reference_type,
comment=comment,
debug_balance=account.balance,
)

What do we have here:

  • We used a classmethod that accepts all necessary data to validate and create the new instance. By not using the default manager’s create function (Action.objects.create) we encapsulate all the business logic in the creation process.
  • We easily introduced custom validation and raise proper ValidationError.
  • We accept the creation time as an argument. That might seem a bit strange at first glance — why not use the built in auto_time_add? For starters It’s much easier to test with predictable values. Second, as we are going to see in just a bit, we can make sure the modified time of the account is exactly the same as the action created time.

Before moving over to the implementation of the account methods let’s define custom exceptions for our Account module:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# errors.py

class Error(Exception):
pass

class ExceedsLimit(Error):
pass

class InvalidAmount(Error):
def __init__(self, amount):
self.amount = amount

def __str__(str):
return 'Invalid Amount: {}'.format(amount)

class InsufficientFunds(Error):
def __init__(self, balance, amount):
self.balance = balance
self.amount = amount

def __str__(self):
return 'amount: {}, current balance: {}'.format(
self.amount, self.balance)

We define a base Error class that inherits from Exception. This is something we found very useful and we use it a lot. A base error class allows us to catch all errors coming from a certain module:

1
2
3
4
5
6
from account.errors import Error as AccountError

try:
# action on account
except AccountError:
# Handle all errors from account

A similar pattern can be found in the popular requests package.

Let’s implement the method to create a new Account:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class Account(models.Model):

...

@classmethod
def create(cls, user, created_by, asof):
"""Create account.

user (User):
Owner of the account.
created_by (User):
User that created the account.
asof (datetime.datetime):
Time of creation.

Returns (tuple):
[0] Account
[1] Action
"""
with transaction.atomic():
account = cls.objects.create(
user=user,
created=asof,
modified=asof,
balance=0,
)

action = Action.create(
user=created_by,
account=account,
type=Action.ACTION_TYPE_CREATED,
delta=0,
asof=asof,
)

return account, action

Pretty straight forward — create the instance, create the action and return them both.

Notice how we accept asof here as well — modified, created and the action creation time are all equal — you cant do that with auto_add and auto_add_now.

Now to the business logic:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# models.py

@classmethod
def deposit(
cls,
uid,
deposited_by,
amount,
asof,
comment=None,
):
"""Deposit to account.

uid (uuid.UUID):
Account public identifier.
deposited_by (User):
Deposited by.
amount (positive int):
Amount to deposit.
asof (datetime.datetime):
Time of deposit.
comment(str or None):
Optional comment.

Raises
Account.DoesNotExist
InvalidAmount
ExceedsLimit

Returns (tuple):
[0] (Account) Updated account instance.
[0] (Action) Deposit action.
"""
assert amount > 0

with transaction.atomic():
account = cls.objects.select_for_update().get(uid=uid)

if not (cls.MIN_DEPOSIT <= amount <= cls.MAX_DEPOSIT):
raise errors.InvalidAmount(amount)

if account.balance + amount > cls.MAX_BALANCE:
raise errors.ExceedsLimit()

total = cls.objects.aggregate(total=Sum('balance'))['total']
if total + amount > cls.MAX_TOTAL_BALANCES:
raise errors.ExceedsLimit()

account.balance += amount
account.modified = asof

account.save(update_fields=[
'balance',
'modified',
])

action = Action.create(
user=deposited_by,
account=account,
type=Action.ACTION_TYPE_DEPOSITED,
delta=amount,
asof=asof,
)

return account, action

@classmethod
def withdraw(
cls,
uid,
withdrawn_by,
amount,
asof
comment=None,
):
"""Withdraw from account.

uid (uuid.UUID):
Account public identifier.
withdrawn_by (User):
The withdrawing user.
amount (positive int):
Amount to withdraw.
asof (datetime.datetime):
Time of withdraw.
comment (str or None):
Optional comment.

Raises:
Account.DoesNotExist
InvalidAmount
InsuficientFunds

Returns (tuple):
[0] (Account) Updated account instance.
[0] (Action) Withdraw action.
"""
assert amount > 0

with transaction.atomic():
account = cls.objects.select_for_update().get(uid=uid)

if not (cls.MIN_WITHDRAW <= amount <= cls.MAX_WITHDRAW):
raise InvalidAmount(amount)

if account.balance - amount < cls.MIN_BALANCE:
raise InsufficientFunds(amount, account.balance)

account.balance -= amount
account.modified = asof

account.save(update_fields=[
'balance',
'modified',
])

action = Action.create(
user=withdrawn_by,
account=account,
type=Action.ACTION_TYPE_WITHDRAWN,
delta=-amount,
asof=asof,
)

return account, action

We can start to see the pattern here:

  • Acquire a lock on the account using select_for_update. This will lock the account row in the database and make sure no one can update the account instance until the transaction is completed (either committed or rolled-back).
  • Perform validation checks and raise proper exceptions — raising an exception will cause the transaction to rollback.
    If all the validations passed update the state (current balance), set the modification time, save the instance and create the log (action).

So how does the model hold up to our challenges?

  • Multiple Platforms and Validation — We encapsulated all of our business logic including input and system wide validation inside the model method so consumers such as API, admin action or forms only need to handle exceptions and serialization / UI.
  • Atomicity — Each method obtains its own lock so there is no risk of race condition.
    Logging / History — We created an action model and made sure each function registers the proper action.

Profit!
Testing

Our app will be incomplete without proper tests. I previously wrote about class based testings — we are going to take a slightly different approach but still have a base class with utility functions:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# tests/common.py

class TestAccountBase:

DEFAULT = object()

@classmethod
def default(value, default_value):
return default_value if value is cls.DEFAULT else value

@classmethod
def setUpTestData(cls):
super().setUpTestData()

# Set up some default values
cls.admin = User.objects.create_superuser(
'Admin',
'admin',
'admin@testing.test',
)

cls.user_A = User.objects.create_user(
'user_A',
'user_A',
'A@testing.test',
)

@classmethod
def create(
cls,
user=DEFAULT,
created_by=DEFAULT,
asof=DEFAULT
):
user = cls.default(user, cls.user_A)
created_by = cls.default(created_by, cls.admin)
asof = cls.default(asof, timezone.now())

account, action = Account.create(user, created_by, asof)
return cls.account, action

def deposit(
self,
amount,
account=DEFAULT,
deposited_by=DEFAULT,
asof=DEFAULT,
comment=DEFAULT,
):
account = self.default(account, self.account)
deposited_by = self.default(deposited_by, self.admin)
asof = self.default(asof, timezone.now())
comment = self.default(comment, ‘deposit comment’)

self.account, action = Account.deposit(
uid=account.uid,
deposited_by=deposited_by,
amount=amount,
asof=asof,
)

self.assertEqual(action.type, Action.ACTION_TYPE_DEPOSITED)
self.assertIsNotNone(action.user_friendly_id)
self.assertEqual(action.created, asof)
self.assertEqual(action.delta, amount)
self.assertEqual(action.user, deposited_by)

return action

def withdraw(
self,
amount,
account=DEFAULT,
withdrawn_by=DEFAULT,
asof=DEFAULT,
comment=DEFAULT,
):
account = self.default(account, self.account)
withdrawn_by = self.default(withdrawn_by, self.admin)
asof = self.default(asof, timezone.now())
comment = self.default(comment, ‘withdraw comment’)

self.account, action = Account.withdraw(
uid=account.uid,
withdrawn_by=withdrawn_by,
amount=amount,
asof=asof,
)

self.assertEqual(action.type, Action.ACTION_TYPE_WITHDRAWN)
self.assertIsNotNone(action.user_friendly_id)
self.assertEqual(action.created, asof)
self.assertEqual(action.delta, amount)
self.assertEqual(action.user, withdrawn_by)

return action

To make testing easier to write we use utility functions to reduce the boilerplate of specifying the user, the account etc each time by providing default values and operating on self.account.

Lets use our base class to write some tests:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# tests/test_account.py

from unittest import mock
from django.test import TestCase

from .common import TestAccoutBase
from ..models import Account, Action
from ..errors import (
InvalidAmount,
ExceedsLimit,
InsuficientFunds,
)

class TestAccount(TestAccountBase, TestCase):

def setUp(self):
self.account, _ = cls.create()

def test_should_start_with_zero_balance(self):
self.assertEqual(self.account.balance, 0)

def test_should_deposit(self):
self.deposit(100)
self.assertEqual(self.account.balance, 100)
self.deposit(150)
self.assertEqual(self.account.balance, 250)

def test_should_fail_to_deposit_less_than_minimum(self):
with self.assertRaises(InvalidAmount):
self.deposit(Account.MIN_DEPOSIT - 1)
self.assertEqual(self.account.balance, 0)

def test_should_fail_to_deposit_more_than_maximum(self):
with self.assertRaises(InvalidAmount):
self.deposit(Account.MAX_DEPOSIT + 1)
self.assertEqual(self.account.balance, 0)

@mock.patch('account.models.Account.MAX_BALANCE', 500)
@mock.patch('account.models.Account.MAX_DEPOSIT', 502)
def test_should_fail_to_deposit_more_than_max_balance(self):
with self.assertRaises(ExceedsLimit):
self.deposit(501)
self.assertEqual(self.account.balance, 0)

@mock.patch('account.models.Account.MAX_BALANCE', 500)
@mock.patch('account.models.Account.MAX_DEPOSIT', 500)
@mock.patch('account.models.Account.MAX_TOTAL_BALANCES', 600)
def test_should_fail_when_exceed_max_total_balances(self):

# Exceed max total balances for the same account

self.deposit(500)
with self.assertRaises(ExceedsLimit):
self.deposit(500)
self.assertEqual(self.account.balance, 500)

# Exceed max total balances in other account

other_user = User.objects.create_user('foo', 'bar', 'baz')
other_account = self.create(user=other_user)

with self.assertRaises(ExceedsLimit):
self.deposit(200, account=other_account)
self.assertEqual(other_account.balance, 0)

def test_should_withdraw(self):
self.deposit(100)
self.withdraw(50)
self.assertEqual(self.account.balance, 50)
self.withdraw(30)
self.assertEqual(self.account.balance, 20)

def test_should_fail_when_insufficient_funds(self):
self.deposit(100)
with self.assertRaises(InsufficientFunds):
self.withdraw(101)
self.assertEqual(self.account.balance, 100)

Final Words

The classmethod approach has proved itself in our development for quite some time now. We found that it provides the necessary flexibility, readability and testability with very little overhead.

In this article we presented two common issues we encounter frequently — validation and concurrency. This method can be extended to handle access control (permissions) and caching (we have total control over the fetch, remember?), performance optimization (use select_related and update_fields…), audit and monitoring and additional business logic.

We usually support several interfaces for each model — admin interface for support, API for mobile and SPA clients, and a dashboard. Encapsulating the business logic inside the model reduced the amount of code duplication and required tests which leads to overall quality code that is easy to maintain.

In a follow up post I (might) present the admin interface for this model with some neat tricks (such as custom actions, intermediate pages etc) and possibly an RPC implementation using DRF to interact with the account as an API.

How to manage concurrency in Django models

https://medium.com/@hakibenita/how-to-manage-concurrency-in-django-models-b240fed4ee2

The days of desktop systems serving single users are long gone — web applications nowadays are serving millions of users at the same time. With many users comes a wide range of new problems — concurrency problems.

In this article I’m going to present two approaches for managing concurrency in Django models.
Photo by Denys Nevozhai
The Problem

To demonstrate common concurrency issues we are going to work on a bank account model:

1
2
3
4
5
6
7
8
9
10
11
class Account(models.Model):

id = models.AutoField(
primary_key=True,
)
user = models.ForeignKey(
User,
)
balance = models.IntegerField(
default=0,
)

To get started we are going to implement a naive deposit and withdraw methods for an account instance:

1
2
3
4
5
6
7
8
9
10
def deposit(self, amount):
self.balance += amount
self.save()

def withdraw(self, amount):
if amount > self.balance:
raise errors.InsufficientFunds()

self.balance -= amount
self.save()

This seems innocent enough and it might even pass unit tests and integration tests on localhost. But, what happens when two users perform actions on the same account at the same time?

  1. User A fetches the account — balance is 100$.
  2. User B fetches the account — balance is 100$.
  3. User B withdraws 30$ — balance is updated to 100$ — 30$ = 70$.
  4. User A deposits 50$ — balance is updated to 100$ + 50$ = 150$.

What happened here?

User B asked to withdraw 30$ and user A deposited 50$ — we expect the balance to be 120$, but we ended up with 150$.
Why did it happen?

At step 4, when user A updated the balance, the amount he had stored in memory was stale (user B had already withdrawn 30$).

To prevent this situation from happening we need to make sure the resource we are working on is not altered while we are working on it.
Pessimistic approach

The pessimistic approach dictates that you should lock the resource exclusively until you are finished with it. If nobody else can acquire a lock on the object while you are working on it, you can be sure the object was not changed.

To acquire a lock on a resource we use a database lock for several reasons:

  • (relational) databases are very good at managing locks and maintaining consistency.
  • The database is the lowest level in which data is accessed — acquiring the lock at the lowest level will protect the data from other processes modifying the data as well. For example, direct updates in the DB, cron jobs, cleanup tasks, etc.
  • A Django app can run on multiple processes (e.g workers). Maintaining locks at the app level will require a lot of (unnecessary) work.

To lock an object in Django we use select_for_update.

Let’s use the pessimistic approach to implement a safe deposit and withdraw:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@classmethod
def deposit(cls, id, amount):
with transaction.atomic():
account = (
cls.objects
.select_for_update()
.get(id=id)
)

account.balance += amount
account.save()

return account

@classmethod
def withdraw(cls, id, amount):
with transaction.atomic():
account = (
cls.objects
.select_for_update()
.get(id=id)
)

if account.balance < amount:
raise errors.InsufficentFunds()

account.balance -= amount
account.save()

return account

What do we have here:

  1. We use select_for_update on our queryset to tell the database to lock the object until the transaction is done.
  2. Locking a row in the database requires a database transaction — we use Django’s decorator transaction.atomic() to scope the transaction.
  3. We use a classmethod instead of an instance method — to acquire the lock we need to tell the database to lock it. To achieve that we need to be the ones fetching the object from the database. When operating on self the object is already fetched and we don’t have any guaranty that it was locked.
  4. All the operations on the account are executed within the database transaction.

Let’s see how the scenario from earlier is prevented with our new implementation:

  1. User A asks to withdraw 30$:
    • User A acquires a lock on the account.
    • Balance is 100$.
  2. User B asks to deposit 50$:
    • Attempt to acquire lock on account fails (locked by user A).
    • User B waits for the lock to release.
  3. User A withdraw 30$ :
    • Balance is 70$.
    • Lock of user A on account is released.
  4. User B acquires a lock on the account.
    • Balance is 70$.
    • New balance is 70$ + 50$ = 120$.
  5. Lock of user B on account is released, balance is 120$.

Bug prevented!

What you need to know about select_for_update:

  • In our scenario user B waited for user A to release the lock. Instead of waiting we can tell Django not to wait for the lock to release and raise a DatabaseError instead. To do that we can set the nowait argument of select_for_update to True, …select_for_update(nowait=True).
  • Select related objects are also locked — When using select_for_update with select_related, the related objects are also locked.
  • For example, If we were to select_related the user along with the account, both the user and the account will be locked. If during deposit, for example, someone is trying to update the first name, that update will fail because the user object is locked.
  • If you are using PostgreSQL or Oracle this might not be a problem soon thanks to a new feature in the upcoming Django 2.0. In this version, select_for_update has an “of” option to explicitly state which of the tables in the query to lock.

I used the bank account example in the past to demonstrate common patterns we use in Django models. You are welcome to follow up in this article:
Bullet Proofing Django Models

We recently added a bank account like functionality into one of our products. During the development we encountered…
medium.com
Optimistic Approach

Unlike the pessimistic approach, the optimistic approach does not require a lock on the object. The optimistic approach assumes collisions are not very common, and dictates that one should only make sure there were no changes made to the object at the time it is updated.
How can we implement such a thing with Django?

First, we add a column to keep track of changes made to the object:

1
2
3
version = models.IntegerField(
default=0,
)

Then, when we update an object we make sure the version did not change:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
def deposit(self, id, amount):
updated = Account.objects.filter(
id=self.id,
version=self.version,
).update(
balance=balance + amount,
version=self.version + 1,
)

return updated > 0

def withdraw(self, id, amount):
if self.balance < amount:
raise errors.InsufficentFunds()

updated = Account.objects.filter(
id=self.id,
version=self.version,
).update(
balance=balance - amount,
version=self.version + 1,
)

return updated > 0

Let’s break it down:

  1. We operate directly on the instance (no classmethod).
  2. We rely on the fact that the version is incremented every time the object is updated.
  3. We update only if the version did not change:
    • If the object was not modified since we fetched it than the object is updated.
    • If it was modified than the query will return zero records and the object will not be updated.
  4. Django returns the number of updated rows. If updated is zero it means someone else changed the object from the time we fetched it.

How is optimistic locking work in our scenario:

  1. User A fetch the account — balance is 100$, version is 0.
  2. User B fetch the account — balance is 100$, version is 0.
  3. User B asks to withdraw 30$:
    • Balance is updated to 100$ — 30$ = 70$.
    • Version is incremented to 1.
  4. User A asks to deposit 50$:
    • The calculated balance is 100$ + 50$ = 150$.
    • The account does not exist with version 0 -> nothing is updated.

What you need to know about the optimistic approach:

  • Unlike the pessimistic approach, this approach requires an additional field and a lot of discipline.
  • One way to overcome the discipline issue is to abstract this behavior. django-fsm implements optimistic locking using a version field as described above. django-optimistic-lock seem to do the same. We haven’t used any of these packages but we’ve taken some inspiration from them.
  • In an environment with a lot of concurrent updates this approach might be wasteful.
  • This approach does not protect from modifications made to the object outside the app. If you have other tasks that modify the data directly (e.g no through the model) you need to make sure they use the version as well.
  • Using the optimistic approach the function can fail and return false. In this case we will most likely want to retry the operation. Using the pessimistic approach with nowait=False the operation cannot fail — it will wait for the lock to release.

Which one should I use?

Like any great question, the answer is “it depends”:

  • If your object has a lot of concurrent updates you are probably better off with the pessimistic approach.
  • If you have updates happening outside the ORM (for example, directly in the database) the pessimistic approach is safer.
  • If your method has side effects such as remote API calls or OS calls make sure they are safe. Some things to consider — can the remote call take a long time? Is the remote call idempotent (safe to retry)?